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 29, 2006 */
17 /* NINT, No.69 P.O.Box, Xi'an City, China */
19 /*****************************************************************************/
31 /* ----------------------------------------------------------------------------
32 * ZONE::build_tricell_data: This function compute circle center, and the distance between
33 * the circle center and each edge. if circle center locates out of the triangle, negtive the
34 * corresponding distance.
36 int ZONE::build_tricell_data()
38 double PI
=3.14159265358979323846;
39 for(int i
=0;i
<datri
.size();i
++)
41 double x1
,y1
,x2
,y2
,x3
,y3
;
43 x1
= danode
[datri
[i
].node
[0]].x
;
44 y1
= danode
[datri
[i
].node
[0]].y
;
45 x2
= danode
[datri
[i
].node
[1]].x
;
46 y2
= danode
[datri
[i
].node
[1]].y
;
47 x3
= danode
[datri
[i
].node
[2]].x
;
48 y3
= danode
[datri
[i
].node
[2]].y
;
49 datri
[i
].edge_len
[0] = a
= Distance(x3
,y3
,x2
,y2
);
50 datri
[i
].edge_len
[1] = b
= Distance(x1
,y1
,x3
,y3
);
51 datri
[i
].edge_len
[2] = c
= Distance(x1
,y1
,x2
,y2
);
52 datri
[i
].angle
[0] = acos((b
*b
+c
*c
-a
*a
)/(2*b
*c
));
53 datri
[i
].angle
[1] = acos((c
*c
+a
*a
-b
*b
)/(2*c
*a
));
54 datri
[i
].angle
[2] = acos((a
*a
+b
*b
-c
*c
)/(2*a
*b
));
55 datri
[i
].area
= TriArea(x1
,y1
,x2
,y2
,x3
,y3
);
56 if(CircleCenter(x1
,y1
,x2
,y2
,x3
,y3
,datri
[i
].xc
,datri
[i
].yc
))
58 sprintf(log_buf
,"warning! CircleCenter: the three nodes of Tri %d of zone %d coplanar.\n",i
,zone_index
);
61 datri
[i
].d
[0] = DistancePointLine(x2
,y2
,x3
,y3
,datri
[i
].xc
,datri
[i
].yc
);
62 datri
[i
].d
[1] = DistancePointLine(x1
,y1
,x3
,y3
,datri
[i
].xc
,datri
[i
].yc
);
63 datri
[i
].d
[2] = DistancePointLine(x1
,y1
,x2
,y2
,datri
[i
].xc
,datri
[i
].yc
);
64 if(CompAngle(x3
,y3
,x1
,y1
,x2
,y2
)>PI
/2) datri
[i
].d
[0]*=-1;
65 if(CompAngle(x1
,y1
,x2
,y2
,x3
,y3
)>PI
/2) datri
[i
].d
[1]*=-1;
66 if(CompAngle(x2
,y2
,x3
,y3
,x1
,y1
)>PI
/2) datri
[i
].d
[2]*=-1;
67 datri
[i
].s
[0] = 0.5*datri
[i
].edge_len
[0]*datri
[i
].d
[0];
68 datri
[i
].s
[1] = 0.5*datri
[i
].edge_len
[1]*datri
[i
].d
[1];
69 datri
[i
].s
[2] = 0.5*datri
[i
].edge_len
[2]*datri
[i
].d
[2];
70 for(int j
=0;j
<dasegment
.size();j
++)
72 if(dasegment
[j
].get_edge_bc_index(datri
[i
].node
[0],datri
[i
].node
[1]))
73 datri
[i
].bc
[2] = dasegment
[j
].bc_index
;
74 if(dasegment
[j
].get_edge_bc_index(datri
[i
].node
[1],datri
[i
].node
[2]))
75 datri
[i
].bc
[0] = dasegment
[j
].bc_index
;
76 if(dasegment
[j
].get_edge_bc_index(datri
[i
].node
[2],datri
[i
].node
[0]))
77 datri
[i
].bc
[1] = dasegment
[j
].bc_index
;
83 /* ----------------------------------------------------------------------------
84 * ZONE::setup_voronoicell: This function setup voronoicell data structure
85 * the adjacency infomation will be build here.
86 * if the Triangle is count clock wise ordered, this function works well
97 int ZONE::setup_voronoicell()
101 vector
<ATABLE
> **zone_atable
;
102 zone_atable
= new vector
<ATABLE
>*[danode
.size()];
103 for(int i
=0;i
<danode
.size();i
++)
104 zone_atable
[i
] = new vector
<ATABLE
>;
107 tmp_atable
.flag1
=0; tmp_atable
.flag2
=0;
110 davcell
.Init(danode
.size()); //init davcell, cell num = node num
112 //insert triangle into each node's adjacent table
113 for(int i
=0;i
<datri
.size();i
++)
117 tmp_atable
.node1
= datri
[i
].node
[1];
118 tmp_atable
.node2
= datri
[i
].node
[2];
119 zone_atable
[datri
[i
].node
[0]]->push_back(tmp_atable
);
121 tmp_atable
.node1
= datri
[i
].node
[2];
122 tmp_atable
.node2
= datri
[i
].node
[0];
123 zone_atable
[datri
[i
].node
[1]]->push_back(tmp_atable
);
125 tmp_atable
.node1
= datri
[i
].node
[0];
126 tmp_atable
.node2
= datri
[i
].node
[1];
127 zone_atable
[datri
[i
].node
[2]]->push_back(tmp_atable
);
134 for(int i
=0;i
<davcell
.size();i
++)
136 vector
<ATABLE
>::iterator pt
= zone_atable
[i
]->begin();
141 //search it's neighbor triangles. begin from zone_atable[0]
142 //clock wise search.push the nodes into a stack
143 clockw
.push(v1
); pt
->flag1
=1;
144 for(int num
=0;num
<zone_atable
[i
]->size();num
++)
145 for(pt
=zone_atable
[i
]->begin();pt
!=zone_atable
[i
]->end();pt
++)
146 if(pt
->node2
==v1
&&pt
->flag1
==0&&pt
->flag2
==0)
149 v1
=pt
->node1
; pt
->flag1
=1; pt
->flag2
=1;
150 if(v1
!=v2
) clockw
.push(v1
);
153 //count clock wise search, push into a queue
154 pt
= zone_atable
[i
]->begin();
158 for(int num
=0;num
<zone_atable
[i
]->size();num
++)
159 for(pt
=zone_atable
[i
]->begin();pt
!=zone_atable
[i
]->end();pt
++)
160 if(pt
->node1
==v2
&&pt
->flag1
==0&&pt
->flag2
==0)
162 v2
=pt
->node2
; pt
->flag1
=1; pt
->flag2
=1;
165 //alloc memory for each vcell, set pointers,cp bc_index form danode
166 VoronoiCell
*pCell
= davcell
.GetPointer(i
);
167 int clockwsize
= clockw
.size();
168 int cclockwsize
= cclockw
.size();
169 int neighbor
= clockw
.size() + cclockw
.size();
171 pCell
->nb_num
= neighbor
;
172 pCell
->bc_index
= danode
[i
].bc_index
;
173 pCell
->nb_array
= new int[neighbor
];
174 pCell
->elen
= new double[neighbor
];
175 pCell
->ilen
= new double[neighbor
];
176 pCell
->angle
= new double[neighbor
];
177 pCell
->celledge
= new int[neighbor
];
178 pCell
->inb_array
= new int[neighbor
];
180 for(int j
=0;j
<pCell
->nb_num
;j
++) pCell
->celledge
[j
] = -1;
182 //now read the neighbors of this node in count clock order
183 for(int j
=0;j
<clockwsize
;j
++)
185 pCell
->nb_array
[j
] = clockw
.top();
188 for(int j
=clockwsize
;j
<cclockwsize
+clockwsize
;j
++)
190 pCell
->nb_array
[j
] = cclockw
.front();
194 adjtabsize
+= neighbor
;
198 //adjtabsize equal to vedge*2
200 davedge
.resize(adjtabsize
/2);
203 //compute invert index of neighbour nodes
204 //i == davcell[j].nb_array[davcell[i].inb_array[j]]
205 for(int i
=0;i
<davcell
.size();i
++)
207 VoronoiCell
*pCell
= davcell
.GetPointer(i
);
208 for(int j
=0;j
<davcell
[i
].nb_num
;j
++)
209 for(int k
=0;k
<davcell
[davcell
[i
].nb_array
[j
]].nb_num
;k
++)
211 if(i
==davcell
[davcell
[i
].nb_array
[j
]].nb_array
[k
])
212 pCell
->inb_array
[j
]=k
;
216 //not needed any more, free them.
217 for(int i
=0;i
<davcell
.size();i
++)
218 delete zone_atable
[i
];
219 delete [] zone_atable
;
224 /* ----------------------------------------------------------------------------
225 * ZONE::setup_voronoicell: This function setup voronoicell data structure
226 * the adjacency infomation will be build here.
227 * if the Triangle is not count clock wise ordered, but the zone is rectangular.
228 * please use this function.
231 int ZONE::setup_voronoicell()
234 list<int>::iterator pt;
235 list<int>**pneighborlist;
237 davcell.Init(danode.size()); //init davcell, cell num = node num
239 //compute max triangle, it may be useful
240 double max_angle = 0;
241 for(int i=0;i<datri.size();i++)
243 double angle= MaxTriAngle(danode[datri[i].A].x,danode[datri[i].A].y,
244 danode[datri[i].B].x,danode[datri[i].B].y,
245 danode[datri[i].C].x,danode[datri[i].C].y);
246 if(max_angle<angle) max_angle=angle;
248 angle= MaxTriAngle(danode[datri[i].A].x,danode[datri[i].A].y,
249 danode[datri[i].C].x,danode[datri[i].C].y,
250 danode[datri[i].D].x,danode[datri[i].D].y);
251 if(max_angle<angle) max_angle=angle;
253 //alloc list. each voronoi cell will have it's own neighborlist.
254 //my god ,tens of thounds of lists i should alloc.
257 pneighborlist=new list<int>* [davcell.size()];
258 for(int i=0;i<davcell.size();i++) pneighborlist[i] = new list<int>;
259 //first for each cell, insert all neighbor nodes into the each node's neighborlist.
260 for(int i=0;i<datri.size();i++)
264 pneighborlist[datri[i].A]->push_front(datri[i].C);
265 pneighborlist[datri[i].A]->push_front(datri[i].B);
266 pneighborlist[datri[i].B]->push_front(datri[i].A);
267 pneighborlist[datri[i].B]->push_front(datri[i].C);
268 pneighborlist[datri[i].C]->push_front(datri[i].B);
269 pneighborlist[datri[i].C]->push_front(datri[i].A);
273 //then remove the overlap nodes in pneighborlist
274 for(int i=0;i<davcell.size();i++)
275 for(pt=pneighborlist[i]->begin();pt!=pneighborlist[i]->end();)
276 if(*pt==i||count(pneighborlist[i]->begin(),pneighborlist[i]->end(),*pt)>1 )
277 pt = pneighborlist[i]->erase(pt);
281 //alloc memory for each vcell, set pointers,cp bc_index form danode
282 VoronoiCell *pCell = davcell.GetPointer(0);
283 for(int i=0;i<davcell.size();i++,pCell++)
285 pCell->nb_num = pneighborlist[i]->size();
286 pCell->nb_array = new int[pneighborlist[i]->size()];
287 pCell->elen = new double[pneighborlist[i]->size()];
288 pCell->ilen = new double[pneighborlist[i]->size()];
289 pCell->angle = new double[pneighborlist[i]->size()];
290 pCell->celledge = new int[pneighborlist[i]->size()];
291 pCell->inb_array = new int[pneighborlist[i]->size()];
293 adjtabsize += pneighborlist[i]->size();
295 //adjtabsize equal to vedge*2
297 davedge.resize(adjtabsize/2);
299 // use angle to horizontal line to reorder the neighbour nodes as count clocked
300 double x1,y1,x2,y2,x3,y3,r,angle;
301 map<double,int> adjmap;
302 map<double,int> ::iterator padjmap;
304 list<int>::iterator pNODElist, pstart;
306 for(int i=0;i<davcell.size();i++)
307 { //compute each angle to horizontal line
308 //use container map to order them
309 for(pt=pneighborlist[i]->begin();pt!=pneighborlist[i]->end();pt++)
311 x2 = danode[i].x; y2 = danode[i].y;
312 x1 = danode[*pt].x; y1 = danode[*pt].y;
313 r = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
314 x3 = danode[i].x+r; y3 = danode[i].y;
315 angle = CompAngle(x1,y1,x2,y2,x3,y3);
316 adjmap.insert(map<double,int>::value_type(angle,*pt));
318 int *pnb_index = davcell.GetPointer(i)->nb_array;
319 double *pangle = davcell.GetPointer(i)->angle;
321 for(padjmap = adjmap.begin();padjmap!=adjmap.end();padjmap++)
323 *pnb_index++ = padjmap->second;
324 *pangle++ = padjmap->first;
328 //boundary cell may have problem. the nb_array may be dissevered by bd nodes
329 //i have to reorder it to make sure that bd nodes are located at first and last
330 //positions of nb_array array
332 if( davcell[i].bc_index != 0) //it is a bd cell
333 { for(int j=0;j<davcell[i].nb_num-1;j++)
334 if(fabs(davcell[i].angle[j]-davcell[i].angle[j+1])>max_angle)
335 {do_reorder=j+1;break;}
337 // the angle between line i,j and line i,j+1 are larger than max_angle
338 // denote that j and j+1 are bd nodes.
339 // j+1 will be set at the beginning of nb_array ,j set as last value
344 //push all the neighbors into a list
345 for(int j=0;j<davcell[i].nb_num;j++)
346 NODElist.push_back(davcell[i].nb_array[j]);
347 pNODElist=NODElist.begin();
348 while((*pNODElist)!=davcell[i].nb_array[do_reorder]) pNODElist++;
349 //find do_reorder point
351 pnb_index = davcell.GetPointer(i)->nb_array;
353 for(;pNODElist!=NODElist.end();pNODElist++)
354 *pnb_index++ = *pNODElist;
355 for(pNODElist=NODElist.begin();pNODElist!=pstart;pNODElist++)
356 *pnb_index++ = *pNODElist;
361 pangle = davcell.GetPointer(i)->angle;
362 for(int j=0;j<davcell[i].nb_num;j++)
364 x2 = danode[i].x; y2 = danode[i].y;
365 Node nb_node = danode[davcell[i].nb_array[j]];
368 r = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
371 *pangle++ = CompAngle(x1,y1,x2,y2,x3,y3);
377 //compute invert index of neighbour nodes
378 //davcell[i] == davcell[davcell[j].nb_array[davcell[i].inb_array[j]]]
379 for(int i=0;i<davcell.size();i++)
381 VoronoiCell *pCell = davcell.GetPointer(i);
382 for(int j=0;j<davcell[i].nb_num;j++)
383 for(int k=0;k<davcell[davcell[i].nb_array[j]].nb_num;k++)
385 if(i==davcell[davcell[i].nb_array[j]].nb_array[k])
386 pCell->inb_array[j]=k;
390 //not needed any more, free them.
391 for(int i=0;i<davcell.size();i++)
392 delete pneighborlist[i];
393 delete [] pneighborlist ;
400 /* ----------------------------------------------------------------------------
401 * ZONE::setup_voronoicell: the remain work is eary to do. ilen,elen and area
402 * will be setted here.
404 int ZONE::build_voronoicell_data()
406 //copy some data from danode
407 for(int i
=0;i
<davcell
.size();i
++)
409 VoronoiCell
*pCell
= davcell
.GetPointer(i
);
410 pCell
->x
= danode
[i
].x
;
411 pCell
->y
= danode
[i
].y
;
412 pCell
->bc_index
= danode
[i
].bc_index
;
415 //comput angle: the angle from horizontal line to it's neighbor node
416 double x1
,y1
,x2
,y2
,x3
,y3
,r
,angle
;
417 for(int i
=0;i
<davcell
.size();i
++)
419 double *pangle
= davcell
.GetPointer(i
)->angle
;
420 for(int j
=0;j
<davcell
[i
].nb_num
;j
++)
422 x2
= danode
[i
].x
; y2
= danode
[i
].y
;
423 Node nb_node
= danode
[davcell
[i
].nb_array
[j
]];
426 r
= sqrt((x1
-x2
)*(x1
-x2
)+(y1
-y2
)*(y1
-y2
));
429 *pangle
++ = CompAngle(x1
,y1
,x2
,y2
,x3
,y3
);
433 //comput ilen: length between node i and it's neighbor
434 for(int i
=0;i
<davcell
.size();i
++)
436 VoronoiCell
*pCell
= davcell
.GetPointer(i
);
437 for(int j
=0;j
<davcell
[i
].nb_num
;j
++)
439 Node n
= danode
[davcell
[i
].nb_array
[j
]];
440 pCell
->ilen
[j
]=Distance(danode
[i
].x
,danode
[i
].y
,n
.x
,n
.y
);
444 //next to comput elen , length of Voronoi Cell's Edge
445 //at the same time ,davedge will be set
446 list
<double> listxc
,listyc
; //two list to store location of CircleCenter
447 list
<double>::iterator pxc
,pyc
;
448 double xc
,yc
,xc_next
,yc_next
;
449 vector
<VEdge
>:: iterator pEdge
= davedge
.begin();
451 for(int i
=0;i
<davcell
.size();i
++)
453 //fill the list with CircleCenter
454 for(int j
=0;j
<davcell
[i
].nb_num
-1;j
++)
456 int error
=CircleCenter(danode
[i
].x
,danode
[i
].y
,
457 danode
[davcell
[i
].nb_array
[j
]].x
,
458 danode
[davcell
[i
].nb_array
[j
]].y
,
459 danode
[davcell
[i
].nb_array
[j
+1]].x
,
460 danode
[davcell
[i
].nb_array
[j
+1]].y
,
464 sprintf(log_buf
,"warning! CircleCenter: the three nodes of vcell %d of zone %d coplanar.\n",i
,zone_index
);
467 listxc
.push_back(xc
);
468 listyc
.push_back(yc
);
470 int nb_first
= davcell
[i
].nb_array
[0];
471 int nb_last
= davcell
[i
].nb_array
[davcell
[i
].nb_num
-1];
472 //if all the 3 points are bd ndoes
473 if (davcell
[i
].bc_index
&&davcell
[nb_first
].bc_index
&&
474 davcell
[nb_last
].bc_index
)
476 xc
= (danode
[i
].x
+danode
[nb_first
].x
)/2.0;
477 yc
= (danode
[i
].y
+danode
[nb_first
].y
)/2.0;
478 listxc
.push_front(xc
);
479 listyc
.push_front(yc
);
480 xc
= (danode
[i
].x
+danode
[nb_last
].x
)/2.0;
481 yc
= (danode
[i
].y
+danode
[nb_last
].y
)/2.0;
482 listxc
.push_back(xc
);
483 listyc
.push_back(yc
);
485 else //compute CircleCenter of the last triangle
487 int error
=CircleCenter(danode
[i
].x
,danode
[i
].y
,
495 sprintf(log_buf
,"warning! CircleCenter: the three nodes of vcell %d of zone %d coplanar.\n",i
,zone_index
);
498 listxc
.push_front(xc
);
499 listyc
.push_front(yc
);
500 listxc
.push_back(xc
);
501 listyc
.push_back(yc
);
506 VoronoiCell
*pCell
= davcell
.GetPointer(i
);
508 for(int j
=0;j
<davcell
[i
].nb_num
;j
++)
510 xc
= *pxc
++; yc
= *pyc
++;
511 xc_next
= *pxc
; yc_next
= *pyc
;
512 pCell
->elen
[j
] = Distance(xc
,yc
,xc_next
,yc_next
);
514 // each vedge belongs to 2 vcells
516 int i_index
= davcell
[i
].inb_array
[j
];
517 if(davcell
[i
].celledge
[j
]==-1 && davcell
[davcell
[i
].nb_array
[j
]].celledge
[i_index
]==-1)
518 { //this edge not registered. set data to it
520 pEdge
->cell2
= davcell
[i
].nb_array
[j
];
522 pEdge
->c2_nb
= davcell
[i
].inb_array
[j
];
524 pEdge
->length
= pCell
->elen
[j
];
525 pEdge
->x1
= xc
; pEdge
->y1
= yc
;
526 pEdge
->x2
= xc_next
; pEdge
->y2
= yc_next
;
527 davcell
.GetPointer(i
)->celledge
[j
] = nedge
;
528 davcell
.GetPointer(davcell
[i
].nb_array
[j
])->celledge
[i_index
] = nedge
;
537 // compute each cell's volume and zone area
538 field_area_vcell
= 0;
539 for(int i
=0;i
<davcell
.size();i
++)
541 VoronoiCell
*pCell
= davcell
.GetPointer(i
);
543 for(int j
=0;j
<davcell
[i
].nb_num
;j
++)
544 pCell
->area
+= davcell
[i
].elen
[j
]*davcell
[i
].ilen
[j
]/4.0;
545 field_area_vcell
+= pCell
->area
;