blob: 350f3369289897caaf6c36d9d09668cf710e20cd [file] [log] [blame]
//#####################################################################
// Copyright 2004, Ron Fedkiw, Eran Guendelman, Geoffrey Irving, Andrew Selle, 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 SOLIDS_EVOLUTION_3D
//#####################################################################
#include "SOLIDS_EVOLUTION_3D.h"
#include "SOLIDS_FLUIDS_EXAMPLE.h"
#include "SOLIDS_PARAMETERS_3D.h"
#include "RIGID_BODY_PARAMETERS_3D.h"
#include "DEFORMABLE_BODY_PARAMETERS_3D.h"
#include "../Utilities/LOG.h"
#include "../Rigid_Bodies/RIGID_BODY_EVOLUTION_3D.h"
#include "../Rigid_Bodies/RIGID_BODY_COLLISIONS_3D.h"
using namespace PhysBAM;
//#####################################################################
// Destructor
//#####################################################################
template<class T> SOLIDS_EVOLUTION_3D<T>::
~SOLIDS_EVOLUTION_3D()
{
delete rigid_body_collisions;
delete rigid_body_evolution;
}
//#####################################################################
// Function Initialize_Deformable_Objects
//#####################################################################
template<class T> void SOLIDS_EVOLUTION_3D<T>::
Initialize_Deformable_Objects (const T frame_rate, const bool restart, const bool verbose_dt)
{
DEFORMABLE_BODY_PARAMETERS_3D<T>& deformable_body_parameters = solids_parameters.deformable_body_parameters;
for (int i = 1; i <= deformable_body_parameters.list.deformable_objects.m; i++)
if (deformable_body_parameters.list (i).embedded_tetrahedralized_volume)
{
deformable_body_parameters.list (i).embedded_tetrahedralized_volume->embedded_particles.Store_Mass();
deformable_body_parameters.list (i).embedded_tetrahedralized_volume->embedded_particles.Store_Velocity (!quasistatic);
deformable_body_parameters.list (i).embedded_tetrahedralized_volume->Update_Embedded_Particle_Masses();
deformable_body_parameters.list (i).embedded_tetrahedralized_volume->Update_Embedded_Particle_Positions();
if (!quasistatic) deformable_body_parameters.list (i).embedded_tetrahedralized_volume->Update_Embedded_Particle_Velocities();
deformable_body_parameters.list (i).embedded_tetrahedralized_volume->Initialize_Embedded_Sub_Elements_In_Parent_Element();
deformable_body_parameters.list (i).embedded_tetrahedralized_volume->Initialize_Embedded_Children();
deformable_body_parameters.list (i).embedded_tetrahedralized_volume->tetrahedralized_volume.tetrahedron_mesh.Initialize_Incident_Tetrahedrons();
deformable_body_parameters.list (i).embedded_tetrahedralized_volume->Initialize_Node_In_Tetrahedron_Is_Material();
}
deformable_body_parameters.list.Initialize_Object_Collisions (solids_parameters.collide_with_interior, solids_parameters.enforce_tangential_collision_velocity);
if (restart)
{
deformable_body_parameters.list.Update_Position_Based_State(); // some CFL's require this
if (!quasistatic) deformable_body_parameters.list.CFL (verbose_dt);
} // needs to be initialized before positions change
}
//#####################################################################
// Function Initialize_Rigid_Bodies
//#####################################################################
template<class T> void SOLIDS_EVOLUTION_3D<T>::
Initialize_Rigid_Bodies (const T frame_rate)
{
RIGID_BODY_PARAMETERS_3D<T>& rigid_body_parameters = solids_parameters.rigid_body_parameters;
if (!rigid_body_parameters.simulate) solids_evolution_callbacks->Update_Collision_Body_Positions_And_Velocities (time); // initialize object positions if not simulating
else
{
RIGID_BODY_COLLISIONS_3D<T>::Adjust_Bounding_Boxes (rigid_body_parameters.list.rigid_bodies);
// compute voxel size for spatial partition
T voxel_size = 0;
if (rigid_body_parameters.spatial_partition_based_on_scene_size)
{
VECTOR_3D<T> scene_box_size = RIGID_BODY_COLLISIONS_3D<T>::Scene_Bounding_Box (rigid_body_parameters.list.rigid_bodies).Size();
voxel_size = (T) one_third * (scene_box_size.x + scene_box_size.y + scene_box_size.z) / rigid_body_parameters.spatial_partition_number_of_cells;
}
else if (rigid_body_parameters.spatial_partition_based_on_object_size)
{
if (rigid_body_parameters.spatial_partition_with_max_size) voxel_size = RIGID_BODY_COLLISIONS_3D<T>::Maximum_Bounding_Box_Size (rigid_body_parameters.list.rigid_bodies);
else voxel_size = RIGID_BODY_COLLISIONS_3D<T>::Average_Bounding_Box_Size (rigid_body_parameters.list.rigid_bodies);
voxel_size *= 8;
} // just to make it bigger
// collisions
rigid_body_collisions = new RIGID_BODY_COLLISIONS_3D<T> (rigid_body_parameters.list.rigid_bodies, voxel_size);
if (rigid_body_parameters.use_collision_matrix) rigid_body_collisions->collision_manager.Use_Collision_Matrix();
rigid_body_collisions->verbose = verbose;
if (rigid_body_parameters.use_particle_partition)
{
rigid_body_collisions->intersections.Use_Particle_Partition (true, rigid_body_parameters.particle_partition_size, rigid_body_parameters.particle_partition_size,
rigid_body_parameters.particle_partition_size);
if (rigid_body_parameters.use_particle_partition_center_phi_test) rigid_body_collisions->intersections.Use_Particle_Partition_Center_Phi_Test();
}
if (rigid_body_parameters.use_triangle_hierarchy)
{
rigid_body_collisions->intersections.Use_Triangle_Hierarchy();
if (rigid_body_parameters.use_triangle_hierarchy_center_phi_test) rigid_body_collisions->intersections.Use_Triangle_Hierarchy_Center_Phi_Test();
if (rigid_body_parameters.use_edge_intersection) rigid_body_collisions->intersections.Use_Edge_Intersection();
}
// dynamics
rigid_body_evolution = new RIGID_BODY_EVOLUTION_3D<T> (rigid_body_parameters.list.rigid_bodies, *rigid_body_collisions);
rigid_body_evolution->Set_CFL_Number (solids_parameters.cfl);
rigid_body_evolution->Set_Max_Rotation_Per_Time_Step (rigid_body_parameters.max_rotation_per_time_step);
rigid_body_evolution->Set_Max_Linear_Movement_Fraction_Per_Time_Step (rigid_body_parameters.max_linear_movement_fraction_per_time_step);
rigid_body_evolution->Set_Minimum_And_Maximum_Time_Step (0, (T).1 / frame_rate);
if (rigid_body_parameters.artificial_maximum_speed) rigid_body_evolution->Set_Artificial_Maximum_Speed (rigid_body_parameters.artificial_maximum_speed);
rigid_body_evolution->collisions.Initialize_Data_Structures(); // Must be done before we check interpenetration statistics
// precompute normals - faster, but less accurate
//RIGID_BODY_COLLISIONS_3D<T>::Precompute_Normals(rigid_body_parameters.list.rigid_bodies);
// check for bad initial data
if (rigid_body_parameters.print_interpenetration_statistics) rigid_body_evolution->collisions.Print_Interpenetration_Statistics();
else if (!rigid_body_evolution->collisions.Check_For_Any_Interpenetration()) LOG::cout << "No initial interpenetration" << std::endl;
}
}
//#####################################################################
// Function Advance_To_Target_Time
//#####################################################################
template<class T> void SOLIDS_EVOLUTION_3D<T>::
Advance_To_Target_Time (const T target_time, const bool verbose_dt)
{
RIGID_BODY_PARAMETERS_3D<T>& rigid_body_parameters = solids_parameters.rigid_body_parameters;
if (!rigid_body_parameters.simulate)
{
Advance_Deformable_Bodies_To_Target_Time (target_time, verbose_dt);
return;
}
bool done = false;
for (int substep = 1; !done; substep++)
{
LOG::Push_Scope ("rigid body", "Rigid body substep %d", substep);
solids_evolution_callbacks->Update_Rigid_Body_Parameters (rigid_body_collisions->collision_manager, time);
rigid_body_evolution->collisions.Initialize_Data_Structures(); // call here to handle possibly changed number of rigid bodies
T dt_cfl = rigid_body_evolution->CFL (verbose_dt), dt = dt_cfl;
SOLIDS_FLUIDS_EXAMPLE<T>::Clamp_Time_Step_With_Target_Time (time, target_time, dt, done);
solids_evolution_callbacks->Update_Kinematic_Rigid_Body_States (dt, time);
if (verbose) LOG::cout << "rigid substep = " << substep << ", time = " << time << ", dt = " << dt << " (cfl = " << dt_cfl << ")" << std::endl;
// Rigid body states are saved in order to do interpolation
for (int i = 1; i <= rigid_body_parameters.list.rigid_bodies.m; i++) rigid_body_parameters.list.rigid_bodies (i)->Save_State (COLLISION_BODY_3D<T>::SOLIDS_EVOLUTION_RIGID_BODY_OLD_STATE, time);
LOG::Time ("advancing rigid bodies");
rigid_body_evolution->Advance_One_Time_Step (dt, time);
for (int i = 1; i <= rigid_body_parameters.list.rigid_bodies.m; i++) rigid_body_parameters.list.rigid_bodies (i)->Save_State (COLLISION_BODY_3D<T>::SOLIDS_EVOLUTION_RIGID_BODY_NEW_STATE, time + dt);
Advance_Deformable_Bodies_To_Target_Time (time + dt, verbose_dt);
for (int i = 1; i <= rigid_body_parameters.list.rigid_bodies.m; i++) rigid_body_parameters.list.rigid_bodies (i)->Restore_State (COLLISION_BODY_3D<T>::SOLIDS_EVOLUTION_RIGID_BODY_NEW_STATE);
solids_evolution_callbacks->Apply_Constraints (dt, time);
LOG::Pop_Scope();
}
}
//#####################################################################
// Function Advance_Deformable_Bodies_To_Target_Time
//#####################################################################
template<class T> void SOLIDS_EVOLUTION_3D<T>::
Advance_Deformable_Bodies_To_Target_Time (const T target_time, const bool verbose_dt)
{
int iteration = 0;
LOG::Push_Scope ("ADB", "ADB");
DEFORMABLE_BODY_PARAMETERS_3D<T>& deformable_body_parameters = solids_parameters.deformable_body_parameters;
if (!deformable_body_parameters.list.deformable_objects.m)
{
time = target_time;
solids_evolution_callbacks->Postprocess_Solids_Substep (time, 1);
LOG::Pop_Scope(); // from ADB
return;
}
// prepare for force computation
deformable_body_parameters.list.Update_Time_Varying_Material_Properties (time);
deformable_body_parameters.list.Update_Position_Based_State();
Advance_Deformable_Objects_In_Time (target_time, INT_MAX, verbose_dt);
solids_evolution_callbacks->Postprocess_Solids_Substep (time, 1);
LOG::Pop_Scope();
}
//#####################################################################
// Function Advance_Deformable_Objects_In_Time
//#####################################################################
template<class T> void SOLIDS_EVOLUTION_3D<T>::
Advance_Deformable_Objects_In_Time (const T final_time, const int total_loops, const bool verbose_dt)
{
DEFORMABLE_BODY_PARAMETERS_3D<T>& deformable_body_parameters = solids_parameters.deformable_body_parameters;
T initial_time = time;
for (int i = 1; i <= deformable_body_parameters.list.deformable_objects.m; i++) if (deformable_body_parameters.list (i).simulate)
{
LOG::Push_Scope ("ADO", "ADO");
time = initial_time;
bool body_done = false;
while (!body_done)
{
T dt = FLT_MAX;
if (quasistatic)
{
SOLIDS_FLUIDS_EXAMPLE<T>::Clamp_Time_Step_With_Target_Time (time, final_time, dt, body_done);
LOG::Time ("ADO - Update collision bodies");
solids_evolution_callbacks->Update_Collision_Body_Positions_And_Velocities (time + dt);
LOG::Stop_Time();
deformable_body_parameters.list (i).Advance_One_Time_Step_Quasistatic (time, dt, solids_parameters.cg_tolerance, solids_parameters.cg_iterations, newton_tolerance,
newton_iterations, use_partially_converged_result, verbose);
}
else if (!solids_parameters.semi_implicit)
{
LOG::Push_Scope ("CFL", "CFL");
dt = deformable_body_parameters.list.deformable_objects (i)->CFL (verbose_dt);
LOG::Pop_Scope();
if (verbose) LOG::cout << "raw dt = " << dt << std::endl;
LOG::Time ("ADO - Update collision bodies");
SOLIDS_FLUIDS_EXAMPLE<T>::Clamp_Time_Step_With_Target_Time (time, final_time, dt, body_done);
solids_evolution_callbacks->Update_Collision_Body_Positions_And_Velocities (time + dt);
LOG::Stop_Time();
deformable_body_parameters.list (i).Advance_One_Time_Step (time, dt, solids_parameters.cg_tolerance, solids_parameters.cg_iterations,
solids_parameters.perform_collision_body_collisions, verbose);
}
else
{
dt = deformable_body_parameters.list.deformable_objects (i)->CFL (verbose_dt);
if (verbose) LOG::cout << "raw dt = " << dt << std::endl;
SOLIDS_FLUIDS_EXAMPLE<T>::Clamp_Time_Step_With_Target_Time (time, final_time, dt, body_done);
solids_evolution_callbacks->Update_Collision_Body_Positions_And_Velocities (time + dt);
deformable_body_parameters.list (i).Advance_One_Time_Step_Semi_Implicit (time, dt, solids_parameters.perform_collision_body_collisions, verbose);
}
time += dt;
if (verbose) LOG::cout << "dt = " << dt << std::endl;
}
LOG::Pop_Scope();
}
if (!solids_parameters.asynchronous) time = final_time;
}
//#####################################################################
template class SOLIDS_EVOLUTION_3D<float>;
template class SOLIDS_EVOLUTION_3D<double>;