PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/src/grid/trimesh.cc

https://github.com/aesop972/gss-tcad
C++ | 1023 lines | 837 code | 96 blank | 90 comment | 150 complexity | 6200ad83881801ac78a966365f4eed46 MD5 | raw file
  1. /*****************************************************************************/
  2. /* 8888888 88888888 88888888 */
  3. /* 8 8 8 */
  4. /* 8 8 8 */
  5. /* 8 88888888 88888888 */
  6. /* 8 8888 8 8 */
  7. /* 8 8 8 8 */
  8. /* 888888 888888888 888888888 */
  9. /* */
  10. /* A Two-Dimensional General Purpose Semiconductor Simulator. */
  11. /* */
  12. /* GSS 0.4x */
  13. /* Last update: May 14, 2006 */
  14. /* */
  15. /* Gong Ding */
  16. /* gdiso@ustc.edu */
  17. /* NINT, No.69 P.O.Box, Xi'an City, China */
  18. /* */
  19. /*****************************************************************************/
  20. #include "typedef.h"
  21. #include "skeleton.h"
  22. #include "material.h"
  23. #include "mathfunc.h"
  24. #include <stdio.h>
  25. #include <cgnslib.h>
  26. mesh_constructor::mesh_constructor(skeleton_line &lx,skeleton_line &ly)
  27. {
  28. // init Triangle io structure.
  29. in.pointlist = (double *) NULL;
  30. in.pointattributelist = (double *) NULL;
  31. in.pointmarkerlist = (int *) NULL;
  32. in.segmentlist = (int *) NULL;
  33. in.segmentmarkerlist = (int *) NULL;
  34. in.regionlist = (double *)NULL;
  35. out.pointlist = (double *) NULL;
  36. out.pointattributelist = (double *) NULL;
  37. out.pointmarkerlist = (int *) NULL;
  38. out.trianglelist = (int *) NULL;
  39. out.triangleattributelist = (double *) NULL;
  40. out.segmentlist = (int *) NULL;
  41. out.segmentmarkerlist = (int *) NULL;
  42. IX = lx.point_list.size();
  43. IY = ly.point_list.size();
  44. point_num = IX*IY;
  45. aux_point_num = 0;
  46. // set up the 2d array for gird points
  47. point_array2d = new skeleton_point *[IY];
  48. for(int i=0;i<IY;i++)
  49. point_array2d[i]= new skeleton_point [IX];
  50. for(int i=0;i<IX;i++)
  51. for(int j=0;j<IY;j++)
  52. {
  53. point_array2d[j][i].set_location(lx.point_list[i].x,ly.point_list[j].y);
  54. }
  55. xmin = point_array2d[0][0].x;
  56. xmax = point_array2d[0][IX-1].x;
  57. ymax = point_array2d[0][0].y;
  58. ymin = point_array2d[IY-1][0].y;
  59. width = xmax-xmin;
  60. depth = ymax-ymin;
  61. }
  62. mesh_constructor::~mesh_constructor()
  63. {
  64. for(int i=0;i<IY;i++)
  65. delete [] point_array2d[i];
  66. delete [] point_array2d;
  67. free(in.pointlist);
  68. free(in.pointmarkerlist);
  69. free(in.pointattributelist);
  70. free(in.segmentlist);
  71. free(in.segmentmarkerlist);
  72. free(in.regionlist);
  73. free(out.pointlist);
  74. free(out.pointmarkerlist);
  75. free(out.pointattributelist);
  76. free(out.trianglelist);
  77. free(out.triangleattributelist);
  78. free(out.segmentlist);
  79. free(out.segmentmarkerlist);
  80. }
  81. int mesh_constructor::find_skeleton_line_x(double x)
  82. {
  83. int ix=0;
  84. double dx=1e10;
  85. for(int i=0;i<IX;i++)
  86. if(fabs(x-point_array2d[0][i].x)<dx)
  87. {
  88. dx=fabs(x-point_array2d[0][i].x);
  89. ix=i;
  90. }
  91. return ix;
  92. }
  93. int mesh_constructor::find_skeleton_line_y(double y)
  94. {
  95. int iy=0;
  96. double dy=1e10;
  97. for(int i=0;i<IY;i++)
  98. if(fabs(y-point_array2d[i][0].y)<dy)
  99. {
  100. dy=fabs(y-point_array2d[i][0].y);
  101. iy=i;
  102. }
  103. return iy;
  104. }
  105. int mesh_constructor::find_move_skeleton_line_x(double x)
  106. {
  107. int ix=find_skeleton_line_x(x);
  108. for(int j=0;j<IY;j++)
  109. point_array2d[j][ix].x=x;
  110. return ix;
  111. }
  112. int mesh_constructor::find_move_skeleton_line_y(double y)
  113. {
  114. int iy=find_skeleton_line_y(y);
  115. for(int i=0;i<IX;i++)
  116. point_array2d[iy][i].y=y;
  117. return iy;
  118. }
  119. int mesh_constructor::x_eliminate(int ixmin,int ixmax, int iymin, int iymax)
  120. {
  121. for(int i=ixmin;i<=ixmax;i++)
  122. {
  123. int eliminate_flag = 1;
  124. for(int j=max(1,iymin+1);j<min(iymax+1,IY-1);j++)
  125. if(!point_array2d[j][i].eliminated)
  126. {
  127. if(eliminate_flag==1)
  128. {
  129. point_array2d[j][i].eliminated=1;
  130. eliminate_flag=0;
  131. }
  132. else
  133. eliminate_flag=1;
  134. }
  135. }
  136. return 0;
  137. }
  138. int mesh_constructor::y_eliminate(int iymin,int iymax, int ixmin, int ixmax)
  139. {
  140. for(int j=iymin;j<=iymax;j++)
  141. {
  142. int eliminate_flag = 1;
  143. for(int i=max(1,ixmin+1);i<min(ixmax+1,IX-1);i++)
  144. if(!point_array2d[j][i].eliminated)
  145. {
  146. if(eliminate_flag==1)
  147. {
  148. point_array2d[j][i].eliminated=1;
  149. eliminate_flag=0;
  150. }
  151. else
  152. eliminate_flag=1;
  153. }
  154. }
  155. return 0;
  156. }
  157. int mesh_constructor::set_spread_rectangle(int location,double width,int upperline,int lowerline,
  158. double yuploc,double yloloc,double encroach,double grading)
  159. {
  160. double ybtanc = point_array2d[IY-1][0].y;
  161. double yupanc = point_array2d[upperline][0].y;
  162. double yloanc = point_array2d[lowerline][0].y;
  163. double xloc,yupold,yloold,ybot;
  164. if(location == LEFT)
  165. xloc = point_array2d[0][0].x + width;
  166. else
  167. xloc = point_array2d[0][IX-1].x - width;
  168. double erfarg,erfar2,erfval,erfvl2;
  169. //proc colume by colume
  170. for(int i=0;i<IX;i++)
  171. {
  172. double xco=point_array2d[0][i].x;
  173. //evaluate error function for this coord.
  174. erfarg=(xco-xloc)*encroach;
  175. if (location==RIGHT)
  176. erfar2=1.5*(erfarg+0.6);
  177. else
  178. erfar2=1.5*(erfarg-0.6);
  179. if (location==LEFT)
  180. {
  181. erfval=erfc(erfarg);
  182. erfvl2=erfc(erfar2);
  183. }
  184. else
  185. {
  186. erfval=erfc(-erfarg);
  187. erfvl2=erfc(-erfar2);
  188. }
  189. erfval=erfval*0.5;
  190. erfvl2=erfvl2*0.5;
  191. //
  192. // compute new node locations on this column
  193. // get upper, lower, bottom current loc.
  194. yupanc = yupold;
  195. yupold = point_array2d[upperline][i].y;
  196. yloanc = yloold;
  197. yloold = point_array2d[lowerline][i].y;
  198. ybtanc = ybot;
  199. ybot = point_array2d[IY-1][i].y;
  200. // compute upward shift and downward
  201. double deltup=erfval*(yupold-yuploc);
  202. double deltlo=erfval*(yloloc-yloold);
  203. // compute new locations
  204. double yupnew=yupold-deltup;
  205. double ylonew=yloold+deltlo;
  206. // compute old and new spreads of middle, bottom
  207. double spmdol=yloold-yupold;
  208. double spmdnw=spmdol+deltup+deltlo;
  209. double spbtol=ybot-yloold;
  210. double spbtnw=spbtol-deltlo;
  211. // grading ratio
  212. double y,dy;
  213. if(grading!=1.0)
  214. {
  215. y = yupnew;
  216. dy = (ylonew-yupnew)*(grading-1)/(pow(grading,lowerline-upperline)-1);
  217. }
  218. // scan y nodes and move as necessary
  219. for(int j=0;j<IY;j++)
  220. {
  221. // get node number and y-coord.
  222. double yco=point_array2d[j][i].y;
  223. // consider top, middle, and bottom regions
  224. // top region (j<upperline) shift all by deltup
  225. if(j<=upperline)
  226. {
  227. yco=yco-deltup;
  228. }
  229. // bottom region, spread proportionally
  230. else if (j>=lowerline)
  231. {
  232. double rat=(yco-yloold)/spbtol;
  233. yco=ylonew+rat*spbtnw;
  234. }
  235. // middle region spread proportionally unless new grading
  236. // is requested.
  237. else
  238. {
  239. if(grading==1.0)
  240. {
  241. double rat=(yco-yupold)/spmdol;
  242. yco=yupnew+rat*spmdnw;
  243. }
  244. else // new grading requested
  245. {
  246. double ycordg = y+dy;
  247. y += dy;
  248. dy*= grading;
  249. // vary from new grading to proportional grading
  250. // based on erfvl2 (2/3 the spread of erfval and
  251. // centered at 30% point of erfval instead of
  252. // 50% point.
  253. yco=yco+erfvl2*(ycordg-yco);
  254. }
  255. }
  256. point_array2d[j][i].y = yco;
  257. }
  258. }
  259. return 0;
  260. }
  261. void mesh_constructor::make_node_index()
  262. {
  263. point_num=0;
  264. for(int i=0;i<IX;i++)
  265. for(int j=0;j<IY;j++)
  266. {
  267. if(!point_array2d[j][i].eliminated)
  268. point_array2d[j][i].index=point_num++;
  269. else
  270. point_array2d[j][i].index=-1;
  271. }
  272. for(int i=0;i<aux_point_array1d.size();i++)
  273. aux_point_array1d[i].index = point_num++;
  274. }
  275. int mesh_constructor::set_region_rectangle()
  276. {
  277. // set inner point for each region;
  278. for(int i=0;i<IX-1;i++)
  279. for(int j=0;j<IY-1;j++)
  280. {
  281. for(int k=region_array1d.size()-1;k>=0;k--)
  282. if(region_array1d[k].shape==Rectangle &&
  283. i>=region_array1d[k].ixmin && i+1<=region_array1d[k].ixmax &&
  284. j>=region_array1d[k].iymin && j+1<=region_array1d[k].iymax)
  285. {
  286. region_array1d[k].px.push_back((point_array2d[j][i].x+point_array2d[j][i+1].x)/2);
  287. region_array1d[k].py.push_back((point_array2d[j][i].y+point_array2d[j+1][i].y)/2);
  288. break;
  289. }
  290. }
  291. // set segment bounding
  292. map<skeleton_edge, int, lt_edge>::iterator pt;
  293. for(int r=0;r<region_array1d.size();r++)
  294. {
  295. if(region_array1d[r].shape!=Rectangle) continue;
  296. int ixmin = region_array1d[r].ixmin;
  297. int ixmax = region_array1d[r].ixmax;
  298. int iymin = region_array1d[r].iymin;
  299. int iymax = region_array1d[r].iymax;
  300. skeleton_edge edge;
  301. edge.IX = IX;
  302. edge.IY = IY;
  303. skeleton_segment segment;
  304. sprintf(segment.segment_label,"%s_Neumann",region_array1d[r].label);
  305. segment.segment_mark=r+1;
  306. segment_array1d.push_back(segment);
  307. //process bottom line
  308. for(int i=ixmin;i<ixmax;)
  309. {
  310. edge.p1[0]=i++;
  311. edge.p1[1]=iymax;
  312. while(point_array2d[iymax][i].eliminated) i++;
  313. edge.p2[0]=i;
  314. edge.p2[1]=iymax;
  315. edge_table[edge]=r+1;
  316. //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
  317. }
  318. //process top line
  319. for(int i=ixmin;i<ixmax;)
  320. {
  321. edge.p1[0]=i++;
  322. edge.p1[1]=iymin;
  323. while(point_array2d[iymin][i].eliminated) i++;
  324. edge.p2[0]=i;
  325. edge.p2[1]=iymin;
  326. edge_table[edge]=r+1;
  327. //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
  328. }
  329. //process left line
  330. for(int i=iymin;i<iymax;)
  331. {
  332. edge.p1[0]=ixmin;
  333. edge.p1[1]=i++;
  334. while(point_array2d[i][ixmin].eliminated) i++;
  335. edge.p2[0]=ixmin;
  336. edge.p2[1]=i;
  337. edge_table[edge]=r+1;
  338. //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
  339. }
  340. //process right line
  341. for(int i=iymin;i<iymax;)
  342. {
  343. edge.p1[0]=ixmax;
  344. edge.p1[1]=i++;
  345. while(point_array2d[i][ixmax].eliminated) i++;
  346. edge.p2[0]=ixmax;
  347. edge.p2[1]=i;
  348. edge_table[edge]=r+1;
  349. //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
  350. }
  351. }
  352. return 0;
  353. }
  354. int mesh_constructor::set_segment_rectangle(int location,int ixmin,int ixmax,int iymin,int iymax,char *label)
  355. {
  356. int segment_mark = region_array1d.size()+segment_array1d.size()+1;
  357. skeleton_segment segment;
  358. strcpy(segment.segment_label,label);
  359. segment.segment_mark=segment_mark;
  360. segment_array1d.push_back(segment);
  361. skeleton_edge edge;
  362. edge.IX = IX;
  363. edge.IY = IY;
  364. if(location==TOP)
  365. {
  366. //process top line
  367. for(int i=ixmin;i<ixmax;)
  368. {
  369. while(point_array2d[0][i].eliminated) i++;
  370. edge.p1[0]=i++;
  371. edge.p1[1]=0;
  372. while(point_array2d[0][i].eliminated) i++;
  373. edge.p2[0]=i;
  374. edge.p2[1]=0;
  375. edge_table[edge]=segment_mark;
  376. }
  377. }
  378. if(location==BOTTOM)
  379. {
  380. //process bottom line
  381. for(int i=ixmin;i<ixmax;)
  382. {
  383. while(point_array2d[IY-1][i].eliminated) i++;
  384. edge.p1[0]=i++;
  385. edge.p1[1]=IY-1;
  386. while(point_array2d[IY-1][i].eliminated) i++;
  387. edge.p2[0]=i;
  388. edge.p2[1]=IY-1;
  389. edge_table[edge]=segment_mark;
  390. }
  391. }
  392. if(location==LEFT)
  393. {
  394. //process left line
  395. for(int i=iymin;i<iymax;)
  396. {
  397. while(point_array2d[i][0].eliminated) i++;
  398. edge.p1[0]=0;
  399. edge.p1[1]=i++;
  400. while(point_array2d[i][0].eliminated) i++;
  401. edge.p2[0]=0;
  402. edge.p2[1]=i;
  403. edge_table[edge]=segment_mark;
  404. }
  405. }
  406. if(location==RIGHT)
  407. {
  408. //process right line
  409. for(int i=iymin;i<iymax;)
  410. {
  411. while(point_array2d[i][IX-1].eliminated) i++;
  412. edge.p1[0]=IX-1;
  413. edge.p1[1]=i++;
  414. while(point_array2d[i][IX-1].eliminated) i++;
  415. edge.p2[0]=IX-1;
  416. edge.p2[1]=i;
  417. edge_table[edge]=segment_mark;
  418. }
  419. }
  420. return 0;
  421. }
  422. int mesh_constructor::set_segment_rectangle(int ixmin,int ixmax,int iymin,int iymax,char *label)
  423. {
  424. int segment_mark = region_array1d.size()+segment_array1d.size()+1;
  425. skeleton_segment segment;
  426. strcpy(segment.segment_label,label);
  427. segment.segment_mark=segment_mark;
  428. segment_array1d.push_back(segment);
  429. skeleton_edge edge;
  430. edge.IX = IX;
  431. edge.IY = IY;
  432. if(iymin==iymax) //horizontal
  433. {
  434. //process horizontal line
  435. for(int i=ixmin;i<ixmax;)
  436. {
  437. while(point_array2d[iymin][i].eliminated) i++;
  438. edge.p1[0]=i++;
  439. edge.p1[1]=iymin;
  440. while(point_array2d[iymin][i].eliminated) i++;
  441. edge.p2[0]=i;
  442. edge.p2[1]=iymin;
  443. edge_table[edge]=segment_mark;
  444. }
  445. }
  446. else if(ixmin==ixmax) //vertical
  447. {
  448. //process vertical line
  449. for(int i=iymin;i<iymax;)
  450. {
  451. while(point_array2d[i][ixmin].eliminated) i++;
  452. edge.p1[0]=ixmin;
  453. edge.p1[1]=i++;
  454. while(point_array2d[i][ixmin].eliminated) i++;
  455. edge.p2[0]=ixmin;
  456. edge.p2[1]=i;
  457. edge_table[edge]=segment_mark;
  458. }
  459. }
  460. return 0;
  461. }
  462. int mesh_constructor::set_region_ellipse()
  463. {
  464. for(int r=0; r<region_array1d.size();r++)
  465. if(region_array1d[r].shape==Ellipse)
  466. {
  467. //set aux point
  468. double theta = region_array1d[r].theta;
  469. double theta0 = region_array1d[r].theta;
  470. double delta_angle = 2*3.14159265359/region_array1d[r].division;
  471. aux_point tmp_point;
  472. aux_edge tmp_edge;
  473. int offset=aux_point_array1d.size();
  474. for(int i=0;i<region_array1d[r].division;i++)
  475. {
  476. tmp_point.x = region_array1d[r].centrex + region_array1d[r].major_radii*cos(theta);
  477. tmp_point.y = region_array1d[r].centrey + region_array1d[r].minor_radii*sin(theta);
  478. theta+=delta_angle;
  479. tmp_edge.p1=aux_point_array1d.size();
  480. aux_point_array1d.push_back(tmp_point);
  481. tmp_edge.p2=aux_point_array1d.size();
  482. if(tmp_edge.p2==offset+region_array1d[r].division) tmp_edge.p2=offset;
  483. // set segment bounding
  484. tmp_edge.segment_mark=r+1;
  485. aux_edge_array1d.push_back(tmp_edge);
  486. }
  487. //do necessary elimination of neibour points to improve mesh quality.
  488. for(int i=1;i<IX-1;i++)
  489. for(int j=1;j<IY-1;j++)
  490. {
  491. double x=point_array2d[j][i].x;
  492. double y=point_array2d[j][i].y;
  493. double xc=region_array1d[r].centrex;
  494. double yc=region_array1d[r].centrey;
  495. double char_length = (fabs(point_array2d[j][i+1].x-point_array2d[j][i-1].x)+
  496. fabs(point_array2d[j+1][i].y-point_array2d[j-1][i].y))/4.0;
  497. double rsmin=pow(region_array1d[r].minor_radii-char_length,2);
  498. double rsmax=pow(region_array1d[r].minor_radii+char_length,2);
  499. double rlmin=pow(region_array1d[r].major_radii-char_length,2);
  500. double rlmax=pow(region_array1d[r].major_radii+char_length,2);
  501. if( pow(x-xc,2)/rlmax + pow(y-yc,2)/rsmax < 1 &&
  502. pow(x-xc,2)/rlmin + pow(y-yc,2)/rsmin > 1 )
  503. point_array2d[j][i].eliminated=1;
  504. }
  505. region_array1d[r].px.push_back(region_array1d[r].centrex);
  506. region_array1d[r].py.push_back(region_array1d[r].centrey);
  507. }
  508. return 0;
  509. }
  510. int mesh_constructor::do_mesh(char *tri_arg)
  511. {
  512. //set point
  513. in.numberofpoints = point_num;
  514. in.numberofpointattributes = 0;
  515. in.pointattributelist = (double *)NULL;
  516. in.pointlist = (double *) malloc(in.numberofpoints * 2 * sizeof(double));
  517. in.pointmarkerlist = (int *) malloc(in.numberofpoints * sizeof(int));
  518. double *ppointlist=in.pointlist;
  519. int *ppointmarkerlist=in.pointmarkerlist;
  520. //the points belongs to rectangle region
  521. for(int i=0;i<IX;i++)
  522. for(int j=0;j<IY;j++)
  523. if(!point_array2d[j][i].eliminated)
  524. {
  525. *ppointlist++ = point_array2d[j][i].x;
  526. *ppointlist++ = point_array2d[j][i].y;
  527. *ppointmarkerlist++ = 0;
  528. }
  529. //the points belongs to the boundary of ellipse region
  530. for(int i=0;i<aux_point_array1d.size();i++)
  531. {
  532. *ppointlist++ = aux_point_array1d[i].x;
  533. *ppointlist++ = aux_point_array1d[i].y;
  534. *ppointmarkerlist++ = 0;
  535. }
  536. //do necessarily prepare for call triangulate
  537. in.numberoftriangles = 0;
  538. in.numberofcorners = 3;
  539. in.numberoftriangleattributes = 0;
  540. in.trianglelist = (int *) NULL;
  541. in.trianglearealist = (double *) NULL;
  542. in.triangleattributelist = NULL;
  543. in.numberofsegments = edge_table.size()+aux_edge_array1d.size();
  544. in.segmentlist = (int *) malloc(in.numberofsegments * 2 * sizeof(int));
  545. in.segmentmarkerlist = (int *) malloc(in.numberofsegments * sizeof(int));
  546. int *psegmentlist = in.segmentlist;
  547. int *psegmentmarkerlist = in.segmentmarkerlist;
  548. map<skeleton_edge, int, lt_edge>::iterator pt = edge_table.begin();
  549. for(int i=0;i<edge_table.size();i++)
  550. {
  551. *psegmentlist++ = point_array2d[pt->first.p1[1]][pt->first.p1[0]].index;
  552. *psegmentlist++ = point_array2d[pt->first.p2[1]][pt->first.p2[0]].index;
  553. *psegmentmarkerlist++ = pt->second;
  554. pt++;
  555. }
  556. for(int i=0;i<aux_edge_array1d.size();i++)
  557. {
  558. *psegmentlist++ = aux_point_array1d[aux_edge_array1d[i].p1].index;
  559. *psegmentlist++ = aux_point_array1d[aux_edge_array1d[i].p2].index;
  560. *psegmentmarkerlist++ = aux_edge_array1d[i].segment_mark;
  561. pt++;
  562. }
  563. in.numberofholes = 0;
  564. in.numberofregions = region_array1d.size();
  565. in.regionlist = (double *) malloc(in.numberofregions * 4 * sizeof(double));
  566. double *pregionlist = in.regionlist;
  567. for(int i=0;i<in.numberofregions;i++)
  568. {
  569. *pregionlist++ = region_array1d[i].px[0];
  570. *pregionlist++ = region_array1d[i].py[0];
  571. *pregionlist++ = double(i);
  572. *pregionlist++ = 0;
  573. }
  574. // Refine the triangulation according to the attached
  575. // triangle area constraints.
  576. triangulate(tri_arg, &in, &out, (struct triangulateio *) NULL);
  577. for(int i=0;i<out.numberofsegments;i++)
  578. {
  579. output_edge edge;
  580. edge.index = i;
  581. edge.p1 = out.segmentlist[2*i+0];
  582. edge.p2 = out.segmentlist[2*i+1];
  583. edge.interface = -1;
  584. edge.r1 = -1;
  585. edge.r2 = -1;
  586. edge.bc_type = -1;
  587. edge.mark = out.segmentmarkerlist[i];
  588. out_edge.push_back(edge);
  589. }
  590. return 0;
  591. }
  592. typedef struct
  593. {
  594. int r1;
  595. int r2;
  596. vector<int> node_r1;
  597. vector<int> node_r2;
  598. int bc_mark;
  599. }Zone_conn;
  600. int mesh_constructor::to_cgns(const char *filename)
  601. {
  602. int fn,B,Z,C,S,BC,I,SOL,F;
  603. int size[3];
  604. double *x,*y;
  605. int *elem;
  606. char bcname[32];
  607. char conn_name[32];
  608. //this is the main part of the work. the nodes will be classified by
  609. //its region and insert to each zone
  610. int region_num = region_array1d.size(); //total region;
  611. int **local_index = new int*[region_num]; //reg_index = local_index[reg][global_index]
  612. int **local_mark = new int*[region_num]; //set local bc mark
  613. int **conn = new int*[region_num]; //for zone to zone connectivity information
  614. for(int r=0; r<region_num; r ++)
  615. {
  616. local_index[r] = new int[out.numberofpoints];
  617. local_mark[r] = new int[out.numberofpoints];
  618. conn[r] = new int[out.numberofpoints];
  619. }
  620. int *af = new int[out.numberofpoints];
  621. for(int r=0;r<region_num;r++)
  622. {
  623. int *pf = af;
  624. for(int j = 0; j < out.numberofpoints; j++)
  625. {
  626. local_index[r][j] = -1; //-1 means node not in this region
  627. local_mark[r][j] = -1; // -1 means no bc_mark
  628. *pf++ = 0; //visited flag array
  629. }
  630. region_array1d[r].node_num = 0;
  631. region_array1d[r].tri_num = 0;
  632. for(int j = 0; j < out.numberoftriangles; j++) //search for all the nodes
  633. if (int(out.triangleattributelist[j]+0.5) == r)
  634. {
  635. region_array1d[r].tri_num++;
  636. int nodeA = out.trianglelist[3*j+0];
  637. int nodeB = out.trianglelist[3*j+1];
  638. int nodeC = out.trianglelist[3*j+2];
  639. if (!af[nodeA]) { af[nodeA] = 1;local_index[r][nodeA] = region_array1d[r].node_num++; }
  640. if (!af[nodeB]) { af[nodeB] = 1;local_index[r][nodeB] = region_array1d[r].node_num++; }
  641. if (!af[nodeC]) { af[nodeC] = 1;local_index[r][nodeC] = region_array1d[r].node_num++; }
  642. }
  643. }
  644. delete [] af;
  645. for(int i = 0; i < out_edge.size(); i++) //search for all the edges
  646. for(int r=0;r<region_num;r++)
  647. {
  648. int p1 = out_edge[i].p1;
  649. int p2 = out_edge[i].p2;
  650. if(local_index[r][p1]!=-1 && local_index[r][p2]!=-1)
  651. {
  652. if(out_edge[i].r1==-1) out_edge[i].r1 = r;
  653. else {out_edge[i].interface = 1; out_edge[i].r2 = r;}
  654. region_array1d[r].boundary.push_back(i);
  655. }
  656. }
  657. // remove old file if exist
  658. remove(filename);
  659. // open CGNS file for write
  660. if(cg_open(filename,MODE_WRITE,&fn))
  661. {
  662. return 1;
  663. }
  664. // create base (can give any name)
  665. cg_base_write(fn,"GSS_Mesh",2,2,&B); /*two dimension*/
  666. // create zone
  667. for(int r=0;r<region_num;r++)
  668. {
  669. size[0] = region_array1d[r].node_num;
  670. size[1] = region_array1d[r].tri_num;
  671. size[2] = 0;
  672. x = new double[size[0]];
  673. y = new double[size[0]];
  674. elem= new int[4*size[1]];
  675. //zone name set as region name
  676. cg_zone_write(fn,B,region_array1d[r].label,size,Unstructured,&Z);
  677. cg_goto(fn,B,"Zone_t",Z,"end");
  678. cg_descriptor_write("RegionType",region_array1d[r].material);
  679. // write grid coordinates
  680. for(int j=0;j<out.numberofpoints;j++)
  681. if(local_index[r][j]>-1) //process node in this region
  682. {
  683. //convert the unit to cm
  684. x[local_index[r][j]] = out.pointlist[2*j+0]*1e-4;
  685. y[local_index[r][j]] = out.pointlist[2*j+1]*1e-4;
  686. }
  687. cg_coord_write(fn,B,Z,RealDouble,"CoordinateX",x,&C);
  688. cg_coord_write(fn,B,Z,RealDouble,"CoordinateY",y,&C);
  689. // set element connectivity here
  690. int *pelem=elem;
  691. for(int j = 0; j < out.numberoftriangles; j++)
  692. if (int(out.triangleattributelist[j]+0.5) == r) //is the triangle belongs to this region?
  693. {
  694. *pelem++ = TRI_3;
  695. *pelem++ = local_index[r][out.trianglelist[3*j+0]]+1;
  696. *pelem++ = local_index[r][out.trianglelist[3*j+1]]+1;
  697. *pelem++ = local_index[r][out.trianglelist[3*j+2]]+1;
  698. }
  699. cg_section_write(fn,B,Z,"GridElements",MIXED,1,size[1],0,elem,&S);
  700. delete [] x;
  701. delete [] y;
  702. delete [] elem;
  703. // write boundary segment
  704. int *asegment = new int[2*out.numberofpoints];
  705. int *psegment = asegment;
  706. int segrange[2];
  707. segrange[0] = size[1]+1;
  708. int csegment;
  709. vector<Zone_conn> zone_conn_array;
  710. // write labeled boundary
  711. for(int j=0;j<segment_array1d.size();j++)
  712. {
  713. if(segment_array1d[j].segment_mark > region_array1d.size()) //for labeled segment
  714. {
  715. psegment = asegment;
  716. csegment = 0;
  717. for(int k=0;k<region_array1d[r].boundary.size();k++)
  718. {
  719. int segment = region_array1d[r].boundary[k];
  720. if(out_edge[segment].mark == segment_array1d[j].segment_mark) //the edge belongs to this labeled segment
  721. {
  722. out_edge[segment].bc_type = LabeledSegment;
  723. int nodeA = out_edge[segment].p1;
  724. int nodeB = out_edge[segment].p2;
  725. //only record the nodes that belong to this region
  726. if(local_index[r][nodeA]==-1||local_index[r][nodeB]==-1 )continue;
  727. *psegment++ = local_index[r][nodeA]+1;
  728. *psegment++ = local_index[r][nodeB]+1;
  729. csegment++;
  730. local_mark[r][nodeA] = j;
  731. local_mark[r][nodeB] = j;
  732. }
  733. }
  734. if(csegment>0)
  735. {
  736. segrange[1] = segrange[0] + csegment - 1;
  737. cg_section_write(fn,B,Z,segment_array1d[j].segment_label,BAR_2,
  738. segrange[0],segrange[1],0,asegment,&S);
  739. cg_boco_write(fn,B,Z,segment_array1d[j].segment_label,BCTypeUserDefined,
  740. ElementRange,2,segrange,&BC);
  741. segrange[0] = segrange[1]+1;
  742. }
  743. }
  744. }
  745. //record zone to zone connectivity data if necessary
  746. if(region_num>1)
  747. { //build connectivity data here
  748. for(int k=0; k<region_num; k++)
  749. {
  750. if(k==r) continue;
  751. Zone_conn zone_conn;
  752. zone_conn.r1 = r;
  753. zone_conn.r2 = k;
  754. for (int s=0; s<segment_array1d.size(); s++)
  755. {
  756. for(int j=0; j<out.numberofpoints; j++)
  757. if(local_index[k][j]!=-1 && local_index[r][j]!=-1 && local_mark[r][j]==s)
  758. {
  759. zone_conn.node_r1.push_back(local_index[r][j]+1);
  760. zone_conn.node_r2.push_back(local_index[k][j]+1);
  761. }
  762. zone_conn.bc_mark = s;
  763. if(zone_conn.node_r1.size()>=2)
  764. zone_conn_array.push_back(zone_conn);
  765. zone_conn.node_r1.clear();
  766. zone_conn.node_r2.clear();
  767. }
  768. }
  769. }
  770. // write Interface as boundary
  771. for(int j=0;j<region_num;j++)
  772. {
  773. if(j!=r)
  774. {
  775. csegment = 0;
  776. psegment = asegment;
  777. for(int k=0; k<region_array1d[j].boundary.size(); k++)
  778. {
  779. //the edge belongs to region j
  780. int segment = region_array1d[j].boundary[k];
  781. int nodeA = out_edge[region_array1d[j].boundary[k]].p1;
  782. int nodeB = out_edge[region_array1d[j].boundary[k]].p2;
  783. if(local_index[r][nodeA]==-1||local_index[r][nodeB]==-1 )continue; // does the edge belongs to region r ?
  784. if(out_edge[segment].bc_type == LabeledSegment) continue; // skip labeled segment
  785. out_edge[segment].bc_type = Interface; // ok , it's an interface edge.
  786. *psegment++ = local_index[r][nodeA]+1;
  787. *psegment++ = local_index[r][nodeB]+1;
  788. local_mark[r][nodeA] = Interface;
  789. local_mark[r][nodeB] = Interface;
  790. csegment++;
  791. }
  792. if(csegment>0)
  793. {
  794. //the name is alpha ordered
  795. if(strcmp(region_array1d[r].label,region_array1d[j].label)<0)
  796. snprintf(bcname,31,"IF_%s_to_%s",region_array1d[r].label,region_array1d[j].label);
  797. else
  798. snprintf(bcname,31,"IF_%s_to_%s",region_array1d[j].label,region_array1d[r].label);
  799. segrange[1] = segrange[0] + csegment - 1;
  800. cg_section_write(fn,B,Z,bcname,BAR_2,
  801. segrange[0],segrange[1],0,asegment,&S);
  802. cg_boco_write(fn,B,Z,bcname,BCTypeUserDefined,ElementRange,2,segrange,&BC);
  803. segrange[0] = segrange[1]+1;
  804. }
  805. }
  806. }
  807. //record zone to zone connectivity data if necessary
  808. if(region_num>1)
  809. { //build connectivity data here
  810. for(int k=0; k<region_num; k++)
  811. {
  812. if(k==r) continue;
  813. Zone_conn zone_conn;
  814. zone_conn.r1 = r;
  815. zone_conn.r2 = k;
  816. for(int j=0; j<out.numberofpoints; j++)
  817. if(local_index[k][j]!=-1 && local_index[r][j]!=-1 && local_mark[r][j]==Interface)
  818. {
  819. zone_conn.node_r1.push_back(local_index[r][j]+1);
  820. zone_conn.node_r2.push_back(local_index[k][j]+1);
  821. }
  822. zone_conn.bc_mark = Interface;
  823. if(zone_conn.node_r1.size()>=2)
  824. zone_conn_array.push_back(zone_conn);
  825. zone_conn.node_r1.clear();
  826. zone_conn.node_r2.clear();
  827. }
  828. }
  829. // write other boundary segments as Neumann boundary
  830. psegment = asegment;
  831. csegment = 0;
  832. for(int j=0;j<region_array1d[r].boundary.size();j++)
  833. {
  834. int segment = region_array1d[r].boundary[j];
  835. int nodeA = out_edge[segment].p1;
  836. int nodeB = out_edge[segment].p2;
  837. //only record the nodes that belong to this region
  838. if(local_index[r][nodeA]==-1||local_index[r][nodeB]==-1 )continue;
  839. //skip labeled segment and interface
  840. if(out_edge[segment].bc_type == LabeledSegment) continue;
  841. if(out_edge[segment].bc_type == Interface) continue;
  842. *psegment++ = local_index[r][nodeA]+1;
  843. *psegment++ = local_index[r][nodeB]+1;
  844. csegment++;
  845. }
  846. if(csegment>0)
  847. {
  848. snprintf(bcname,31,"%s_Neumann",region_array1d[r].label);
  849. segrange[1] = segrange[0] + csegment - 1;
  850. cg_section_write(fn,B,Z,bcname,BAR_2,
  851. segrange[0],segrange[1],0,asegment,&S);
  852. cg_boco_write(fn,B,Z,bcname,BCTypeUserDefined,ElementRange,2,segrange,&BC);
  853. segrange[0] = segrange[1]+1;
  854. }
  855. delete [] asegment;
  856. for(int j=0; j<zone_conn_array.size(); j++)
  857. {
  858. int conn_node = zone_conn_array[j].node_r1.size();
  859. int r2 = zone_conn_array[j].r2;
  860. for(int k=0;k<conn_node;k++)
  861. {
  862. conn[r][k] = zone_conn_array[j].node_r1[k];
  863. conn[r2][k] = zone_conn_array[j].node_r2[k];
  864. }
  865. if(zone_conn_array[j].bc_mark==Interface)
  866. {
  867. //the conn_name is alpha ordered
  868. if(strcmp(region_array1d[r].label,region_array1d[r2].label)<0)
  869. snprintf(conn_name,31,"IF_%s_to_%s",region_array1d[r].label,region_array1d[r2].label);
  870. else
  871. snprintf(conn_name,31,"IF_%s_to_%s",region_array1d[r2].label,region_array1d[r].label);
  872. cg_conn_write(fn,B,Z,conn_name,Vertex, Abutting1to1,
  873. PointList, conn_node, conn[r],region_array1d[r2].label,Unstructured,
  874. PointListDonor,Integer,conn_node, conn[r2],&I);
  875. }
  876. else
  877. {
  878. cg_conn_write(fn,B,Z,segment_array1d[zone_conn_array[j].bc_mark].segment_label,Vertex, Abutting1to1,
  879. PointList, conn_node, conn[r],region_array1d[r2].label,Unstructured,
  880. PointListDonor,Integer,conn_node, conn[r2],&I);
  881. }
  882. }
  883. if(IsSingleCompSemiconductor(region_array1d[r].material))
  884. {
  885. double *mole_x;
  886. mole_x = new double[region_array1d[r].node_num];
  887. if(region_array1d[r].mole_x1_grad == MOLE_GRAD_X)
  888. {
  889. for(int j=0;j<out.numberofpoints;j++)
  890. if(local_index[r][j]>-1) //process node in this region
  891. {
  892. double x = out.pointlist[2*j+0];
  893. double mole = region_array1d[r].mole_x1
  894. + region_array1d[r].mole_x1_slope*(x-region_array1d[r].xmin);
  895. mole_x[local_index[r][j]] = dmax(mole,0);
  896. }
  897. }
  898. else if(region_array1d[r].mole_x1_grad == MOLE_GRAD_Y)
  899. {
  900. for(int j=0;j<out.numberofpoints;j++)
  901. if(local_index[r][j]>-1) //process node in this region
  902. {
  903. double y = out.pointlist[2*j+1];
  904. double mole = region_array1d[r].mole_x1
  905. - region_array1d[r].mole_x1_slope*(y-region_array1d[r].ymax);
  906. mole_x[local_index[r][j]] = dmax(mole,0);
  907. }
  908. }
  909. cg_sol_write(fn,B,Z,"Mole",Vertex,&SOL);
  910. cg_field_write(fn,B,Z,SOL,RealDouble,"mole_x",mole_x,&F);
  911. delete [] mole_x;
  912. }
  913. }
  914. //all things are done
  915. for(int r =0; r<region_num; r ++)
  916. {
  917. delete [] local_index[r];
  918. delete [] local_mark[r];
  919. delete [] conn[r];
  920. }
  921. delete [] local_index;
  922. delete [] local_mark;
  923. delete [] conn;
  924. // close CGNS file
  925. cg_close(fn);
  926. return 0;
  927. }