1 /*****************************************************************************/
2 /* 8888888 88888888 88888888 */
5 /* 8 88888888 88888888 */
8 /* 888888 888888888 888888888 */
10 /* A Two-Dimensional General Purpose Semiconductor Simulator. */
13 /* Last update: May 14, 2006 */
17 /* NINT, No.69 P.O.Box, Xi'an City, China */
19 /*****************************************************************************/
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();
49 // set up the 2d array for gird points
50 point_array2d
= new skeleton_point
*[IY
];
52 point_array2d
[i
]= new skeleton_point
[IX
];
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
;
68 mesh_constructor::~mesh_constructor()
71 delete [] point_array2d
[i
];
72 delete [] point_array2d
;
74 free(in
.pointmarkerlist
);
75 free(in
.pointattributelist
);
77 free(in
.segmentmarkerlist
);
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
)
94 if(fabs(x
-point_array2d
[0][i
].x
)<dx
)
96 dx
=fabs(x
-point_array2d
[0][i
].x
);
102 int mesh_constructor::find_skeleton_line_y(double y
)
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
);
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
;
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
;
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;
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;
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
;
184 xloc
= point_array2d
[0][0].x
+ width
;
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
;
198 erfar2
=1.5*(erfarg
+0.6);
200 erfar2
=1.5*(erfarg
-0.6);
208 erfval
=erfc(-erfarg
);
209 erfvl2
=erfc(-erfar2
);
215 // compute new node locations on this column
217 // get upper, lower, bottom current loc.
220 yupold
= point_array2d
[upperline
][i
].y
;
222 yloold
= point_array2d
[lowerline
][i
].y
;
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
;
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
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
273 double rat
=(yco
-yupold
)/spmdol
;
274 yco
=yupnew
+rat
*spmdnw
;
276 else // new grading requested
278 double ycordg
= y
+dy
;
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
285 yco
=yco
+erfvl2
*(ycordg
-yco
);
288 point_array2d
[j
][i
].y
= yco
;
296 void mesh_constructor::make_node_index()
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
++;
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);
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
;
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
;)
349 while(point_array2d
[iymax
][i
].eliminated
) i
++;
352 edge_table
[edge
]=r
+1;
353 //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
356 for(int i
=ixmin
;i
<ixmax
;)
360 while(point_array2d
[iymin
][i
].eliminated
) i
++;
363 edge_table
[edge
]=r
+1;
364 //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
367 for(int i
=iymin
;i
<iymax
;)
371 while(point_array2d
[i
][ixmin
].eliminated
) i
++;
374 edge_table
[edge
]=r
+1;
375 //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
378 for(int i
=iymin
;i
<iymax
;)
382 while(point_array2d
[i
][ixmax
].eliminated
) i
++;
385 edge_table
[edge
]=r
+1;
386 //edge_table.insert(pair<skeleton_edge const,int>(edge,r+1));
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
);
406 for(int i
=ixmin
;i
<ixmax
;)
408 while(point_array2d
[0][i
].eliminated
) i
++;
411 while(point_array2d
[0][i
].eliminated
) i
++;
414 edge_table
[edge
]=segment_mark
;
420 //process bottom line
421 for(int i
=ixmin
;i
<ixmax
;)
423 while(point_array2d
[IY
-1][i
].eliminated
) i
++;
426 while(point_array2d
[IY
-1][i
].eliminated
) i
++;
429 edge_table
[edge
]=segment_mark
;
435 for(int i
=iymin
;i
<iymax
;)
437 while(point_array2d
[i
][0].eliminated
) i
++;
440 while(point_array2d
[i
][0].eliminated
) i
++;
443 edge_table
[edge
]=segment_mark
;
449 for(int i
=iymin
;i
<iymax
;)
451 while(point_array2d
[i
][IX
-1].eliminated
) i
++;
454 while(point_array2d
[i
][IX
-1].eliminated
) i
++;
457 edge_table
[edge
]=segment_mark
;
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
);
475 if(iymin
==iymax
) //horizontal
477 //process horizontal line
478 for(int i
=ixmin
;i
<ixmax
;)
480 while(point_array2d
[iymin
][i
].eliminated
) i
++;
483 while(point_array2d
[iymin
][i
].eliminated
) i
++;
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
++;
497 while(point_array2d
[i
][ixmin
].eliminated
) i
++;
500 edge_table
[edge
]=segment_mark
;
507 int mesh_constructor::set_region_ellipse()
510 for(int r
=0; r
<region_array1d
.size();r
++)
511 if(region_array1d
[r
].shape
==Ellipse
)
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
;
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
);
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
);
561 int mesh_constructor::do_mesh(char *tri_arg
)
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
;
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
;
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
);
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
++)
638 edge
.p1
= out
.segmentlist
[2*i
+0];
639 edge
.p2
= out
.segmentlist
[2*i
+1];
644 edge
.mark
= out
.segmentmarkerlist
[i
];
645 out_edge
.push_back(edge
);
661 int mesh_constructor::to_cgns(const char *filename
)
663 int fn
,B
,Z
,C
,S
,BC
,I
,SOL
,F
;
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
++)
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
++; }
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
728 // open CGNS file for write
729 if(cg_open(filename
,MODE_WRITE
,&fn
))
733 // create base (can give any name)
734 cg_base_write(fn
,"GSS_Mesh",2,2,&B
); /*two dimension*/
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
;
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
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?
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
);
783 // write boundary segment
784 int *asegment
= new int[2*out
.numberofpoints
];
785 int *psegment
= asegment
;
787 segrange
[0] = size
[1]+1;
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
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;
811 local_mark
[r
][nodeA
] = j
;
812 local_mark
[r
][nodeB
] = j
;
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
829 { //build connectivity data here
830 for(int k
=0; k
<region_num
; 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
++)
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
;
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
);
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
895 { //build connectivity data here
896 for(int k
=0; k
<region_num
; 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
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;
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;
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
);
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
);
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
))
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
);
1010 //all things are done
1011 for(int r
=0; r
<region_num
; r
++)
1013 delete [] local_index
[r
];
1014 delete [] local_mark
[r
];
1017 delete [] local_index
;
1018 delete [] local_mark
;