blob: a08997c71e6b34a3aa79ca8a5382cf957512a502 [file] [log] [blame]
//#####################################################################
// Copyright 2004-2005, Ron Fedkiw, Joseph Teran, Eftychios Sifakis.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class COLLISION_PENALTY_FORCES
//#####################################################################
#ifndef __COLLISION_PENALTY_FORCES__
#define __COLLISION_PENALTY_FORCES__
#include "../Forces_And_Torques/SOLIDS_FORCES.h"
#include "../Grids/TETRAHEDRON_MESH.h"
#include "TETRAHEDRON_COLLISION_BODY.h"
#include "COLLISION_BODY_LIST_3D.h"
#include "../Utilities/LOG.h"
namespace PhysBAM
{
template<class T>
class COLLISION_PENALTY_FORCES: public SOLIDS_FORCES<T, VECTOR_3D<T> >
{
public:
using SOLIDS_FORCES<T, VECTOR_3D<T> >::particles;
COLLISION_BODY_LIST_3D<T>* collision_body_list;
ARRAY<bool> skip_collision_body;
ARRAY<int> check_collision;
ARRAY<VECTOR_3D<T> > collision_force;
ARRAY<SYMMETRIC_MATRIX_3X3<T> > collision_force_derivative;
T stiffness;
T separation_parameter;
T self_collision_reciprocity_factor;
int collision_body_list_id;
LIST_ARRAY<LIST_ARRAY<int> > partition_check_collision;
LIST_ARRAY<int> particle_to_check_collision_index;
COLLISION_PENALTY_FORCES (SOLIDS_PARTICLE<T, VECTOR_3D<T> >& particles_input)
: SOLIDS_FORCES<T, VECTOR_3D<T> > (particles_input), collision_body_list_id (0)
{
Set_Stiffness();
Set_Separation_Parameter();
Set_Self_Collision_Reciprocity_Factor();
}
~COLLISION_PENALTY_FORCES()
{}
void Set_Stiffness (const T stiffness_input = (T) 1e4)
{
stiffness = stiffness_input;
}
void Set_Separation_Parameter (const T separation_parameter_input = (T) 1e-4)
{
separation_parameter = separation_parameter_input;
}
void Set_Collision_Body_List (COLLISION_BODY_LIST_3D<T>& collision_body_list_input)
{
collision_body_list = &collision_body_list_input;
skip_collision_body.Resize_Array (collision_body_list->collision_bodies.m);
ARRAY<bool>::copy (false, skip_collision_body);
}
void Set_Boundary_Only_Collisions (TETRAHEDRON_MESH& 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();
for (int p = 1; p <= particles.array_size; p++) if ( (*tetrahedron_mesh.node_on_boundary) (p)) check_collision.Append_Element (p);
collision_force.Resize_Array (check_collision.m);
collision_force_derivative.Resize_Array (check_collision.m);
delete tetrahedron_mesh.node_on_boundary;
tetrahedron_mesh.node_on_boundary = old_node_on_boundary;
ARRAY<bool> particle_checked (particles.number);
particle_to_check_collision_index.Resize_Array (particles.number);
for (int p = 1; p <= check_collision.m; p++)
{
particle_checked (check_collision (p)) = true;
particle_to_check_collision_index (check_collision (p)) = p;
}
if (particles.particle_ranges)
{
partition_check_collision.Resize_Array (particles.particle_ranges->m);
for (int r = 1; r <= particles.particle_ranges->m; r++)
{
VECTOR_2D<int>& range = (*particles.particle_ranges) (r);
for (int p = range.x; p <= range.y; p++)
{
if (particle_checked (p)) partition_check_collision (r).Append_Element (p);
}
}
}
}
void Set_Collision_Body_List_ID (const int id)
{
collision_body_list_id = id;
}
void Set_Self_Collision_Reciprocity_Factor (const T self_collision_reciprocity_factor_input = (T) 2)
{
self_collision_reciprocity_factor = self_collision_reciprocity_factor_input;
}
void Check_Collision (const int particle)
{
check_collision.Append_Unique_Element (particle);
}
void Omit_Collision (const int particle)
{
int index;
if (check_collision.Find (particle, index)) check_collision.Remove_Index (index);
}
void Resize_Collision_Arrays_From_Check_Collision()
{
collision_force.Resize_Array (check_collision.m);
collision_force_derivative.Resize_Array (check_collision.m);
}
void Enforce_Definiteness (const bool enforce_definiteness_input)
{}
void Update_Position_Based_State()
{
LOG::Time ("UPBS (CPF)");
if (collision_body_list_id && collision_body_list->collision_bodies (collision_body_list_id)->body_type == COLLISION_BODY_3D<T>::TETRAHEDRON_TYPE)
{
TETRAHEDRON_COLLISION_BODY<T>* collision_body = (TETRAHEDRON_COLLISION_BODY<T>*) collision_body_list->collision_bodies (collision_body_list_id);
collision_body->tetrahedralized_volume.tetrahedron_hierarchy->Update_Boxes (collision_body->collision_thickness);
collision_body->tetrahedralized_volume.triangulated_surface->Update_Vertex_Normals();
}
LOG::Stop_Time();
}
void Update_Forces_And_Derivatives()
{
for (int p = 1; p <= check_collision.m; p++)
{
int index = check_collision (p);
collision_force (p) = VECTOR_3D<T>();
collision_force_derivative (p) = SYMMETRIC_MATRIX_3X3<T>();
for (int r = 1; r <= collision_body_list->collision_bodies.m; r++) if (!skip_collision_body (r))
{
int collision_body_particle_index = 0;
if (collision_body_list_id == r) collision_body_particle_index = index;
T phi_value;
int aggregate = -1;
VECTOR_3D<T> normal = collision_body_list->collision_bodies (r)->Implicit_Surface_Extended_Normal (particles.X (index), phi_value, aggregate, collision_body_particle_index);
if (phi_value <= 0)
{
collision_force (p) += stiffness * (-phi_value + separation_parameter) * normal;
if (collision_body_list_id == r) collision_force_derivative (p) -= self_collision_reciprocity_factor * stiffness * SYMMETRIC_MATRIX_3X3<T>::Outer_Product (normal);
else collision_force_derivative (p) -= stiffness * SYMMETRIC_MATRIX_3X3<T>::Outer_Product (normal);
}
else if (phi_value < collision_body_list->collision_bodies (r)->collision_thickness)
{
collision_force (p) += stiffness * separation_parameter * (T) exp (-phi_value / separation_parameter) * normal;
if (collision_body_list_id == r)
collision_force_derivative (p) -= self_collision_reciprocity_factor * stiffness * (T) exp (-phi_value / separation_parameter) * SYMMETRIC_MATRIX_3X3<T>::Outer_Product (normal);
else collision_force_derivative (p) -= stiffness * (T) exp (-phi_value / separation_parameter) * SYMMETRIC_MATRIX_3X3<T>::Outer_Product (normal);
}
}
}
}
void Add_Velocity_Independent_Forces (ARRAY<VECTOR_3D<T> >& F) const
{
LOG::Time ("AVIF (CPF)");
for (int p = 1; p <= check_collision.m; p++) F (check_collision (p)) += collision_force (p);
LOG::Stop_Time();
}
void Add_Force_Differential (const ARRAY<VECTOR_3D<T> >& dX, ARRAY<VECTOR_3D<T> >& dF) const
{
//LOG::Time("AFD (CPF)");
for (int p = 1; p <= check_collision.m; p++) dF (check_collision (p)) += collision_force_derivative (p) * dX (check_collision (p));
//LOG::Stop_Time();
}
void Add_Force_Differential (const ARRAY<VECTOR_3D<T> >& dX, ARRAY<VECTOR_3D<T> >& dF, const int partition_id) const
{
for (int i = 1; i <= partition_check_collision (partition_id).m; i++)
{
int particle = partition_check_collision (partition_id) (i), index = particle_to_check_collision_index (particle);
dF (particle) += collision_force_derivative (index) * dX (particle);
}
}
//#####################################################################
};
}
#endif