/* $Id: shoot_regularisers.c 4875 2012-08-30 20:04:30Z john $ */ /* (c) John Ashburner (2011) */ #include #include extern double log(double x); #include "shoot_boundary.h" /* % MATLAB code (requiring Symbolic Toolbox) for computing the % regulariser for linear elasticity. syms mu lam syms v0 v1 v2 N = 3; O = sym(zeros(N)); OO = kron(kron(O,O),O); I = sym(eye(N)); G1 = sym(spdiags(repmat([-1 1],N,1),[ 0 1],N,N)); G1(N,1) = 1; G2 = sym(spdiags(repmat([-1 1],N,1),[-1 0],N,N)); G2(1,N) = -1; G = {G1 G2}; LL = sym(zeros(3*N^3,3*N^3)); for i=1:2, Di = kron(I,kron(I,G{i}))/v0; for j=1:2, Dj = kron(I,kron(G{j},I))/v1; for k=1:2, Dk = kron(G{k},kron(I,I))/v2; L1 = [ Di OO OO OO Dj OO OO OO Dk 0.5*Dj 0.5*Di OO 0.5*Dk OO 0.5*Di OO 0.5*Dk 0.5*Dj 0.5*Dj 0.5*Di OO 0.5*Dk OO 0.5*Di OO 0.5*Dk 0.5*Dj]; % Elements of symmetric part of Jacobian L2 = [ Di Dj Dk]; % Divergence LL = LL + mu*(L1.'*L1) + lam*(L2.'*L2); end end end LL = LL/8; o = sym(ones(1,27)); LL = LL.*kron([v0*o v1*o v2*o],[o o o].').*kron([v0*o v1*o v2*o].',[o o o]); L1 = simplify(reshape(LL(:,2+3+9 ),[3 3 3 3])) L2 = simplify(reshape(LL(:,2+3+9+27),[3 3 3 3])) L3 = simplify(reshape(LL(:,2+3+9+54),[3 3 3 3])) */ /* % MATLAB code (requiring Symbolic Toolbox) for computing the % regulariser for bending energy. Note that an additional multiplication % by the square of the voxel size is needed. syms s1 s2 s3 syms l1 l2 l3 zz = sym(zeros(3,3)); K1 = cat(3,zz,[0 -1/(v0*v0) 0; 0 2/(v0*v0) 0; 0 -1/(v0*v0) 0],zz); K2 = cat(3,zz,[0 0 0; -1/(v1*v1) 2/(v1*v1) -1/(v1*v1); 0 0 0],zz); K3 = sym(zeros(3,3,3)); K3(2,2,1) = -1/(v2*v2); K3(2,2,2) = 2/(v2*v2); K3(2,2,3) = -1/(v2*v2); K = K1+K2+K3; K1 = K*l1; K1(2,2,2) = K1(2,2,2)+l2; K2 = K*l1; K2(2,2,2) = K2(2,2,2)+l3; % L = convn(K,K) L = sym(zeros(5,5,5)); for i=1:3, for j=1:3, for k=1:3, L(i-1+1:i+1+1,j-1+1:j+1+1,k-1+1:k+1+1) = L(i-1+1:i+1+1,j-1+1:j+1+1,k-1+1:k+1+1) + K1(i,j,k)*K2; end; end; end; disp(simplify(L(3:end,3:end,3:end))) */ void kernel(mwSize dm[], double s[], float f[]) { double w000,w100,w200, w010,w110, w020, w001,w101, w011, w002; double v0 = s[0]*s[0], v1 = s[1]*s[1], v2 = s[2]*s[2]; double lam0 = s[3], lam1 = s[4], lam2 = s[5], mu = s[6], lam = s[7]; mwSignedIndex im2,im1,ip1,ip2, jm2,jm1,jp1,jp2, km2,km1,kp1,kp2; km2 = (bound((mwSignedIndex)-2,dm[2]))*dm[0]*dm[1]; km1 = (bound((mwSignedIndex)-1,dm[2]))*dm[0]*dm[1]; kp1 = (bound((mwSignedIndex) 1,dm[2]))*dm[0]*dm[1]; kp2 = (bound((mwSignedIndex) 2,dm[2]))*dm[0]*dm[1]; jm2 = (bound((mwSignedIndex)-2,dm[1]))*dm[0]; jm1 = (bound((mwSignedIndex)-1,dm[1]))*dm[0]; jp1 = (bound((mwSignedIndex) 1,dm[1]))*dm[0]; jp2 = (bound((mwSignedIndex) 2,dm[1]))*dm[0]; im2 = bound((mwSignedIndex)-2,dm[0]); im1 = bound((mwSignedIndex)-1,dm[0]); ip1 = bound((mwSignedIndex) 1,dm[0]); ip2 = bound((mwSignedIndex) 2,dm[0]); w000 = lam2*(6*(v0*v0+v1*v1+v2*v2) +8*(v0*v1+v0*v2+v1*v2)) +lam1*2*(v0+v1+v2) + lam0; w100 = lam2*(-4*v0*(v0+v1+v2)) -lam1*v0; w010 = lam2*(-4*v1*(v0+v1+v2)) -lam1*v1; w001 = lam2*(-4*v2*(v0+v1+v2)) -lam1*v2; w200 = lam2*v0*v0; w020 = lam2*v1*v1; w002 = lam2*v2*v2; w110 = lam2*2*v0*v1; w101 = lam2*2*v0*v2; w011 = lam2*2*v1*v2; if (mu==0 && lam==0) { f[0] += w000; f[im1 ] += w100; f[ip1 ] += w100; f[ jm1 ] += w010; f[ jp1 ] += w010; f[ km1] += w001; f[ kp1] += w001; f[im2 ] += w200; f[ip2 ] += w200; f[ jm2 ] += w020; f[ jp2 ] += w020; f[ km2] += w002; f[ kp2] += w002; f[im1+jm1 ] += w110; f[ip1+jm1 ] += w110; f[im1+jp1 ] += w110; f[ip1+jp1 ] += w110; f[im1 +km1] += w101; f[ip1 +km1] += w101; f[im1 +kp1] += w101; f[ip1 +kp1] += w101; f[ jm1+km1] += w011; f[ jp1+km1] += w011; f[ jm1+kp1] += w011; f[ jp1+kp1] += w011; } else { double wx000, wx100, wx010, wx001, wy000, wy100, wy010, wy001, wz000, wz100, wz010, wz001, w2; float *pxx, *pxy, *pxz, *pyx, *pyy, *pyz, *pzx, *pzy, *pzz; mwSignedIndex m = dm[0]*dm[1]*dm[2]; wx000 = 2*mu*(2*v0+v1+v2)/v0+2*lam + w000/v0; wx100 = -2*mu-lam + w100/v0; wx010 = -mu*v1/v0 + w010/v0; wx001 = -mu*v2/v0 + w001/v0; wy000 = 2*mu*(v0+2*v1+v2)/v1+2*lam + w000/v1; wy100 = -mu*v0/v1 + w100/v1; wy010 = -2*mu-lam + w010/v1; wy001 = -mu*v2/v1 + w001/v1; wz000 = 2*mu*(v0+v1+2*v2)/v2+2*lam + w000/v2; wz100 = -mu*v0/v2 + w100/v2; wz010 = -mu*v1/v2 + w010/v2; wz001 = -2*mu-lam + w001/v2; w2 = 0.25*mu+0.25*lam; pxx = f; pyx = f + m; pzx = f + m*2; pxy = f + m*3; pyy = f + m*4; pzy = f + m*5; pxz = f + m*6; pyz = f + m*7; pzz = f + m*8; pxx[0 ] += wx000; pxx[im1 ] += wx100; pxx[ip1 ] += wx100; pxx[ jm1 ] += wx010; pxx[ jp1 ] += wx010; pxx[ km1] += wx001; pxx[ kp1] += wx001; pxy[ip1+jm1 ] += w2; pxy[ip1+jp1 ] -= w2; pxy[im1+jm1 ] -= w2; pxy[im1+jp1 ] += w2; pxz[ip1 +km1] += w2; pxz[ip1 +kp1] -= w2; pxz[im1 +km1] -= w2; pxz[im1 +kp1] += w2; pxx[im1+jm1 ] += w110/v0; pxx[ip1+jm1 ] += w110/v0; pxx[im1+jp1 ] += w110/v0; pxx[ip1+jp1 ] += w110/v0; pxx[im1 +km1] += w101/v0; pxx[ip1 +km1] += w101/v0; pxx[im1 +kp1] += w101/v0; pxx[ip1 +kp1] += w101/v0; pxx[ jm1+km1] += w011/v0; pxx[ jp1+km1] += w011/v0; pxx[ jm1+kp1] += w011/v0; pxx[ jp1+kp1] += w011/v0; pxx[im2 ] += w200/v0; pxx[ip2 ] += w200/v0; pxx[ jm2 ] += w020/v0; pxx[ jp2 ] += w020/v0; pxx[ km2] += w002/v0; pxx[ kp2] += w002/v0; pyy[0 ] += wy000; pyy[im1 ] += wy100; pyy[ip1 ] += wy100; pyy[ jm1 ] += wy010; pyy[ jp1 ] += wy010; pyy[ km1] += wy001; pyy[ kp1] += wy001; pyx[ip1+jm1 ] += w2; pyx[ip1+jp1 ] -= w2; pyx[im1+jm1 ] -= w2; pyx[im1+jp1 ] += w2; pyz[ jp1+km1] += w2; pyz[ jp1+kp1] -= w2; pyz[ jm1+km1] -= w2; pyz[ jm1+kp1] += w2; pyy[im1+jm1 ] += w110/v1; pyy[ip1+jm1 ] += w110/v1; pyy[im1+jp1 ] += w110/v1; pyy[ip1+jp1 ] += w110/v1; pyy[im1 +km1] += w101/v1; pyy[ip1 +km1] += w101/v1; pyy[im1 +kp1] += w101/v1; pyy[ip1 +kp1] += w101/v1; pyy[ jm1+km1] += w011/v1; pyy[ jp1+km1] += w011/v1; pyy[ jm1+kp1] += w011/v1; pyy[ jp1+kp1] += w011/v1; pyy[im2 ] += w200/v1; pyy[ip2 ] += w200/v1; pyy[ jm2 ] += w020/v1; pyy[ jp2 ] += w020/v1; pyy[ km2] += w002/v1; pyy[ kp2] += w002/v1; pzz[0 ] += wz000; pzz[im1 ] += wz100; pzz[ip1 ] += wz100; pzz[ jm1 ] += wz010; pzz[ jp1 ] += wz010; pzz[ km1] += wz001; pzz[ kp1] += wz001; pzx[im1 +kp1] += w2; pzx[ip1 +kp1] -= w2; pzx[im1 +km1] -= w2; pzx[ip1 +km1] += w2; pzy[jm1 +kp1] += w2; pzy[ jp1+kp1] -= w2; pzy[ jm1+km1] -= w2; pzy[ jp1+km1] += w2; pzz[im1+jm1 ] += w110/v2; pzz[ip1+jm1 ] += w110/v2; pzz[im1+jp1 ] += w110/v2; pzz[ip1+jp1 ] += w110/v2; pzz[im1 +km1] += w101/v2; pzz[ip1 +km1] += w101/v2; pzz[im1 +kp1] += w101/v2; pzz[ip1 +kp1] += w101/v2; pzz[ jm1+km1] += w011/v2; pzz[ jp1+km1] += w011/v2; pzz[ jm1+kp1] += w011/v2; pzz[ jp1+kp1] += w011/v2; pzz[im2 ] += w200/v2; pzz[ip2 ] += w200/v2; pzz[ jm2 ] += w020/v2; pzz[ jp2 ] += w020/v2; pzz[ km2] += w002/v2; pzz[ kp2] += w002/v2; } } double sumsq(mwSize dm[], float a[], float b[], double s[], float u[]) { double w000,w100,w200, w010,w110, w020, w001,w101, w011, w002; double ss = 0.0; mwSignedIndex k; double v0 = s[0]*s[0], v1 = s[1]*s[1], v2 = s[2]*s[2]; double lam0 = s[3], lam1 = s[4], lam2 = s[5], mu = s[6], lam = s[7]; double wx000, wx100, wx010, wx001, wy000, wy100, wy010, wy001, wz000, wz100, wz010, wz001, w2; w000 = lam2*(6*(v0*v0+v1*v1+v2*v2) +8*(v0*v1+v0*v2+v1*v2)) +lam1*2*(v0+v1+v2) + lam0; w100 = lam2*(-4*v0*(v0+v1+v2)) -lam1*v0; w010 = lam2*(-4*v1*(v0+v1+v2)) -lam1*v1; w001 = lam2*(-4*v2*(v0+v1+v2)) -lam1*v2; w200 = lam2*v0*v0; w020 = lam2*v1*v1; w002 = lam2*v2*v2; w110 = lam2*2*v0*v1; w101 = lam2*2*v0*v2; w011 = lam2*2*v1*v2; wx000 = 2*mu*(2*v0+v1+v2)/v0+2*lam + w000/v0; wx100 = -2*mu-lam + w100/v0; wx010 = -mu*v1/v0 + w010/v0; wx001 = -mu*v2/v0 + w001/v0; wy000 = 2*mu*(v0+2*v1+v2)/v1+2*lam + w000/v1; wy100 = -mu*v0/v1 + w100/v1; wy010 = -2*mu-lam + w010/v1; wy001 = -mu*v2/v1 + w001/v1; wz000 = 2*mu*(v0+v1+2*v2)/v2+2*lam + w000/v2; wz100 = -mu*v0/v2 + w100/v2; wz010 = -mu*v1/v2 + w010/v2; wz001 = -2*mu-lam + w001/v2; w2 = 0.25*mu+0.25*lam; for(k=0; k>1)&1; j>2)&1; i