blob: 1f93c699104027e12e7f0c1223b7f5cfe48c9ed8 [file] [log] [blame]
//#####################################################################
// Copyright 2004, Zhaosheng Bao, Ronald Fedkiw, Geoffrey Irving, Sergey Koltakov, Igor Neverov, Eftychios Sifakis, Joseph Teran.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class DEFORMABLE_OBJECT_3D
//#####################################################################
#ifndef __DEFORMABLE_OBJECT_3D__
#define __DEFORMABLE_OBJECT_3D__
#include "DEFORMABLE_OBJECT.h"
#include "DEFORMABLE_OBJECT_COLLISIONS_3D.h"
#include "../Fracture/EMBEDDED_TETRAHEDRALIZED_VOLUME_BOUNDARY_SURFACE.h"
namespace PhysBAM
{
template<class T> class BODY_FORCES_3D;
template<class T> class DIAGONALIZED_FINITE_VOLUME_3D;
template<class T> class STRAIN_MEASURE_3D;
template<class T> class CONSTITUTIVE_MODEL_3D;
template<class T> class DIAGONALIZED_CONSTITUTIVE_MODEL_3D;
template<class T> class COLLISION_PENALTY_FORCES;
template<class T>
class DEFORMABLE_OBJECT_3D: public DEFORMABLE_OBJECT<T, VECTOR_3D<T> >
{
public:
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::particles;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::solids_forces;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::external_forces_and_velocities;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::id_number;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::print_diagnostics;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::print_residuals;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::Enforce_Definiteness;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::Save_Velocity;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::Restore_Velocity;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::Update_Position_Based_State;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::cfl_number;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::Add_Velocity_Independent_Forces;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::dX_full;
using DEFORMABLE_OBJECT<T, VECTOR_3D<T> >::R_full;
SEGMENTED_CURVE_3D<T>* segmented_curve;
TRIANGULATED_SURFACE<T>* triangulated_surface;
TETRAHEDRALIZED_VOLUME<T>* tetrahedralized_volume;
EMBEDDED_TETRAHEDRALIZED_VOLUME<T>* embedded_tetrahedralized_volume;
EMBEDDED_TETRAHEDRALIZED_VOLUME_BOUNDARY_SURFACE<T>* embedded_tetrahedralized_volume_boundary_surface;
DEFORMABLE_OBJECT_COLLISIONS_3D<T> collisions;
ARRAY<BODY_FORCES_3D<T>*> body_forces;
ARRAY<DIAGONALIZED_FINITE_VOLUME_3D<T>*> diagonalized_finite_volume_3d;
ARRAY<STRAIN_MEASURE_3D<T>*> strain_measure_3d;
ARRAY<COLLISION_PENALTY_FORCES<T>*> collision_penalty_forces;
private:
ARRAY<CONSTITUTIVE_MODEL_3D<T>*> constitutive_model_3d;
ARRAY<DIAGONALIZED_CONSTITUTIVE_MODEL_3D<T>*> diagonalized_constitutive_model_3d;
public:
bool use_nonembedded_self_collision;
DEFORMABLE_OBJECT_3D()
: segmented_curve (0), triangulated_surface (0), tetrahedralized_volume (0), embedded_tetrahedralized_volume (0),
embedded_tetrahedralized_volume_boundary_surface (0), use_nonembedded_self_collision (false)
{}
virtual ~DEFORMABLE_OBJECT_3D()
{
if (segmented_curve)
{
delete &segmented_curve->segment_mesh;
delete segmented_curve;
}
if (triangulated_surface)
{
delete &triangulated_surface->triangle_mesh;
delete triangulated_surface;
}
if (tetrahedralized_volume)
{
delete &tetrahedralized_volume->tetrahedron_mesh;
delete tetrahedralized_volume;
}
if (embedded_tetrahedralized_volume)
{
delete &embedded_tetrahedralized_volume->tetrahedralized_volume.tetrahedron_mesh;
delete &embedded_tetrahedralized_volume->tetrahedralized_volume;
delete embedded_tetrahedralized_volume;
}
delete embedded_tetrahedralized_volume_boundary_surface;
Delete_Forces();
}
void Allocate_Segmented_Curve()
{
assert (!segmented_curve);
segmented_curve = new SEGMENTED_CURVE_3D<T> (* (new SEGMENT_MESH), particles);
particles.Update_Velocity();
particles.Store_Mass();
}
void Allocate_Triangulated_Surface()
{
assert (!triangulated_surface);
triangulated_surface = new TRIANGULATED_SURFACE<T> (* (new TRIANGLE_MESH), particles);
particles.Update_Velocity();
particles.Store_Mass();
}
void Allocate_Tetrahedralized_Volume()
{
assert (!tetrahedralized_volume);
tetrahedralized_volume = new TETRAHEDRALIZED_VOLUME<T> (* (new TETRAHEDRON_MESH), particles);
particles.Update_Velocity();
particles.Store_Mass();
}
void Allocate_Embedded_Triangulated_Surface (const int hashtable_multiplier = 15, const T interpolation_fraction_threshold = 1e-4)
{}
void Allocate_Embedded_Tetrahedralized_Volume (const int hashtable_multiplier = 15, const T interpolation_fraction_threshold = 1e-4)
{
assert (!embedded_tetrahedralized_volume);
assert (!embedded_tetrahedralized_volume_boundary_surface);
embedded_tetrahedralized_volume = new EMBEDDED_TETRAHEDRALIZED_VOLUME<T> (* (new TETRAHEDRALIZED_VOLUME<T> (* (new TETRAHEDRON_MESH), particles)));
particles.Update_Velocity();
particles.Store_Mass();
embedded_tetrahedralized_volume->Initialize_Parents_To_Embedded_Particles_Hash_Table (hashtable_multiplier);
embedded_tetrahedralized_volume->Set_Interpolation_Fraction_Threshold (interpolation_fraction_threshold);
embedded_tetrahedralized_volume_boundary_surface = new EMBEDDED_TETRAHEDRALIZED_VOLUME_BOUNDARY_SURFACE<T> (*embedded_tetrahedralized_volume);
}
virtual void Initialize_Collision_Geometry()
{
if (segmented_curve) collisions.Initialize_Segmented_Curve (*segmented_curve);
else if (triangulated_surface) collisions.Initialize_Triangulated_Surface (*triangulated_surface);
else if (tetrahedralized_volume)
{
if (!tetrahedralized_volume->triangulated_surface) tetrahedralized_volume->Initialize_Triangulated_Surface();
collisions.Initialize_Triangulated_Surface (*tetrahedralized_volume->triangulated_surface);
}
else if (embedded_tetrahedralized_volume) collisions.Initialize_Triangulated_Surface (embedded_tetrahedralized_volume_boundary_surface->boundary_surface);
}
void Initialize_Object_Collisions (const bool collide_with_interior = false, const bool enforce_tangential_collision_velocity = false)
{
if (segmented_curve) collisions.Initialize_Object_Collisions (segmented_curve->particles, enforce_tangential_collision_velocity);
else if (triangulated_surface) collisions.Initialize_Object_Collisions (triangulated_surface->particles, enforce_tangential_collision_velocity);
else if (tetrahedralized_volume)
{
collisions.Initialize_Object_Collisions (tetrahedralized_volume->particles, enforce_tangential_collision_velocity);
if (!collide_with_interior)
{
TETRAHEDRON_MESH& tetrahedron_mesh = tetrahedralized_volume->tetrahedron_mesh;
LIST_ARRAY<bool>* old_node_on_boundary = tetrahedron_mesh.node_on_boundary;
tetrahedron_mesh.node_on_boundary = 0;
tetrahedron_mesh.Initialize_Node_On_Boundary();
ARRAY<bool>::exchange_arrays (collisions.check_collision, tetrahedron_mesh.node_on_boundary->array);
delete tetrahedron_mesh.node_on_boundary;
tetrahedron_mesh.node_on_boundary = old_node_on_boundary;
}
}
else if (embedded_tetrahedralized_volume)
{
collisions.Initialize_Object_Collisions (embedded_tetrahedralized_volume->tetrahedralized_volume.particles, enforce_tangential_collision_velocity);
if (collide_with_interior) assert (false);
}
}
void Allocate_Asynchronous_Time_Stepping()
{}
// Should be accelerated by using the triangle_hierarchy to eliminate tests on parts of the surface that aren't close to collision bodies.
int Adjust_Nodes_For_Collision_Body_Collisions (const T dt)
{
if (embedded_tetrahedralized_volume) return collisions.Adjust_Nodes_For_Collision_Body_Collisions (*embedded_tetrahedralized_volume, *embedded_tetrahedralized_volume_boundary_surface, dt);
else return collisions.Adjust_Nodes_For_Collision_Body_Collisions (dt);
}
void Restore_Self_Collision_Free_State()
{
collisions.Restore_Self_Collision_Free_State();
if (embedded_tetrahedralized_volume) // triangle_collisions only restores the boundary mesh, need to propagate this back to the tetrahedralized volume
{
for (int p = 1; p <= embedded_tetrahedralized_volume->tetrahedralized_volume.particles.number; p++)
{
embedded_tetrahedralized_volume->tetrahedralized_volume.particles.X (p) =
embedded_tetrahedralized_volume_boundary_surface->boundary_particles.X (p + embedded_tetrahedralized_volume->embedded_particles.number);
embedded_tetrahedralized_volume->tetrahedralized_volume.particles.V (p) =
embedded_tetrahedralized_volume_boundary_surface->boundary_particles.V (p + embedded_tetrahedralized_volume->embedded_particles.number);
}
for (int p = 1; p <= embedded_tetrahedralized_volume->tetrahedralized_volume.particles.number; p++) // THIS IS NEW!
{
embedded_tetrahedralized_volume->embedded_particles.X (p) = embedded_tetrahedralized_volume_boundary_surface->boundary_particles.X (p);
embedded_tetrahedralized_volume->embedded_particles.V (p) = embedded_tetrahedralized_volume_boundary_surface->boundary_particles.V (p);
}
}
}
void Disable_Finite_Volume_Damping()
{
for (int k = 1; k <= diagonalized_finite_volume_3d.m; k++) diagonalized_finite_volume_3d (k)->Use_Velocity_Dependent_Forces (false);
}
void Disable_Spring_Elasticity()
{}
template<class RW>
void Read_Static_Variables (const std::string& prefix, const int frame = -1)
{
char version;
bool has_segmented_curve, has_triangulated_surface, has_tetrahedralized_volume, has_embedded_tetrahedralized_volume, has_embedded_triangulated_surface = false;
std::string f = frame == -1 ? "" : STRING_UTILITIES::string_sprintf (".%d", frame);
std::istream* mesh_type_input = FILE_UTILITIES::Safe_Open_Input (prefix + "mesh_type" + f);
Read_Binary<RW> (*mesh_type_input, version, has_segmented_curve, has_triangulated_surface, has_tetrahedralized_volume, has_embedded_tetrahedralized_volume);
if (version == 2) Read_Binary<RW> (*mesh_type_input, has_embedded_triangulated_surface);
else if (version != 1)
{
std::cerr << "Unrecognized deformable object version number " << (int) version << std::endl;
exit (1);
}
delete mesh_type_input;
if (has_segmented_curve)
{
Allocate_Segmented_Curve();
FILE_UTILITIES::Read_From_File<RW> (prefix + "segment_mesh" + f, segmented_curve->segment_mesh);
}
if (has_triangulated_surface)
{
Allocate_Triangulated_Surface();
FILE_UTILITIES::Read_From_File<RW> (prefix + "triangle_mesh" + f, triangulated_surface->triangle_mesh);
}
if (has_tetrahedralized_volume)
{
Allocate_Tetrahedralized_Volume();
FILE_UTILITIES::Read_From_File<RW> (prefix + "tetrahedron_mesh" + f, tetrahedralized_volume->tetrahedron_mesh);
}
if (has_embedded_tetrahedralized_volume)
{
Allocate_Embedded_Tetrahedralized_Volume();
FILE_UTILITIES::Read_From_File<RW> (prefix + "embedded_tetrahedralized_volume" + f, *embedded_tetrahedralized_volume);
}
}
template<class RW>
void Read_Dynamic_Variables (const std::string& prefix, const int frame)
{
particles.template Read<RW> (prefix, frame);
if (embedded_tetrahedralized_volume) embedded_tetrahedralized_volume->embedded_particles.template Read<RW> (prefix + "embedded_surface_", frame);
}
template<class RW>
void Write_Static_Variables (const std::string& prefix, const int frame = -1) const
{
char version = 2;
std::string f = frame == -1 ? "" : STRING_UTILITIES::string_sprintf (".%d", frame);
FILE_UTILITIES::Write_To_File<RW> (prefix + "mesh_type" + f, version, segmented_curve != 0, triangulated_surface != 0, tetrahedralized_volume != 0, embedded_tetrahedralized_volume != 0, false);
if (segmented_curve) FILE_UTILITIES::Write_To_File<RW> (prefix + "segment_mesh" + f, segmented_curve->segment_mesh);
if (triangulated_surface) FILE_UTILITIES::Write_To_File<RW> (prefix + "triangle_mesh" + f, triangulated_surface->triangle_mesh);
if (tetrahedralized_volume) FILE_UTILITIES::Write_To_File<RW> (prefix + "tetrahedron_mesh" + f, tetrahedralized_volume->tetrahedron_mesh);
if (embedded_tetrahedralized_volume) // writes positions
{
FILE_UTILITIES::Write_To_File<RW> (prefix + "embedded_tetrahedralized_volume" + f, *embedded_tetrahedralized_volume);
FILE_UTILITIES::Write_To_File<RW> (prefix + "embedded_tetrahedralized_volume_boundary_surface" + f, embedded_tetrahedralized_volume_boundary_surface->boundary_surface);
}
}
template<class RW>
void Write_Dynamic_Variables (const std::string& prefix, const int frame) const
{
particles.template Write<RW> (prefix, frame);
if (embedded_tetrahedralized_volume) embedded_tetrahedralized_volume->embedded_particles.template Write<RW> (prefix + "embedded_surface_", frame);
}
//#####################################################################
void Delete_Forces();
void Update_Collision_Penalty_Forces_And_Derivatives();
void Advance_One_Time_Step (const T time, const T dt, const T cg_tolerance, const int cg_iterations, const bool perform_collision_body_collisions, const bool verbose);
void Advance_One_Time_Step_Semi_Implicit (const T time, const T dt, const bool perform_collision_body_collisions, const bool verbose);
void Advance_One_Time_Step_Quasistatic (const T time, const T dt, const T cg_tolerance, const int cg_iterations, const T newton_tolerance, const int newton_iterations, const bool use_partially_converged_result,
const bool verbose);
public:
int Add_Quasistatic_Neo_Hookean_Elasticity (TETRAHEDRALIZED_VOLUME<T>& tetrahedralized_volume, const T youngs_modulus = 3e6, const T poissons_ratio = .475, const bool verbose = true);
int Add_Quasistatic_Diagonalized_Linear_Finite_Volume (TETRAHEDRALIZED_VOLUME<T>& tetrahedralized_volume, const T youngs_modulus = 3e6, const T poissons_ratio = .475, const bool verbose = true,
const bool precompute_stiffness_matrix = false);
int Add_Quasistatic_Diagonalized_Neo_Hookean_Elasticity (TETRAHEDRALIZED_VOLUME<T>& tetrahedralized_volume, const T youngs_modulus = 3e6, const T poissons_ratio = .475, const T failure_threshold = .25,
const bool verbose = true, const bool precompute_stiffness_matrix = false);
int Add_Quasistatic_Diagonalized_Linear_Elasticity (TETRAHEDRALIZED_VOLUME<T>& tetrahedralized_volume, const T youngs_modulus = 3e6, const T poissons_ratio = .475, const bool verbose = true);
int Add_Diagonalized_Mooney_Rivlin (TETRAHEDRALIZED_VOLUME<T>& tetrahedralized_volume, const T mu_10 = (T) 6e4, const T mu_01 = (T) 2e4, const T kappa = (T) 6e4, const T Rayleigh_coefficient = .05,
const T failure_threshold = (T).25, const bool limit_time_step_by_strain_rate = true, const T max_strain_per_time_step = .1, const bool use_rest_state_for_strain_rate = true, const bool verbose = true);
int Add_Quasistatic_Diagonalized_Mooney_Rivlin (TETRAHEDRALIZED_VOLUME<T>& tetrahedralized_volume, const T mu_10 = (T) 6e4, const T mu_01 = (T) 2e4, const T kappa = (T) 6e4, const T failure_threshold = (T).25,
const bool verbose = true, const bool precompute_stiffness_matrix = false);
int Add_Diagonalized_Face (TETRAHEDRALIZED_VOLUME<T>& tetrahedralized_volume, const LIST_ARRAY<LIST_ARRAY<int> >& muscle_tets, const LIST_ARRAY<LIST_ARRAY<VECTOR_3D<T> > >& muscle_fibers,
const LIST_ARRAY<LIST_ARRAY<T> >& muscle_densities, LIST_ARRAY<T>& muscle_activations, const LIST_ARRAY<T>* peak_isometric_stress = 0, const T mu_10 = (T) 6e4, const T mu_01 = (T) 2e4, const T kappa = (T) 6e4,
const T Rayleigh_coefficient = (T).05, const T failure_threshold = (T).25, const bool limit_time_step_by_strain_rate = true, const T max_strain_per_time_step = (T).1,
const bool use_rest_state_for_strain_rate = true, const bool verbose = true);
int Add_Quasistatic_Diagonalized_Face (TETRAHEDRALIZED_VOLUME<T>& tetrahedralized_volume, const LIST_ARRAY<LIST_ARRAY<int> >& muscle_tets, const LIST_ARRAY<LIST_ARRAY<VECTOR_3D<T> > >& muscle_fibers,
const LIST_ARRAY<LIST_ARRAY<T> >& muscle_densities, LIST_ARRAY<T>& muscle_activations, int* single_activation_used_for_force_derivative = 0, const LIST_ARRAY<T>* peak_isometric_stress = 0,
DIAGONALIZED_CONSTITUTIVE_MODEL_3D<T> **face_constitutive_model = 0, const T mu_10 = (T) 6e4, const T mu_01 = (T) 2e4, const T kappa = (T) 6e4, const T failure_threshold = (T).25, const bool verbose = false);
//#####################################################################
};
}
#endif