Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_CONTAINERS_GRID_UTIL_GRID_CURVATURE_FLOW_H
00002 #define OPENTISSUE_CORE_CONTAINERS_GRID_UTIL_GRID_CURVATURE_FLOW_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/containers/grid/util/grid_mean_curvature.h>
00013
00014 namespace OpenTissue
00015 {
00016 namespace grid
00017 {
00018
00032 template<
00033 typename grid_type
00034 , typename real_type
00035 >
00036 inline void curvature_flow(
00037 grid_type const & phi
00038 , real_type const & mu
00039 , real_type const & dt
00040 , grid_type & psi
00041 )
00042 {
00043 using std::min;
00044 using std::max;
00045 using std::sqrt;
00046
00047 typedef typename grid_type::value_type value_type;
00048 typedef typename grid_type::iterator iterator;
00049 typedef typename grid_type::index_iterator index_iterator;
00050 typedef typename grid_type::const_index_iterator const_index_iterator;
00051
00052 assert(mu>0 || !"curvature_flow(): curvature coefficient must be positive");
00053 assert(dt>0 || !"curvature_flow(): time-step must be positive");
00054
00055 size_t I = phi.I();
00056 size_t J = phi.J();
00057 size_t K = phi.K();
00058 real_type dx = static_cast<real_type> ( phi.dx() );
00059 real_type dy = static_cast<real_type> ( phi.dy() );
00060 real_type dz = static_cast<real_type> ( phi.dz() );
00061 real_type m_inv_dx2 = static_cast<real_type> ( 1.0 / (dx*dx) );
00062 real_type m_inv_dy2 = static_cast<real_type> ( 1.0 / (dy*dy) );
00063 real_type m_inv_dz2 = static_cast<real_type> ( 1.0 / (dz*dz) );
00064 real_type m_inv_4dxy = static_cast<real_type> ( 0.25 / (dx*dy) );
00065 real_type m_inv_4dxz = static_cast<real_type> ( 0.25 / (dx*dz) );
00066 real_type m_inv_4dyz = static_cast<real_type> ( 0.25 / (dy*dz) );
00067
00068 real_type min_delta = static_cast<real_type> (min(dx,min(dy,dz) ));
00069
00070 real_type kappa_limit = static_cast<real_type> ( 1.0 / ( max(dx, max(dy,dz) ) ) );
00071
00072 value_type zero = static_cast<value_type>(0.0);
00073 grid_type F = phi;
00074
00075 if(&psi != &phi)
00076 psi = phi;
00077
00078 iterator fbegin = F.begin();
00079 index_iterator sbegin = psi.begin();
00080 index_iterator send = psi.end();
00081
00082 real_type threshold = static_cast<real_type>(10e-15);
00083
00084 real_type time = static_cast<real_type>(0.0);
00085 while (time < dt)
00086 {
00087 value_type max_F = zero;
00088 iterator f = fbegin;
00089 index_iterator s = sbegin;
00090 for(;s!=send; ++s,++f)
00091 {
00092 size_t i = s.i();
00093 size_t j = s.j();
00094 size_t k = s.k();
00095
00096 size_t im1 = ( i ) ? i - 1 : 0;
00097 size_t jm1 = ( j ) ? j - 1 : 0;
00098 size_t km1 = ( k ) ? k - 1 : 0;
00099 size_t ip1 = min( i + 1, I - 1 );
00100 size_t jp1 = min( j + 1, J - 1 );
00101 size_t kp1 = min( k + 1, K - 1 );
00102
00103 size_t idx_000 = ( k * J + j ) * I + i;
00104 size_t idx_m00 = ( k * J + j ) * I + im1;
00105 size_t idx_p00 = ( k * J + j ) * I + ip1;
00106 size_t idx_0m0 = ( k * J + jm1 ) * I + i;
00107 size_t idx_0p0 = ( k * J + jp1 ) * I + i;
00108 size_t idx_00m = ( km1 * J + j ) * I + i;
00109 size_t idx_00p = ( kp1 * J + j ) * I + i;
00110 size_t idx_pp0 = ( k * J + jp1 ) * I + ip1;
00111 size_t idx_mp0 = ( k * J + jp1 ) * I + im1;
00112 size_t idx_pm0 = ( k * J + jm1 ) * I + ip1;
00113 size_t idx_mm0 = ( k * J + jm1 ) * I + im1;
00114 size_t idx_p0p = ( kp1 * J + j ) * I + ip1;
00115 size_t idx_m0p = ( kp1 * J + j ) * I + im1;
00116 size_t idx_p0m = ( km1 * J + j ) * I + ip1;
00117 size_t idx_m0m = ( km1 * J + j ) * I + im1;
00118 size_t idx_0pp = ( kp1 * J + jp1 ) * I + i;
00119 size_t idx_0pm = ( km1 * J + jp1 ) * I + i;
00120 size_t idx_0mp = ( kp1 * J + jm1 ) * I + i;
00121 size_t idx_0mm = ( km1 * J + jm1 ) * I + i;
00122
00123 real_type d000 = 2.0 * psi( idx_000 );
00124 real_type dp00 = psi( idx_p00 );
00125 real_type dm00 = psi( idx_m00 );
00126 real_type d0p0 = psi( idx_0p0 );
00127 real_type d0m0 = psi( idx_0m0 );
00128 real_type d00p = psi( idx_00p );
00129 real_type d00m = psi( idx_00m );
00130 real_type dpp0 = psi( idx_pp0 );
00131 real_type dmp0 = psi( idx_mp0 );
00132 real_type dpm0 = psi( idx_pm0 );
00133 real_type dmm0 = psi( idx_mm0 );
00134 real_type dp0p = psi( idx_p0p );
00135 real_type dm0p = psi( idx_m0p );
00136 real_type dp0m = psi( idx_p0m );
00137 real_type dm0m = psi( idx_m0m );
00138 real_type d0pp = psi( idx_0pp );
00139 real_type d0pm = psi( idx_0pm );
00140 real_type d0mp = psi( idx_0mp );
00141 real_type d0mm = psi( idx_0mm );
00142
00143
00144
00145
00146
00147
00148
00149
00150 real_type psi_x = (dp00 - dm00) * m_inv_dx2;
00151 real_type psi_y = (d0p0 - d0m0) * m_inv_dy2;
00152 real_type psi_z = (d00p - d00m) * m_inv_dz2;
00153 real_type psi_xx = ( dp00 + dm00 - d000 ) * m_inv_dx2;
00154 real_type psi_yy = ( d0p0 + d0m0 - d000 ) * m_inv_dy2;
00155 real_type psi_zz = ( d00p + d00m - d000 ) * m_inv_dz2;
00156 real_type psi_xy = ( dpp0 - dmp0 - dpm0 + dmm0 ) * m_inv_4dxy;
00157 real_type psi_xz = ( dp0p - dm0p - dp0m + dm0m ) * m_inv_4dxz;
00158 real_type psi_yz = ( d0pp - d0pm - d0mp + d0mm ) * m_inv_4dyz;
00159 real_type norm_grad_psi = sqrt( (psi_x*psi_x) + (psi_y*psi_y) + (psi_z*psi_z) );
00160 real_type kappa =
00161 (
00162 (psi_x*psi_x)*psi_yy
00163 + (psi_x*psi_x)*psi_zz
00164 + (psi_y*psi_y)*psi_xx
00165 + (psi_y*psi_y)*psi_zz
00166 + (psi_z*psi_z)*psi_xx
00167 + (psi_z*psi_z)*psi_yy
00168 - 2*(psi_x*psi_y)*psi_xy
00169 - 2*(psi_x*psi_z)*psi_xz
00170 - 2*(psi_y*psi_z)*psi_yz
00171 )
00172 /
00173 (norm_grad_psi*norm_grad_psi*norm_grad_psi + threshold );
00174
00175 kappa = max( kappa, -kappa_limit );
00176 kappa = min( kappa, kappa_limit );
00177
00178 *f = static_cast<value_type>(mu * kappa);
00179 max_F = max(max_F, std::fabs(*f));
00180 }
00181 real_type time_left = max( dt - time, 0.0 );
00182 if(time_left <= 0)
00183 return;
00184
00185 value_type time_step = static_cast<value_type>( min( time_left, min_delta / (max_F) ) );
00186
00187 std::cout << "\tcurvature_flow() : timestep = " << time_step << std::endl;
00188
00189 for(s=sbegin, f=fbegin;s!=send;++s,++f)
00190 (*s) = (*s) + time_step * (*f);
00191 time += time_step;
00192 }
00193 }
00194
00195 }
00196 }
00197
00198
00199 #endif