more fix on Ec/Ev.
[gss-tcad.git] / src / grid / trimesh.cc
blob484b4173b1557921498630610088ff275c9aeb0f
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 /*****************************************************************************/
21 #include "typedef.h"
22 #include "skeleton.h"
23 #include "material.h"
24 #include "mathfunc.h"
25 #include <stdio.h>
26 #include <cgnslib.h>
28 mesh_constructor::mesh_constructor(skeleton_line &lx,skeleton_line &ly)
30 // init Triangle io structure.
31 in.pointlist = (double *) NULL;
32 in.pointattributelist = (double *) NULL;
33 in.pointmarkerlist = (int *) NULL;
34 in.segmentlist = (int *) NULL;
35 in.segmentmarkerlist = (int *) NULL;
36 in.regionlist = (double *)NULL;
37 out.pointlist = (double *) NULL;
38 out.pointattributelist = (double *) NULL;
39 out.pointmarkerlist = (int *) NULL;
40 out.trianglelist = (int *) NULL;
41 out.triangleattributelist = (double *) NULL;
42 out.segmentlist = (int *) NULL;
43 out.segmentmarkerlist = (int *) NULL;
45 IX = lx.point_list.size();
46 IY = ly.point_list.size();
47 point_num = IX*IY;
48 aux_point_num = 0;
49 // set up the 2d array for gird points
50 point_array2d = new skeleton_point *[IY];
51 for(int i=0;i<IY;i++)
52 point_array2d[i]= new skeleton_point [IX];
53 for(int i=0;i<IX;i++)
54 for(int j=0;j<IY;j++)
56 point_array2d[j][i].set_location(lx.point_list[i].x,ly.point_list[j].y);
59 xmin = point_array2d[0][0].x;
60 xmax = point_array2d[0][IX-1].x;
61 ymax = point_array2d[0][0].y;
62 ymin = point_array2d[IY-1][0].y;
64 width = xmax-xmin;
65 depth = ymax-ymin;
68 mesh_constructor::~mesh_constructor()
70 for(int i=0;i<IY;i++)
71 delete [] point_array2d[i];
72 delete [] point_array2d;
73 free(in.pointlist);
74 free(in.pointmarkerlist);
75 free(in.pointattributelist);
76 free(in.segmentlist);
77 free(in.segmentmarkerlist);
78 free(in.regionlist);
80 free(out.pointlist);
81 free(out.pointmarkerlist);
82 free(out.pointattributelist);
83 free(out.trianglelist);
84 free(out.triangleattributelist);
85 free(out.segmentlist);
86 free(out.segmentmarkerlist);
89 int mesh_constructor::find_skeleton_line_x(double x)
91 int ix=0;
92 double dx=1e10;
93 for(int i=0;i<IX;i++)
94 if(fabs(x-point_array2d[0][i].x)<dx)
96 dx=fabs(x-point_array2d[0][i].x);
97 ix=i;
99 return ix;
102 int mesh_constructor::find_skeleton_line_y(double y)
104 int iy=0;
105 double dy=1e10;
106 for(int i=0;i<IY;i++)
107 if(fabs(y-point_array2d[i][0].y)<dy)
109 dy=fabs(y-point_array2d[i][0].y);
110 iy=i;
112 return iy;
116 int mesh_constructor::find_move_skeleton_line_x(double x)
118 int ix=find_skeleton_line_x(x);
119 for(int j=0;j<IY;j++)
120 point_array2d[j][ix].x=x;
121 return ix;
125 int mesh_constructor::find_move_skeleton_line_y(double y)
127 int iy=find_skeleton_line_y(y);
128 for(int i=0;i<IX;i++)
129 point_array2d[iy][i].y=y;
130 return iy;
134 int mesh_constructor::x_eliminate(int ixmin,int ixmax, int iymin, int iymax)
136 for(int i=ixmin;i<=ixmax;i++)
138 int eliminate_flag = 1;
139 for(int j=max(1,iymin+1);j<min(iymax+1,IY-1);j++)
140 if(!point_array2d[j][i].eliminated)
142 if(eliminate_flag==1)
144 point_array2d[j][i].eliminated=1;
145 eliminate_flag=0;
147 else
148 eliminate_flag=1;
151 return 0;
154 int mesh_constructor::y_eliminate(int iymin,int iymax, int ixmin, int ixmax)
156 for(int j=iymin;j<=iymax;j++)
158 int eliminate_flag = 1;
159 for(int i=max(1,ixmin+1);i<min(ixmax+1,IX-1);i++)
160 if(!point_array2d[j][i].eliminated)
162 if(eliminate_flag==1)
164 point_array2d[j][i].eliminated=1;
165 eliminate_flag=0;
167 else
168 eliminate_flag=1;
171 return 0;
175 int mesh_constructor::set_spread_rectangle(int location,double width,int upperline,int lowerline,
176 double yuploc,double yloloc,double encroach,double grading)
178 double ybtanc = point_array2d[IY-1][0].y;
179 double yupanc = point_array2d[upperline][0].y;
180 double yloanc = point_array2d[lowerline][0].y;
182 double xloc,yupold,yloold,ybot;
183 if(location == LEFT)
184 xloc = point_array2d[0][0].x + width;
185 else
186 xloc = point_array2d[0][IX-1].x - width;
188 double erfarg,erfar2,erfval,erfvl2;
190 //proc colume by colume
191 for(int i=0;i<IX;i++)
193 double xco=point_array2d[0][i].x;
195 //evaluate error function for this coord.
196 erfarg=(xco-xloc)*encroach;
197 if (location==RIGHT)
198 erfar2=1.5*(erfarg+0.6);
199 else
200 erfar2=1.5*(erfarg-0.6);
201 if (location==LEFT)
203 erfval=erfc(erfarg);
204 erfvl2=erfc(erfar2);
206 else
208 erfval=erfc(-erfarg);
209 erfvl2=erfc(-erfar2);
211 erfval=erfval*0.5;
212 erfvl2=erfvl2*0.5;
215 // compute new node locations on this column
217 // get upper, lower, bottom current loc.
219 yupanc = yupold;
220 yupold = point_array2d[upperline][i].y;
221 yloanc = yloold;
222 yloold = point_array2d[lowerline][i].y;
223 ybtanc = ybot;
224 ybot = point_array2d[IY-1][i].y;
226 // compute upward shift and downward
227 double deltup=erfval*(yupold-yuploc);
228 double deltlo=erfval*(yloloc-yloold);
230 // compute new locations
231 double yupnew=yupold-deltup;
232 double ylonew=yloold+deltlo;
234 // compute old and new spreads of middle, bottom
235 double spmdol=yloold-yupold;
236 double spmdnw=spmdol+deltup+deltlo;
237 double spbtol=ybot-yloold;
238 double spbtnw=spbtol-deltlo;
240 // grading ratio
241 double y,dy;
242 if(grading!=1.0)
244 y = yupnew;
245 dy = (ylonew-yupnew)*(grading-1)/(pow(grading,lowerline-upperline)-1);
248 // scan y nodes and move as necessary
249 for(int j=0;j<IY;j++)
251 // get node number and y-coord.
252 double yco=point_array2d[j][i].y;
254 // consider top, middle, and bottom regions
256 // top region (j<upperline) shift all by deltup
257 if(j<=upperline)
259 yco=yco-deltup;
261 // bottom region, spread proportionally
262 else if (j>=lowerline)
264 double rat=(yco-yloold)/spbtol;
265 yco=ylonew+rat*spbtnw;
267 // middle region spread proportionally unless new grading
268 // is requested.
269 else
271 if(grading==1.0)
273 double rat=(yco-yupold)/spmdol;
274 yco=yupnew+rat*spmdnw;
276 else // new grading requested
278 double ycordg = y+dy;
279 y += dy;
280 dy*= grading;
281 // vary from new grading to proportional grading
282 // based on erfvl2 (2/3 the spread of erfval and
283 // centered at 30% point of erfval instead of
284 // 50% point.
285 yco=yco+erfvl2*(ycordg-yco);
288 point_array2d[j][i].y = yco;
291 return 0;
296 void mesh_constructor::make_node_index()
298 point_num=0;
299 for(int i=0;i<IX;i++)
300 for(int j=0;j<IY;j++)
302 if(!point_array2d[j][i].eliminated)
303 point_array2d[j][i].index=point_num++;
304 else
305 point_array2d[j][i].index=-1;
307 for(int i=0;i<aux_point_array1d.size();i++)
308 aux_point_array1d[i].index = point_num++;
312 int mesh_constructor::set_region_rectangle()
314 // set inner point for each region;
315 for(int i=0;i<IX-1;i++)
316 for(int j=0;j<IY-1;j++)
318 for(int k=region_array1d.size()-1;k>=0;k--)
319 if(region_array1d[k].shape==Rectangle &&
320 i>=region_array1d[k].ixmin && i+1<=region_array1d[k].ixmax &&
321 j>=region_array1d[k].iymin && j+1<=region_array1d[k].iymax)
323 region_array1d[k].px.push_back((point_array2d[j][i].x+point_array2d[j][i+1].x)/2);
324 region_array1d[k].py.push_back((point_array2d[j][i].y+point_array2d[j+1][i].y)/2);
325 break;
328 // set segment bounding
329 map<skeleton_edge, int, lt_edge>::iterator pt;
330 for(int r=0;r<region_array1d.size();r++)
332 if(region_array1d[r].shape!=Rectangle) continue;
333 int ixmin = region_array1d[r].ixmin;
334 int ixmax = region_array1d[r].ixmax;
335 int iymin = region_array1d[r].iymin;
336 int iymax = region_array1d[r].iymax;
337 skeleton_edge edge;
338 edge.IX = IX;
339 edge.IY = IY;
340 skeleton_segment segment;
341 sprintf(segment.segment_label,"%s_Neumann",region_array1d[r].label);
342 segment.segment_mark=r+1;
343 segment_array1d.push_back(segment);
344 //process bottom line
345 for(int i=ixmin;i<ixmax;)
347 edge.p1[0]=i++;
348 edge.p1[1]=iymax;
349 while(point_array2d[iymax][i].eliminated) i++;
350 edge.p2[0]=i;
351 edge.p2[1]=iymax;
352 edge_table[edge]=r+1;
353 //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
355 //process top line
356 for(int i=ixmin;i<ixmax;)
358 edge.p1[0]=i++;
359 edge.p1[1]=iymin;
360 while(point_array2d[iymin][i].eliminated) i++;
361 edge.p2[0]=i;
362 edge.p2[1]=iymin;
363 edge_table[edge]=r+1;
364 //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
366 //process left line
367 for(int i=iymin;i<iymax;)
369 edge.p1[0]=ixmin;
370 edge.p1[1]=i++;
371 while(point_array2d[i][ixmin].eliminated) i++;
372 edge.p2[0]=ixmin;
373 edge.p2[1]=i;
374 edge_table[edge]=r+1;
375 //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
377 //process right line
378 for(int i=iymin;i<iymax;)
380 edge.p1[0]=ixmax;
381 edge.p1[1]=i++;
382 while(point_array2d[i][ixmax].eliminated) i++;
383 edge.p2[0]=ixmax;
384 edge.p2[1]=i;
385 edge_table[edge]=r+1;
386 //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
389 return 0;
393 int mesh_constructor::set_segment_rectangle(int location,int ixmin,int ixmax,int iymin,int iymax,char *label)
395 int segment_mark = region_array1d.size()+segment_array1d.size()+1;
396 skeleton_segment segment;
397 strcpy(segment.segment_label,label);
398 segment.segment_mark=segment_mark;
399 segment_array1d.push_back(segment);
400 skeleton_edge edge;
401 edge.IX = IX;
402 edge.IY = IY;
403 if(location==TOP)
405 //process top line
406 for(int i=ixmin;i<ixmax;)
408 while(point_array2d[0][i].eliminated) i++;
409 edge.p1[0]=i++;
410 edge.p1[1]=0;
411 while(point_array2d[0][i].eliminated) i++;
412 edge.p2[0]=i;
413 edge.p2[1]=0;
414 edge_table[edge]=segment_mark;
418 if(location==BOTTOM)
420 //process bottom line
421 for(int i=ixmin;i<ixmax;)
423 while(point_array2d[IY-1][i].eliminated) i++;
424 edge.p1[0]=i++;
425 edge.p1[1]=IY-1;
426 while(point_array2d[IY-1][i].eliminated) i++;
427 edge.p2[0]=i;
428 edge.p2[1]=IY-1;
429 edge_table[edge]=segment_mark;
432 if(location==LEFT)
434 //process left line
435 for(int i=iymin;i<iymax;)
437 while(point_array2d[i][0].eliminated) i++;
438 edge.p1[0]=0;
439 edge.p1[1]=i++;
440 while(point_array2d[i][0].eliminated) i++;
441 edge.p2[0]=0;
442 edge.p2[1]=i;
443 edge_table[edge]=segment_mark;
446 if(location==RIGHT)
448 //process right line
449 for(int i=iymin;i<iymax;)
451 while(point_array2d[i][IX-1].eliminated) i++;
452 edge.p1[0]=IX-1;
453 edge.p1[1]=i++;
454 while(point_array2d[i][IX-1].eliminated) i++;
455 edge.p2[0]=IX-1;
456 edge.p2[1]=i;
457 edge_table[edge]=segment_mark;
461 return 0;
465 int mesh_constructor::set_segment_rectangle(int ixmin,int ixmax,int iymin,int iymax,char *label)
467 int segment_mark = region_array1d.size()+segment_array1d.size()+1;
468 skeleton_segment segment;
469 strcpy(segment.segment_label,label);
470 segment.segment_mark=segment_mark;
471 segment_array1d.push_back(segment);
472 skeleton_edge edge;
473 edge.IX = IX;
474 edge.IY = IY;
475 if(iymin==iymax) //horizontal
477 //process horizontal line
478 for(int i=ixmin;i<ixmax;)
480 while(point_array2d[iymin][i].eliminated) i++;
481 edge.p1[0]=i++;
482 edge.p1[1]=iymin;
483 while(point_array2d[iymin][i].eliminated) i++;
484 edge.p2[0]=i;
485 edge.p2[1]=iymin;
486 edge_table[edge]=segment_mark;
489 else if(ixmin==ixmax) //vertical
491 //process vertical line
492 for(int i=iymin;i<iymax;)
494 while(point_array2d[i][ixmin].eliminated) i++;
495 edge.p1[0]=ixmin;
496 edge.p1[1]=i++;
497 while(point_array2d[i][ixmin].eliminated) i++;
498 edge.p2[0]=ixmin;
499 edge.p2[1]=i;
500 edge_table[edge]=segment_mark;
504 return 0;
507 int mesh_constructor::set_region_ellipse()
510 for(int r=0; r<region_array1d.size();r++)
511 if(region_array1d[r].shape==Ellipse)
513 //set aux point
514 double theta = region_array1d[r].theta;
515 double theta0 = region_array1d[r].theta;
516 double delta_angle = 2*3.14159265359/region_array1d[r].division;
517 aux_point tmp_point;
518 aux_edge tmp_edge;
519 int offset=aux_point_array1d.size();
520 for(int i=0;i<region_array1d[r].division;i++)
522 tmp_point.x = region_array1d[r].centrex + region_array1d[r].major_radii*cos(theta);
523 tmp_point.y = region_array1d[r].centrey + region_array1d[r].minor_radii*sin(theta);
524 theta+=delta_angle;
525 tmp_edge.p1=aux_point_array1d.size();
526 aux_point_array1d.push_back(tmp_point);
527 tmp_edge.p2=aux_point_array1d.size();
528 if(tmp_edge.p2==offset+region_array1d[r].division) tmp_edge.p2=offset;
529 // set segment bounding
530 tmp_edge.segment_mark=r+1;
531 aux_edge_array1d.push_back(tmp_edge);
533 //do necessary elimination of neibour points to improve mesh quality.
534 for(int i=1;i<IX-1;i++)
535 for(int j=1;j<IY-1;j++)
537 double x=point_array2d[j][i].x;
538 double y=point_array2d[j][i].y;
539 double xc=region_array1d[r].centrex;
540 double yc=region_array1d[r].centrey;
541 double char_length = (fabs(point_array2d[j][i+1].x-point_array2d[j][i-1].x)+
542 fabs(point_array2d[j+1][i].y-point_array2d[j-1][i].y))/4.0;
543 double rsmin=pow(region_array1d[r].minor_radii-char_length,2);
544 double rsmax=pow(region_array1d[r].minor_radii+char_length,2);
545 double rlmin=pow(region_array1d[r].major_radii-char_length,2);
546 double rlmax=pow(region_array1d[r].major_radii+char_length,2);
547 if( pow(x-xc,2)/rlmax + pow(y-yc,2)/rsmax < 1 &&
548 pow(x-xc,2)/rlmin + pow(y-yc,2)/rsmin > 1 )
549 point_array2d[j][i].eliminated=1;
552 region_array1d[r].px.push_back(region_array1d[r].centrex);
553 region_array1d[r].py.push_back(region_array1d[r].centrey);
556 return 0;
561 int mesh_constructor::do_mesh(char *tri_arg)
563 //set point
564 in.numberofpoints = point_num;
565 in.numberofpointattributes = 0;
566 in.pointattributelist = (double *)NULL;
567 in.pointlist = (double *) malloc(in.numberofpoints * 2 * sizeof(double));
568 in.pointmarkerlist = (int *) malloc(in.numberofpoints * sizeof(int));
569 double *ppointlist=in.pointlist;
570 int *ppointmarkerlist=in.pointmarkerlist;
571 //the points belongs to rectangle region
572 for(int i=0;i<IX;i++)
573 for(int j=0;j<IY;j++)
574 if(!point_array2d[j][i].eliminated)
576 *ppointlist++ = point_array2d[j][i].x;
577 *ppointlist++ = point_array2d[j][i].y;
578 *ppointmarkerlist++ = 0;
580 //the points belongs to the boundary of ellipse region
581 for(int i=0;i<aux_point_array1d.size();i++)
583 *ppointlist++ = aux_point_array1d[i].x;
584 *ppointlist++ = aux_point_array1d[i].y;
585 *ppointmarkerlist++ = 0;
588 //do necessarily prepare for call triangulate
589 in.numberoftriangles = 0;
590 in.numberofcorners = 3;
591 in.numberoftriangleattributes = 0;
592 in.trianglelist = (int *) NULL;
593 in.trianglearealist = (double *) NULL;
594 in.triangleattributelist = NULL;
596 in.numberofsegments = edge_table.size()+aux_edge_array1d.size();
597 in.segmentlist = (int *) malloc(in.numberofsegments * 2 * sizeof(int));
598 in.segmentmarkerlist = (int *) malloc(in.numberofsegments * sizeof(int));
599 int *psegmentlist = in.segmentlist;
600 int *psegmentmarkerlist = in.segmentmarkerlist;
601 map<skeleton_edge, int, lt_edge>::iterator pt = edge_table.begin();
602 for(int i=0;i<edge_table.size();i++)
604 *psegmentlist++ = point_array2d[pt->first.p1[1]][pt->first.p1[0]].index;
605 *psegmentlist++ = point_array2d[pt->first.p2[1]][pt->first.p2[0]].index;
606 *psegmentmarkerlist++ = pt->second;
607 pt++;
609 for(int i=0;i<aux_edge_array1d.size();i++)
611 *psegmentlist++ = aux_point_array1d[aux_edge_array1d[i].p1].index;
612 *psegmentlist++ = aux_point_array1d[aux_edge_array1d[i].p2].index;
613 *psegmentmarkerlist++ = aux_edge_array1d[i].segment_mark;
614 pt++;
617 in.numberofholes = 0;
618 in.numberofregions = region_array1d.size();
619 in.regionlist = (double *) malloc(in.numberofregions * 4 * sizeof(double));
620 double *pregionlist = in.regionlist;
621 for(int i=0;i<in.numberofregions;i++)
623 *pregionlist++ = region_array1d[i].px[0];
624 *pregionlist++ = region_array1d[i].py[0];
625 *pregionlist++ = double(i);
626 *pregionlist++ = 0;
629 // Refine the triangulation according to the attached
630 // triangle area constraints.
632 triangulate(tri_arg, &in, &out, (struct triangulateio *) NULL);
634 for(int i=0;i<out.numberofsegments;i++)
636 output_edge edge;
637 edge.index = i;
638 edge.p1 = out.segmentlist[2*i+0];
639 edge.p2 = out.segmentlist[2*i+1];
640 edge.interface = -1;
641 edge.r1 = -1;
642 edge.r2 = -1;
643 edge.bc_type = -1;
644 edge.mark = out.segmentmarkerlist[i];
645 out_edge.push_back(edge);
648 return 0;
651 typedef struct
653 int r1;
654 int r2;
655 vector<int> node_r1;
656 vector<int> node_r2;
657 int bc_mark;
658 }Zone_conn;
661 int mesh_constructor::to_cgns(const char *filename)
663 int fn,B,Z,C,S,BC,I,SOL,F;
664 int size[3];
665 double *x,*y;
666 int *elem;
667 char bcname[32];
668 char conn_name[32];
669 //this is the main part of the work. the nodes will be classified by
670 //its region and insert to each zone
672 int region_num = region_array1d.size(); //total region;
673 int **local_index = new int*[region_num]; //reg_index = local_index[reg][global_index]
674 int **local_mark = new int*[region_num]; //set local bc mark
675 int **conn = new int*[region_num]; //for zone to zone connectivity information
677 for(int r=0; r<region_num; r ++)
679 local_index[r] = new int[out.numberofpoints];
680 local_mark[r] = new int[out.numberofpoints];
681 conn[r] = new int[out.numberofpoints];
684 int *af = new int[out.numberofpoints];
686 for(int r=0;r<region_num;r++)
688 int *pf = af;
689 for(int j = 0; j < out.numberofpoints; j++)
691 local_index[r][j] = -1; //-1 means node not in this region
692 local_mark[r][j] = -1; // -1 means no bc_mark
693 *pf++ = 0; //visited flag array
695 region_array1d[r].node_num = 0;
696 region_array1d[r].tri_num = 0;
698 for(int j = 0; j < out.numberoftriangles; j++) //search for all the nodes
699 if (int(out.triangleattributelist[j]+0.5) == r)
701 region_array1d[r].tri_num++;
702 int nodeA = out.trianglelist[3*j+0];
703 int nodeB = out.trianglelist[3*j+1];
704 int nodeC = out.trianglelist[3*j+2];
705 if (!af[nodeA]) { af[nodeA] = 1;local_index[r][nodeA] = region_array1d[r].node_num++; }
706 if (!af[nodeB]) { af[nodeB] = 1;local_index[r][nodeB] = region_array1d[r].node_num++; }
707 if (!af[nodeC]) { af[nodeC] = 1;local_index[r][nodeC] = region_array1d[r].node_num++; }
710 delete [] af;
712 for(int i = 0; i < out_edge.size(); i++) //search for all the edges
713 for(int r=0;r<region_num;r++)
715 int p1 = out_edge[i].p1;
716 int p2 = out_edge[i].p2;
717 if(local_index[r][p1]!=-1 && local_index[r][p2]!=-1)
719 if(out_edge[i].r1==-1) out_edge[i].r1 = r;
720 else {out_edge[i].interface = 1; out_edge[i].r2 = r;}
721 region_array1d[r].boundary.push_back(i);
725 // remove old file if exist
726 remove(filename);
728 // open CGNS file for write
729 if(cg_open(filename,MODE_WRITE,&fn))
731 return 1;
733 // create base (can give any name)
734 cg_base_write(fn,"GSS_Mesh",2,2,&B); /*two dimension*/
736 // create zone
737 for(int r=0;r<region_num;r++)
740 size[0] = region_array1d[r].node_num;
741 size[1] = region_array1d[r].tri_num;
742 size[2] = 0;
744 x = new double[size[0]];
745 y = new double[size[0]];
746 elem= new int[4*size[1]];
747 //zone name set as region name
748 cg_zone_write(fn,B,region_array1d[r].label,size,Unstructured,&Z);
750 cg_goto(fn,B,"Zone_t",Z,"end");
751 cg_descriptor_write("RegionType",region_array1d[r].material);
752 // write grid coordinates
753 for(int j=0;j<out.numberofpoints;j++)
754 if(local_index[r][j]>-1) //process node in this region
756 //convert the unit to cm
757 x[local_index[r][j]] = out.pointlist[2*j+0]*1e-4;
758 y[local_index[r][j]] = out.pointlist[2*j+1]*1e-4;
761 cg_coord_write(fn,B,Z,RealDouble,"CoordinateX",x,&C);
762 cg_coord_write(fn,B,Z,RealDouble,"CoordinateY",y,&C);
764 // set element connectivity here
766 int *pelem=elem;
767 for(int j = 0; j < out.numberoftriangles; j++)
768 if (int(out.triangleattributelist[j]+0.5) == r) //is the triangle belongs to this region?
770 *pelem++ = TRI_3;
771 *pelem++ = local_index[r][out.trianglelist[3*j+0]]+1;
772 *pelem++ = local_index[r][out.trianglelist[3*j+1]]+1;
773 *pelem++ = local_index[r][out.trianglelist[3*j+2]]+1;
776 cg_section_write(fn,B,Z,"GridElements",MIXED,1,size[1],0,elem,&S);
778 delete [] x;
779 delete [] y;
780 delete [] elem;
783 // write boundary segment
784 int *asegment = new int[2*out.numberofpoints];
785 int *psegment = asegment;
786 int segrange[2];
787 segrange[0] = size[1]+1;
788 int csegment;
789 vector<Zone_conn> zone_conn_array;
790 // write labeled boundary
791 for(int j=0;j<segment_array1d.size();j++)
793 if(segment_array1d[j].segment_mark > region_array1d.size()) //for labeled segment
795 psegment = asegment;
796 csegment = 0;
797 for(int k=0;k<region_array1d[r].boundary.size();k++)
799 int segment = region_array1d[r].boundary[k];
800 if(out_edge[segment].mark == segment_array1d[j].segment_mark) //the edge belongs to this labeled segment
802 out_edge[segment].bc_type = LabeledSegment;
803 int nodeA = out_edge[segment].p1;
804 int nodeB = out_edge[segment].p2;
805 //only record the nodes that belong to this region
806 if(local_index[r][nodeA]==-1||local_index[r][nodeB]==-1 )continue;
808 *psegment++ = local_index[r][nodeA]+1;
809 *psegment++ = local_index[r][nodeB]+1;
810 csegment++;
811 local_mark[r][nodeA] = j;
812 local_mark[r][nodeB] = j;
816 if(csegment>0)
818 segrange[1] = segrange[0] + csegment - 1;
819 cg_section_write(fn,B,Z,segment_array1d[j].segment_label,BAR_2,
820 segrange[0],segrange[1],0,asegment,&S);
821 cg_boco_write(fn,B,Z,segment_array1d[j].segment_label,BCTypeUserDefined,
822 ElementRange,2,segrange,&BC);
823 segrange[0] = segrange[1]+1;
827 //record zone to zone connectivity data if necessary
828 if(region_num>1)
829 { //build connectivity data here
830 for(int k=0; k<region_num; k++)
832 if(k==r) continue;
833 Zone_conn zone_conn;
834 zone_conn.r1 = r;
835 zone_conn.r2 = k;
836 for (int s=0; s<segment_array1d.size(); s++)
838 for(int j=0; j<out.numberofpoints; j++)
839 if(local_index[k][j]!=-1 && local_index[r][j]!=-1 && local_mark[r][j]==s)
841 zone_conn.node_r1.push_back(local_index[r][j]+1);
842 zone_conn.node_r2.push_back(local_index[k][j]+1);
844 zone_conn.bc_mark = s;
845 if(zone_conn.node_r1.size()>=2)
846 zone_conn_array.push_back(zone_conn);
847 zone_conn.node_r1.clear();
848 zone_conn.node_r2.clear();
853 // write Interface as boundary
854 for(int j=0;j<region_num;j++)
856 if(j!=r)
858 csegment = 0;
859 psegment = asegment;
860 for(int k=0; k<region_array1d[j].boundary.size(); k++)
862 //the edge belongs to region j
863 int segment = region_array1d[j].boundary[k];
864 int nodeA = out_edge[region_array1d[j].boundary[k]].p1;
865 int nodeB = out_edge[region_array1d[j].boundary[k]].p2;
866 if(local_index[r][nodeA]==-1||local_index[r][nodeB]==-1 )continue; // does the edge belongs to region r ?
867 if(out_edge[segment].bc_type == LabeledSegment) continue; // skip labeled segment
868 out_edge[segment].bc_type = Interface; // ok , it's an interface edge.
869 *psegment++ = local_index[r][nodeA]+1;
870 *psegment++ = local_index[r][nodeB]+1;
871 local_mark[r][nodeA] = Interface;
872 local_mark[r][nodeB] = Interface;
873 csegment++;
876 if(csegment>0)
878 //the name is alpha ordered
879 if(strcmp(region_array1d[r].label,region_array1d[j].label)<0)
880 snprintf(bcname,31,"IF_%s_to_%s",region_array1d[r].label,region_array1d[j].label);
881 else
882 snprintf(bcname,31,"IF_%s_to_%s",region_array1d[j].label,region_array1d[r].label);
884 segrange[1] = segrange[0] + csegment - 1;
885 cg_section_write(fn,B,Z,bcname,BAR_2,
886 segrange[0],segrange[1],0,asegment,&S);
887 cg_boco_write(fn,B,Z,bcname,BCTypeUserDefined,ElementRange,2,segrange,&BC);
888 segrange[0] = segrange[1]+1;
893 //record zone to zone connectivity data if necessary
894 if(region_num>1)
895 { //build connectivity data here
896 for(int k=0; k<region_num; k++)
898 if(k==r) continue;
899 Zone_conn zone_conn;
900 zone_conn.r1 = r;
901 zone_conn.r2 = k;
902 for(int j=0; j<out.numberofpoints; j++)
903 if(local_index[k][j]!=-1 && local_index[r][j]!=-1 && local_mark[r][j]==Interface)
905 zone_conn.node_r1.push_back(local_index[r][j]+1);
906 zone_conn.node_r2.push_back(local_index[k][j]+1);
908 zone_conn.bc_mark = Interface;
909 if(zone_conn.node_r1.size()>=2)
910 zone_conn_array.push_back(zone_conn);
911 zone_conn.node_r1.clear();
912 zone_conn.node_r2.clear();
916 // write other boundary segments as Neumann boundary
917 psegment = asegment;
918 csegment = 0;
920 for(int j=0;j<region_array1d[r].boundary.size();j++)
922 int segment = region_array1d[r].boundary[j];
923 int nodeA = out_edge[segment].p1;
924 int nodeB = out_edge[segment].p2;
925 //only record the nodes that belong to this region
926 if(local_index[r][nodeA]==-1||local_index[r][nodeB]==-1 )continue;
927 //skip labeled segment and interface
928 if(out_edge[segment].bc_type == LabeledSegment) continue;
929 if(out_edge[segment].bc_type == Interface) continue;
930 *psegment++ = local_index[r][nodeA]+1;
931 *psegment++ = local_index[r][nodeB]+1;
932 csegment++;
934 if(csegment>0)
936 snprintf(bcname,31,"%s_Neumann",region_array1d[r].label);
937 segrange[1] = segrange[0] + csegment - 1;
938 cg_section_write(fn,B,Z,bcname,BAR_2,
939 segrange[0],segrange[1],0,asegment,&S);
940 cg_boco_write(fn,B,Z,bcname,BCTypeUserDefined,ElementRange,2,segrange,&BC);
941 segrange[0] = segrange[1]+1;
943 delete [] asegment;
946 for(int j=0; j<zone_conn_array.size(); j++)
949 int conn_node = zone_conn_array[j].node_r1.size();
950 int r2 = zone_conn_array[j].r2;
951 for(int k=0;k<conn_node;k++)
953 conn[r][k] = zone_conn_array[j].node_r1[k];
954 conn[r2][k] = zone_conn_array[j].node_r2[k];
956 if(zone_conn_array[j].bc_mark==Interface)
958 //the conn_name is alpha ordered
959 if(strcmp(region_array1d[r].label,region_array1d[r2].label)<0)
960 snprintf(conn_name,31,"IF_%s_to_%s",region_array1d[r].label,region_array1d[r2].label);
961 else
962 snprintf(conn_name,31,"IF_%s_to_%s",region_array1d[r2].label,region_array1d[r].label);
963 cg_conn_write(fn,B,Z,conn_name,Vertex, Abutting1to1,
964 PointList, conn_node, conn[r],region_array1d[r2].label,Unstructured,
965 PointListDonor,Integer,conn_node, conn[r2],&I);
967 else
969 cg_conn_write(fn,B,Z,segment_array1d[zone_conn_array[j].bc_mark].segment_label,Vertex, Abutting1to1,
970 PointList, conn_node, conn[r],region_array1d[r2].label,Unstructured,
971 PointListDonor,Integer,conn_node, conn[r2],&I);
975 if(IsSingleCompSemiconductor(region_array1d[r].material))
977 double *mole_x;
978 mole_x = new double[region_array1d[r].node_num];
979 if(region_array1d[r].mole_x1_grad == MOLE_GRAD_X)
981 for(int j=0;j<out.numberofpoints;j++)
982 if(local_index[r][j]>-1) //process node in this region
984 double x = out.pointlist[2*j+0];
985 double mole = region_array1d[r].mole_x1
986 + region_array1d[r].mole_x1_slope*(x-region_array1d[r].xmin);
987 mole_x[local_index[r][j]] = dmax(mole,0);
991 else if(region_array1d[r].mole_x1_grad == MOLE_GRAD_Y)
993 for(int j=0;j<out.numberofpoints;j++)
994 if(local_index[r][j]>-1) //process node in this region
996 double y = out.pointlist[2*j+1];
997 double mole = region_array1d[r].mole_x1
998 - region_array1d[r].mole_x1_slope*(y-region_array1d[r].ymax);
999 mole_x[local_index[r][j]] = dmax(mole,0);
1003 cg_sol_write(fn,B,Z,"Mole",Vertex,&SOL);
1004 cg_field_write(fn,B,Z,SOL,RealDouble,"mole_x",mole_x,&F);
1005 delete [] mole_x;
1010 //all things are done
1011 for(int r =0; r<region_num; r ++)
1013 delete [] local_index[r];
1014 delete [] local_mark[r];
1015 delete [] conn[r];
1017 delete [] local_index;
1018 delete [] local_mark;
1019 delete [] conn;
1020 // close CGNS file
1021 cg_close(fn);
1022 return 0;