find_ellipse.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. #include "find_ellipse.h"
  2. #include "find_ellipse_opencl.h"
  3. #include <sys/time.h>
  4. // The number of sample points per ellipse
  5. #define NPOINTS 150
  6. // The expected radius (in pixels) of a cell
  7. #define RADIUS 10
  8. // The range of acceptable radii
  9. #define MIN_RAD RADIUS - 2
  10. #define MAX_RAD RADIUS * 2
  11. // The number of different sample ellipses to try
  12. #define NCIRCLES 7
  13. extern MAT * m_inverse(MAT * A, MAT * out);
  14. // Returns the current system time in microseconds
  15. long long get_time() {
  16. struct timeval tv;
  17. gettimeofday(&tv, NULL);
  18. return (tv.tv_sec * 1000000) + tv.tv_usec;
  19. }
  20. // Returns the specified frame from the specified video file
  21. // If cropped == true, the frame is cropped to pre-determined dimensions
  22. // (hardcoded to the boundaries of the blood vessel in the test video)
  23. // If scaled == true, all values are scaled to the range [0.0, 1.0]
  24. MAT * get_frame(avi_t *cell_file, int frame_num, int cropped, int scaled) {
  25. int dummy;
  26. int width = AVI_video_width(cell_file);
  27. int height = AVI_video_height(cell_file);
  28. unsigned char *image_buf = (unsigned char *) malloc(width * height);
  29. // There are 600 frames in this file (i.e. frame_num = 600 causes an error)
  30. AVI_set_video_position(cell_file, frame_num);
  31. //Read in the frame from the AVI
  32. if(AVI_read_frame(cell_file, (char *)image_buf, &dummy) == -1) {
  33. AVI_print_error("Error with AVI_read_frame");
  34. exit(-1);
  35. }
  36. // The image is read in upside-down, so we need to flip it
  37. MAT * image_chopped;
  38. if (cropped) {
  39. // Crop and flip image so we deal only with the interior of the vein
  40. image_chopped = chop_flip_image(image_buf, height, width, TOP, BOTTOM, 0, width - 1, scaled);
  41. } else {
  42. // Just flip the image
  43. image_chopped = chop_flip_image(image_buf, height, width, 0, height - 1, 0, width - 1, scaled);
  44. }
  45. free(image_buf);
  46. return image_chopped;
  47. }
  48. // Flips the specified image and crops it to the specified dimensions
  49. // If scaled == true, all values are scaled to the range [0.0, 1.0
  50. MAT * chop_flip_image(unsigned char *image, int height, int width, int top, int bottom, int left, int right, int scaled) {
  51. MAT * result = m_get(bottom - top + 1, right - left + 1);
  52. int i, j;
  53. if (scaled) {
  54. double scale = 1.0 / 255.0;
  55. for(i = 0; i <= (bottom - top); i++)
  56. for(j = 0; j <= (right - left); j++)
  57. //m_set_val(result, i, j, (double) image[((height - (i + top)) * width) + (j + left)] * scale);
  58. m_set_val(result, i, j, (double) image[((height - 1 - (i + top)) * width) + (j + left)] * scale);
  59. } else {
  60. for(i = 0; i <= (bottom - top); i++)
  61. for(j = 0; j <= (right - left); j++)
  62. //m_set_val(result, i, j, (double) image[((height - (i + top)) * width) + (j + left)]);
  63. m_set_val(result, i, j, (double) image[((height - 1 - (i + top)) * width) + (j + left)]);
  64. }
  65. return result;
  66. }
  67. // Chooses the best GPU on the current machine
  68. void choose_GPU(int platform_id, int device_id, int use_gpu) {
  69. select_device(platform_id, device_id, use_gpu);
  70. }
  71. // Computes and then transfers to the GPU all of the
  72. // constant matrices required by the GPU kernels
  73. void compute_constants() {
  74. // Compute memory sizes
  75. int strel_m = 12 * 2 + 1;
  76. int strel_n = 12 * 2 + 1;
  77. int n, k;
  78. // Compute the sine and cosine of the angle to each point in each sample circle
  79. // (which are the same across all sample circles)
  80. float host_sin_angle[NPOINTS], host_cos_angle[NPOINTS], theta[NPOINTS];
  81. for(n = 0; n < NPOINTS; n++) {
  82. theta[n] = (((double) n) * 2.0 * PI) / ((double) NPOINTS);
  83. host_sin_angle[n] = sin(theta[n]);
  84. host_cos_angle[n] = cos(theta[n]);
  85. }
  86. // Compute the (x,y) pixel offsets of each sample point in each sample circle
  87. int host_tX[NCIRCLES * NPOINTS], host_tY[NCIRCLES * NPOINTS];
  88. for (k = 0; k < NCIRCLES; k++) {
  89. double rad = (double) (MIN_RAD + (2 * k));
  90. for (n = 0; n < NPOINTS; n++) {
  91. host_tX[(k * NPOINTS) + n] = (int)(cos(theta[n]) * rad);
  92. host_tY[(k * NPOINTS) + n] = (int)(sin(theta[n]) * rad);
  93. }
  94. }
  95. // Compute the structuring element used in dilation
  96. float *host_strel = structuring_element(12);
  97. // Transfer the computed matrices to the GPU
  98. transfer_constants(host_sin_angle, host_cos_angle, host_tX, host_tY, strel_m, strel_n, host_strel);
  99. // Free the memory (only need to free strel since the rest are declared statically)
  100. free(host_strel);
  101. }
  102. // Given x- and y-gradients of a video frame, computes the GICOV
  103. // score for each sample ellipse at every pixel in the frame
  104. MAT *GICOV(MAT *grad_x, MAT *grad_y) {
  105. // Determine the dimensions of the frame
  106. int grad_m = grad_x->m;
  107. int grad_n = grad_y->n;
  108. // Allocate host memory for grad_x and grad_y
  109. unsigned int grad_mem_size = sizeof(float) * grad_m * grad_n;
  110. float *host_grad_x = (float*) malloc(grad_mem_size);
  111. float *host_grad_y = (float*) malloc(grad_mem_size);
  112. // initalize float versions of grad_x and grad_y
  113. int m, n;
  114. for (m = 0; m < grad_m; m++) {
  115. for (n = 0; n < grad_n; n++) {
  116. host_grad_x[(n * grad_m) + m] = (float) m_get_val(grad_x, m, n);
  117. host_grad_y[(n * grad_m) + m] = (float) m_get_val(grad_y, m, n);
  118. }
  119. }
  120. // Offload the GICOV score computation to the GPU
  121. float *host_gicov = GICOV_OpenCL(grad_m, grad_n, host_grad_x, host_grad_y);
  122. // Copy the results into a new host matrix
  123. MAT *gicov = m_get(grad_m, grad_n);
  124. for (m = 0; m < grad_m; m++)
  125. for (n = 0; n < grad_n; n++)
  126. m_set_val(gicov, m, n, host_gicov[(n * grad_m) + m]);
  127. // Cleanup memory
  128. free(host_grad_x);
  129. free(host_grad_y);
  130. /* free(host_gicov); */
  131. return gicov;
  132. }
  133. // Returns a circular structuring element of the specified radius
  134. float * structuring_element(int radius) {
  135. int m = radius*2+1;
  136. int n = radius*2+1;
  137. float *result = (float *) malloc(sizeof(float) * m * n);
  138. int i, j;
  139. for (i = 0; i < m; i++) {
  140. for (j = 0; j < n; j++) {
  141. if (sqrt((float)((i-radius)*(i-radius)+(j-radius)*(j-radius))) <= radius)
  142. result[(i * m) + j] = 1.0;
  143. else
  144. result[(i * m) + j] = 0.0;
  145. }
  146. }
  147. return result;
  148. }
  149. // Performs an image dilation on the specified matrix
  150. MAT *dilate(MAT *img_in) {
  151. // Determine the dimensions of the frame
  152. int max_gicov_m = img_in->m;
  153. int max_gicov_n = img_in->n;
  154. // Determine the dimensions of the structuring element
  155. int strel_m = 12 * 2 + 1;
  156. int strel_n = 12 * 2 + 1;
  157. // Offload the dilation to the GPU
  158. float *host_img_dilated = dilate_OpenCL(max_gicov_m, max_gicov_n, strel_m, strel_n);
  159. // Copy results into a new host matrix
  160. MAT *dilated = m_get(max_gicov_m, max_gicov_n);
  161. int m, n;
  162. for (m = 0; m < max_gicov_m; m++)
  163. for (n = 0; n < max_gicov_n; n++)
  164. m_set_val(dilated, m, n, host_img_dilated[(m * max_gicov_n) + n]);
  165. // Cleanup memory
  166. free(host_img_dilated);
  167. return dilated;
  168. }
  169. //M = # of sampling points in each segment
  170. //N = number of segment of curve
  171. //Get special TMatrix
  172. MAT * TMatrix(unsigned int N, unsigned int M)
  173. {
  174. MAT * B = NULL, * LB = NULL, * B_TEMP = NULL, * B_TEMP_INV = NULL, * B_RET = NULL;
  175. int * aindex, * bindex, * cindex, * dindex;
  176. int i, j;
  177. aindex = (int*) malloc(N*sizeof(int));
  178. bindex = (int*) malloc(N*sizeof(int));
  179. cindex = (int*) malloc(N*sizeof(int));
  180. dindex = (int*) malloc(N*sizeof(int));
  181. for(i = 1; i < N; i++)
  182. aindex[i] = i-1;
  183. aindex[0] = N-1;
  184. for(i = 0; i < N; i++)
  185. bindex[i] = i;
  186. for(i = 0; i < N-1; i++)
  187. cindex[i] = i+1;
  188. cindex[N-1] = 0;
  189. for(i = 0; i < N-2; i++)
  190. dindex[i] = i+2;
  191. dindex[N-2] = 0;
  192. dindex[N-1] = 1;
  193. B = m_get(N*M, N);
  194. LB = m_get(M, N);
  195. for(i = 0; i < N; i++)
  196. {
  197. m_zero(LB);
  198. for(j = 0; j < M; j++)
  199. {
  200. double s = (double)j / (double)M;
  201. double a, b, c, d;
  202. a = (-1.0*s*s*s + 3.0*s*s - 3.0*s + 1.0) / 6.0;
  203. b = (3.0*s*s*s - 6.0*s*s + 4.0) / 6.0;
  204. c = (-3.0*s*s*s + 3.0*s*s + 3.0*s + 1.0) / 6.0;
  205. d = s*s*s / 6.0;
  206. m_set_val(LB, j, aindex[i], a);
  207. m_set_val(LB, j, bindex[i], b);
  208. m_set_val(LB, j, cindex[i], c);
  209. m_set_val(LB, j, dindex[i], d);
  210. }
  211. int m, n;
  212. for(m = i*M; m < (i+1)*M; m++)
  213. for(n = 0; n < N; n++)
  214. m_set_val(B, m, n, m_get_val(LB, m%M, n));
  215. }
  216. B_TEMP = mtrm_mlt(B, B, B_TEMP);
  217. B_TEMP_INV = m_inverse(B_TEMP, B_TEMP_INV);
  218. B_RET = mmtr_mlt(B_TEMP_INV, B, B_RET);
  219. m_free(B);
  220. m_free(LB);
  221. m_free(B_TEMP);
  222. m_free(B_TEMP_INV);
  223. free(dindex);
  224. free(cindex);
  225. free(bindex);
  226. free(aindex);
  227. return B_RET;
  228. }
  229. void uniformseg(VEC * cellx_row, VEC * celly_row, MAT * x, MAT * y)
  230. {
  231. double dx[36], dy[36], dist[36], dsum[36], perm = 0.0, uperm;
  232. int i, j, index[36];
  233. for(i = 1; i <= 36; i++)
  234. {
  235. dx[i%36] = v_get_val(cellx_row, i%36) - v_get_val(cellx_row, (i-1)%36);
  236. dy[i%36] = v_get_val(celly_row, i%36) - v_get_val(celly_row, (i-1)%36);
  237. dist[i%36] = sqrt(dx[i%36]*dx[i%36] + dy[i%36]*dy[i%36]);
  238. perm+= dist[i%36];
  239. }
  240. uperm = perm / 36.0;
  241. dsum[0] = dist[0];
  242. for(i = 1; i < 36; i++)
  243. dsum[i] = dsum[i-1]+dist[i];
  244. for(i = 0; i < 36; i++)
  245. {
  246. double minimum=DBL_MAX, temp;
  247. int min_index = 0;
  248. for(j = 0; j < 36; j++)
  249. {
  250. temp = fabs(dsum[j]- (double)i*uperm);
  251. if (temp < minimum)
  252. {
  253. minimum = temp;
  254. min_index = j;
  255. }
  256. }
  257. index[i] = min_index;
  258. }
  259. for(i = 0; i < 36; i++)
  260. {
  261. m_set_val(x, 0, i, v_get_val(cellx_row, index[i]));
  262. m_set_val(y, 0, i, v_get_val(celly_row, index[i]));
  263. }
  264. }
  265. //Get minimum element in a matrix
  266. double m_min(MAT * m)
  267. {
  268. int i, j;
  269. double minimum = DBL_MAX, temp;
  270. for(i = 0; i < m->m; i++)
  271. {
  272. for(j = 0; j < m->n; j++)
  273. {
  274. temp = m_get_val(m, i, j);
  275. if(temp < minimum)
  276. minimum = temp;
  277. }
  278. }
  279. return minimum;
  280. }
  281. //Get maximum element in a matrix
  282. double m_max(MAT * m)
  283. {
  284. int i, j;
  285. double maximum = DBL_MIN, temp;
  286. for(i = 0; i < m->m; i++)
  287. {
  288. for(j = 0; j < m->n; j++)
  289. {
  290. temp = m_get_val(m, i, j);
  291. if(temp > maximum)
  292. maximum = temp;
  293. }
  294. }
  295. return maximum;
  296. }
  297. VEC * getsampling(MAT * m, int ns)
  298. {
  299. int N = m->n > m->m ? m-> n:m->m, M = ns;
  300. int * aindex, * bindex, * cindex, * dindex;
  301. int i, j;
  302. VEC * retval = v_get(N*M);
  303. aindex = (int*) malloc(N*sizeof(int));
  304. bindex = (int*) malloc(N*sizeof(int));
  305. cindex = (int*) malloc(N*sizeof(int));
  306. dindex = (int*) malloc(N*sizeof(int));
  307. for(i = 1; i < N; i++)
  308. aindex[i] = i-1;
  309. aindex[0] = N-1;
  310. for(i = 0; i < N; i++)
  311. bindex[i] = i;
  312. for(i = 0; i < N-1; i++)
  313. cindex[i] = i+1;
  314. cindex[N-1] = 0;
  315. for(i = 0; i < N-2; i++)
  316. dindex[i] = i+2;
  317. dindex[N-2] = 0;
  318. dindex[N-1] = 1;
  319. for(i = 0; i < N; i++)
  320. {
  321. for(j = 0; j < M; j++)
  322. {
  323. double s = (double)j / (double)M;
  324. double a, b, c, d;
  325. a = m_get_val(m, 0, aindex[i]) * (-1.0*s*s*s + 3.0*s*s - 3.0*s + 1.0);
  326. b = m_get_val(m, 0, bindex[i]) * (3.0*s*s*s - 6.0*s*s + 4.0);
  327. c = m_get_val(m, 0, cindex[i]) * (-3.0*s*s*s + 3.0*s*s + 3.0*s + 1.0);
  328. d = m_get_val(m, 0, dindex[i]) * s*s*s;
  329. v_set_val(retval, i*M+j,(a+b+c+d)/6.0);
  330. }
  331. }
  332. free(dindex);
  333. free(cindex);
  334. free(bindex);
  335. free(aindex);
  336. return retval;
  337. }
  338. VEC * getfdriv(MAT * m, int ns)
  339. {
  340. int N = m->n > m->m ? m-> n:m->m, M = ns;
  341. int * aindex, * bindex, * cindex, * dindex;
  342. int i, j;
  343. VEC * retval = v_get(N*M);
  344. aindex = (int*) malloc(N*sizeof(int));
  345. bindex = (int*) malloc(N*sizeof(int));
  346. cindex = (int*) malloc(N*sizeof(int));
  347. dindex = (int*) malloc(N*sizeof(int));
  348. for(i = 1; i < N; i++)
  349. aindex[i] = i-1;
  350. aindex[0] = N-1;
  351. for(i = 0; i < N; i++)
  352. bindex[i] = i;
  353. for(i = 0; i < N-1; i++)
  354. cindex[i] = i+1;
  355. cindex[N-1] = 0;
  356. for(i = 0; i < N-2; i++)
  357. dindex[i] = i+2;
  358. dindex[N-2] = 0;
  359. dindex[N-1] = 1;
  360. for(i = 0; i < N; i++)
  361. {
  362. for(j = 0; j < M; j++)
  363. {
  364. double s = (double)j / (double)M;
  365. double a, b, c, d;
  366. a = m_get_val(m, 0, aindex[i]) * (-3.0*s*s + 6.0*s - 3.0);
  367. b = m_get_val(m, 0, bindex[i]) * (9.0*s*s - 12.0*s);
  368. c = m_get_val(m, 0, cindex[i]) * (-9.0*s*s + 6.0*s + 3.0);
  369. d = m_get_val(m, 0, dindex[i]) * (3.0 *s*s);
  370. v_set_val(retval, i*M+j, (a+b+c+d)/6.0);
  371. }
  372. }
  373. free(dindex);
  374. free(cindex);
  375. free(bindex);
  376. free(aindex);
  377. return retval;
  378. }
  379. //Performs bilinear interpolation, getting the values of m specified in the vectors X and Y
  380. MAT * linear_interp2(MAT * m, VEC * X, VEC * Y)
  381. {
  382. //Kind of assumes X and Y have same len!
  383. MAT * retval = m_get(1, X->dim);
  384. double x_coord, y_coord, new_val, a, b;
  385. int l, k, i;
  386. for(i = 0; i < X->dim; i++)
  387. {
  388. x_coord = v_get_val(X, i);
  389. y_coord = v_get_val(Y, i);
  390. l = (int)x_coord;
  391. k = (int)y_coord;
  392. a = x_coord - (double)l;
  393. b = y_coord - (double)k;
  394. //printf("xc: %f \t yc: %f \t i: %d \t l: %d \t k: %d \t a: %f \t b: %f\n", x_coord, y_coord, i, l, k, a, b);
  395. new_val = (1.0-a)*(1.0-b)*m_get_val(m, k, l) +
  396. a*(1.0-b)*m_get_val(m, k, l+1) +
  397. (1.0-a)*b*m_get_val(m, k+1, l) +
  398. a*b*m_get_val(m, k+1, l+1);
  399. m_set_val(retval, 0, i, new_val);
  400. }
  401. return retval;
  402. }
  403. void splineenergyform01(MAT * Cx, MAT * Cy, MAT * Ix, MAT * Iy, int ns, double delta, double dt, int typeofcell)
  404. {
  405. VEC * X, * Y, * Xs, * Ys, * Nx, * Ny, * X1, * Y1, * X2, * Y2, * XY, * XX, * YY, * dCx, * dCy, * Ix1, * Ix2, *Iy1, *Iy2;
  406. MAT * Ix1_mat, * Ix2_mat, * Iy1_mat, * Iy2_mat;
  407. int i,j, N, * aindex, * bindex, * cindex, * dindex;
  408. X = getsampling(Cx, ns);
  409. Y = getsampling(Cy, ns);
  410. Xs = getfdriv(Cx, ns);
  411. Ys = getfdriv(Cy, ns);
  412. Nx = v_get(Ys->dim);
  413. for(i = 0; i < Nx->dim; i++)
  414. v_set_val(Nx, i, v_get_val(Ys, i) / sqrt(v_get_val(Xs, i)*v_get_val(Xs, i) + v_get_val(Ys, i)*v_get_val(Ys, i)));
  415. Ny = v_get(Xs->dim);
  416. for(i = 0; i < Ny->dim; i++)
  417. v_set_val(Ny, i, -1.0 * v_get_val(Xs, i) / sqrt(v_get_val(Xs, i)*v_get_val(Xs, i) + v_get_val(Ys, i)*v_get_val(Ys, i)));
  418. X1 = v_get(Nx->dim);
  419. for(i = 0; i < X1->dim; i++)
  420. v_set_val(X1, i, v_get_val(X, i) + delta*v_get_val(Nx, i));
  421. Y1 = v_get(Ny->dim);
  422. for(i = 0; i < Y1->dim; i++)
  423. v_set_val(Y1, i, v_get_val(Y, i) + delta*v_get_val(Ny, i));
  424. X2 = v_get(Nx->dim);
  425. for(i = 0; i < X2->dim; i++)
  426. v_set_val(X2, i, v_get_val(X, i) - delta*v_get_val(Nx, i));
  427. Y2 = v_get(Ny->dim);
  428. for(i = 0; i < Y2->dim; i++)
  429. v_set_val(Y2, i, v_get_val(Y, i) + delta*v_get_val(Ny, i));
  430. // seg fault happens at this func call
  431. Ix1_mat = linear_interp2(Ix, X1, Y1);
  432. Iy1_mat = linear_interp2(Iy, X1, Y1);
  433. Ix2_mat = linear_interp2(Ix, X2, Y2);
  434. Iy2_mat = linear_interp2(Iy, X2, Y2);
  435. Ix1 = v_get(Ix1_mat->n);
  436. Iy1 = v_get(Iy1_mat->n);
  437. Ix2 = v_get(Ix2_mat->n);
  438. Iy2 = v_get(Iy2_mat->n);
  439. Ix1 = get_row(Ix1_mat, 0, Ix1);
  440. Iy1 = get_row(Iy1_mat, 0, Iy1);
  441. Ix2 = get_row(Ix2_mat, 0, Ix2);
  442. Iy2 = get_row(Iy2_mat, 0, Iy2);
  443. N = Cx->m;
  444. //VEC * retval = v_get(N*ns);
  445. aindex = (int*) malloc(N*sizeof(int));
  446. bindex = (int*) malloc(N*sizeof(int));
  447. cindex = (int*) malloc(N*sizeof(int));
  448. dindex = (int*) malloc(N*sizeof(int));
  449. for(i = 1; i < N; i++)
  450. aindex[i] = i-1;
  451. aindex[0] = N-1;
  452. for(i = 0; i < N; i++)
  453. bindex[i] = i;
  454. for(i = 0; i < N-1; i++)
  455. cindex[i] = i+1;
  456. cindex[N-1] = 0;
  457. for(i = 0; i < N-2; i++)
  458. dindex[i] = i+2;
  459. dindex[N-2] = 0;
  460. dindex[N-1] = 1;
  461. XY = v_get(Xs->dim);
  462. for(i = 0; i < Xs->dim; i++)
  463. v_set_val(XY, i, v_get_val(Xs, i) * v_get_val(Ys, i));
  464. XX = v_get(Xs->dim);
  465. for(i = 0; i < Xs->dim; i++)
  466. v_set_val(XX, i, v_get_val(Xs, i) * v_get_val(Xs, i));
  467. YY = v_get(Ys->dim);
  468. for(i = 0; i < Xs->dim; i++)
  469. v_set_val(YY, i, v_get_val(Ys, i) * v_get_val(Ys, i));
  470. dCx = v_get(Cx->m);
  471. dCy = v_get(Cy->m);
  472. //get control points for splines
  473. for(i = 0; i < Cx->m; i++)
  474. {
  475. for(j = 0; j < ns; j++)
  476. {
  477. double s = (double)j / (double)ns;
  478. double A1, A2, A3, A4, B1, B2, B3, B4, D, D_3, Tx1, Tx2, Tx3, Tx4, Ty1, Ty2, Ty3, Ty4;
  479. int k;
  480. A1 = (-1.0*(s-1.0)*(s-1.0)*(s-1.0)) / 6.0;
  481. A2 = (3.0*s*s*s - 6.0*s*s + 4.0) / 6.0;
  482. A3 = (-3.0*s*s*s + 3.0*s*s + 3.0*s + 1.0) / 6.0;
  483. A4 = s*s*s / 6.0;
  484. B1 = (-3.0*s*s + 6.0*s - 3.0) / 6.0;
  485. B2 = (9.0*s*s - 12.0*s) / 6.0;
  486. B3 = (-9.0*s*s + 6.0*s + 3.0) / 6.0;
  487. B4 = 3.0*s*s / 6.0;
  488. k = i*ns+j;
  489. D = sqrt(v_get_val(Xs, k)*v_get_val(Xs, k) + v_get_val(Ys, k)*v_get_val(Ys, k));
  490. D_3 = D*D*D;
  491. //1st control point
  492. Tx1 = A1 - delta * v_get_val(XY, k) * B1 / D_3;
  493. Tx2 = -1.0 * delta*(B1/D - v_get_val(XX, k)*B1/D_3);
  494. Tx3 = A1 + delta * v_get_val(XY, k) * B1 / D_3;
  495. Tx4 = delta*(B1/D - v_get_val(XX, k)*B1/D_3);
  496. Ty1 = delta*(B1/D - v_get_val(YY, k)*B1/D_3);
  497. Ty2 = A1 + delta * v_get_val(XY, k) * B1 / D_3;
  498. Ty3 = -1.0 * delta*(B1/D - v_get_val(YY, k)*B1/D_3);
  499. Ty4 = A1 - delta * v_get_val(XY, k) * B1 / D_3;
  500. v_set_val(dCx, aindex[i], v_get_val(dCx, aindex[i]) + Tx1*v_get_val(Ix1, k) + Tx2*v_get_val(Iy1,k) - Tx3*v_get_val(Ix2, k) - Tx4*v_get_val(Iy2, k));
  501. v_set_val(dCy, aindex[i], v_get_val(dCy, aindex[i]) + Ty1*v_get_val(Ix1, k) + Ty2*v_get_val(Iy1,k) - Ty3*v_get_val(Ix2, k) - Ty4*v_get_val(Iy2, k));
  502. //2nd control point
  503. Tx1 = A2 - delta * v_get_val(XY, k) * B2 / D_3;
  504. Tx2 = -1.0 * delta*(B2/D - v_get_val(XX, k)*B2/D_3);
  505. Tx3 = A2 + delta * v_get_val(XY, k) * B2 / D_3;
  506. Tx4 = delta*(B2/D - v_get_val(XX, k)*B2/D_3);
  507. Ty1 = delta*(B2/D - v_get_val(YY, k)*B2/D_3);
  508. Ty2 = A2 + delta * v_get_val(XY, k) * B2 / D_3;
  509. Ty3 = -1.0 * delta*(B2/D - v_get_val(YY, k)*B2/D_3);
  510. Ty4 = A2 - delta * v_get_val(XY, k) * B2 / D_3;
  511. v_set_val(dCx, bindex[i], v_get_val(dCx, bindex[i]) + Tx1*v_get_val(Ix1, k) + Tx2*v_get_val(Iy1,k) - Tx3*v_get_val(Ix2, k) - Tx4*v_get_val(Iy2, k));
  512. v_set_val(dCy, bindex[i], v_get_val(dCy, bindex[i]) + Ty1*v_get_val(Ix1, k) + Ty2*v_get_val(Iy1,k) - Ty3*v_get_val(Ix2, k) - Ty4*v_get_val(Iy2, k));
  513. //3nd control point
  514. Tx1 = A3 - delta * v_get_val(XY, k) * B3 / D_3;
  515. Tx2 = -1.0 * delta*(B3/D - v_get_val(XX, k)*B3/D_3);
  516. Tx3 = A3 + delta * v_get_val(XY, k) * B3 / D_3;
  517. Tx4 = delta*(B3/D - v_get_val(XX, k)*B3/D_3);
  518. Ty1 = delta*(B3/D - v_get_val(YY, k)*B3/D_3);
  519. Ty2 = A3 + delta * v_get_val(XY, k) * B3 / D_3;
  520. Ty3 = -1.0 * delta*(B3/D - v_get_val(YY, k)*B3/D_3);
  521. Ty4 = A3 - delta * v_get_val(XY, k) * B3 / D_3;
  522. v_set_val(dCx, cindex[i], v_get_val(dCx, cindex[i]) + Tx1*v_get_val(Ix1, k) + Tx2*v_get_val(Iy1,k) - Tx3*v_get_val(Ix2, k) - Tx4*v_get_val(Iy2, k));
  523. v_set_val(dCy, cindex[i], v_get_val(dCy, cindex[i]) + Ty1*v_get_val(Ix1, k) + Ty2*v_get_val(Iy1,k) - Ty3*v_get_val(Ix2, k) - Ty4*v_get_val(Iy2, k));
  524. //4nd control point
  525. Tx1 = A4 - delta * v_get_val(XY, k) * B4 / D_3;
  526. Tx2 = -1.0 * delta*(B4/D - v_get_val(XX, k)*B4/D_3);
  527. Tx3 = A4 + delta * v_get_val(XY, k) * B4 / D_3;
  528. Tx4 = delta*(B4/D - v_get_val(XX, k)*B4/D_3);
  529. Ty1 = delta*(B4/D - v_get_val(YY, k)*B4/D_3);
  530. Ty2 = A4 + delta * v_get_val(XY, k) * B4 / D_3;
  531. Ty3 = -1.0 * delta*(B4/D - v_get_val(YY, k)*B4/D_3);
  532. Ty4 = A4 - delta * v_get_val(XY, k) * B4 / D_3;
  533. v_set_val(dCx, dindex[i], v_get_val(dCx, dindex[i]) + Tx1*v_get_val(Ix1, k) + Tx2*v_get_val(Iy1,k) - Tx3*v_get_val(Ix2, k) - Tx4*v_get_val(Iy2, k));
  534. v_set_val(dCy, dindex[i], v_get_val(dCy, dindex[i]) + Ty1*v_get_val(Ix1, k) + Ty2*v_get_val(Iy1,k) - Ty3*v_get_val(Ix2, k) - Ty4*v_get_val(Iy2, k));
  535. }
  536. }
  537. if(typeofcell==1)
  538. {
  539. for(i = 0; i < Cx->n; i++)
  540. m_set_val(Cx, 0, i, m_get_val(Cx, 1, i) - dt*v_get_val(dCx, i));
  541. for(i = 0; i < Cy->n; i++)
  542. m_set_val(Cy, 0, i, m_get_val(Cy, 1, i) - dt*v_get_val(dCy, i));
  543. }
  544. else
  545. {
  546. for(i = 0; i < Cx->n; i++)
  547. m_set_val(Cx, 0, i, m_get_val(Cx, 1, i) + dt*v_get_val(dCx, i));
  548. for(i = 0; i < Cy->n; i++)
  549. m_set_val(Cy, 0, i, m_get_val(Cy, 1, i) + dt*v_get_val(dCy, i));
  550. }
  551. v_free(dCy); v_free(dCx); v_free(YY); v_free(XX); v_free(XY);
  552. free(dindex); free(cindex); free(bindex); free(aindex);
  553. v_free(Iy2); v_free(Ix2); v_free(Iy1); v_free(Ix1);
  554. m_free(Iy2_mat); m_free(Ix2_mat); m_free(Iy1_mat); m_free(Ix1_mat);
  555. v_free(Y2); v_free(X2); v_free(Y1); v_free(X1); v_free(Ny); v_free(Nx); v_free(Ys); v_free(Xs); v_free(Y); v_free(X);
  556. }