Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_VERSATILE_VERSATILE_VOLUME_CONSTRAINT_H
00002 #define OPENTISSUE_DYNAMICS_VERSATILE_VERSATILE_VOLUME_CONSTRAINT_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 namespace OpenTissue
00013 {
00014 namespace versatile
00015 {
00016 namespace detail
00017 {
00018 template <typename versatile_types>
00019 class VolumeConstraint
00020 {
00021 public:
00022
00023 typedef typename versatile_types::value_traits value_traits;
00024 typedef typename versatile_types::real_type real_type;
00025 typedef typename versatile_types::vector3_type vector3_type;
00026 typedef typename versatile_types::node_type node_type;
00027
00028 public:
00029
00030 real_type m_k;
00031 real_type m_b;
00032 real_type m_V0;
00033 node_type * m_ni;
00034 node_type * m_nj;
00035 node_type * m_nk;
00036 node_type * m_nm;
00037
00038 public:
00039
00040 void initialize(node_type & ni,node_type & nj,node_type & nk,node_type & nm)
00041 {
00042 real_type const six = boost::numeric_cast<real_type>(6.0);
00043
00044 m_ni = & ni;
00045 m_nj = & nj;
00046 m_nk = & nk;
00047 m_nm = & nm;
00048
00049 vector3_type e_ki = (m_nk->m_coord - m_ni->m_coord);
00050 vector3_type e_mi = (m_nm->m_coord - m_ni->m_coord);
00051 vector3_type e_ji = (m_nj->m_coord - m_ni->m_coord);
00052
00053 m_V0 = e_mi * cross(e_ji , e_ki) / six;
00054 }
00055
00056 void apply()const
00057 {
00058 real_type const six = boost::numeric_cast<real_type>(6.0);
00059
00060 vector3_type e_mj = (m_nm->m_coord - m_nj->m_coord);
00061 vector3_type e_kj = (m_nk->m_coord - m_nj->m_coord);
00062 vector3_type e_ki = (m_nk->m_coord - m_ni->m_coord);
00063 vector3_type e_mi = (m_nm->m_coord - m_ni->m_coord);
00064 vector3_type e_ji = (m_nj->m_coord - m_ni->m_coord);
00065
00066 real_type V = e_mi * cross(e_ji , e_ki) / six;
00067 real_type C = (V-m_V0) / m_V0;
00068 real_type nominator = value_traits::one() / six*m_V0;
00069 vector3_type dCdi = cross(e_mj , e_kj) * nominator;
00070 vector3_type dCdj = cross(e_ki , e_mi) * nominator;
00071 vector3_type dCdk = cross(e_mi , e_ji) * nominator;
00072 vector3_type dCdm = cross(e_ji , e_ki) * nominator;
00073 real_type factor = value_traits::zero();
00074 if(m_k>value_traits::zero())
00075 factor -= m_k *C;
00076 if(m_b>value_traits::zero())
00077 factor -= m_b * (dCdi*m_ni->m_v + dCdj*m_nj->m_v + dCdk*m_nk->m_v+ dCdm*m_nm->m_v);
00078 if(factor)
00079 {
00080 m_ni->m_f_con += factor*dCdi;
00081 m_nj->m_f_con += factor*dCdj;
00082 m_nk->m_f_con += factor*dCdk;
00083 m_nm->m_f_con += factor*dCdm;
00084 }
00085 }
00086
00087 real_type compute_internal_energy()
00088 {
00089 real_type const six = boost::numeric_cast<real_type>(6.0);
00090
00091 vector3_type e_ki = (m_nk->m_coord - m_ni->m_coord);
00092 vector3_type e_mi = (m_nm->m_coord - m_ni->m_coord);
00093 vector3_type e_ji = (m_nj->m_coord - m_ni->m_coord);
00094 real_type V = e_mi * cross(e_ji , e_ki) / six;
00095 real_type C = (V-m_V0) / m_V0;
00096 return value_traits::half()*m_k*C*C;
00097 }
00098 };
00099
00100 }
00101 }
00102 }
00103
00104
00105 #endif