1 /*****************************************************************************/
2 /* 8888888 88888888 88888888 */
5 /* 8 88888888 88888888 */
8 /* 888888 888888888 888888888 */
10 /* A Two-Dimensional General Purpose Semiconductor Simulator. */
13 /* Last update: March 13, 2006 */
17 /* NINT, No.69 P.O.Box, Xi'an City, China */
19 /*****************************************************************************/
25 unsigned int adtl::AutoDScalar::numdir
= 9;
27 int BSolver::build_zonedata()
29 zonedata
.resize(zone_num
);
30 // determine zone material by zone label. the label is compatible with medici
31 for(int i
=0; i
<zone_num
; i
++)
32 { //it is an Insulator zone
33 if(IsInsulator(zone
[i
].zonelabel
))
35 zonedata
[i
] = new ISZone
;
36 ISZone
*pzonedata
= dynamic_cast< ISZone
* >(zonedata
[i
]);
37 pzonedata
->pzone
= &zone
[i
];
38 pzonedata
->zone_index
= zone
[i
].zone_index
;
39 pzonedata
->pzone
= &zone
[i
];
40 pzonedata
->node_num
= zone
[i
].davcell
.size();
41 pzonedata
->tri_num
= zone
[i
].datri
.size();
42 pzonedata
->material_type
= Insulator
;
43 pzonedata
->material
= IsInsulator(zone
[i
].zonelabel
);
44 try {pzonedata
->mt
= new MatInsulator(zone
[i
].zonename
,
45 FormatInsulatorString(zone
[i
].zonelabel
),&scale_unit
);}
47 pzonedata
->fs
= new ISData
[pzonedata
->node_num
];
48 pzonedata
->aux
= new ISAuxData
[pzonedata
->node_num
];
49 pzonedata
->electrode
.clear();
50 for(int j
=0;j
<pzonedata
->pzone
->dasegment
.size();j
++)
52 int bc_index
= pzonedata
->pzone
->dasegment
[j
].bc_index
-1;
53 if(bc
[bc_index
].BCType
==GateContact
||
54 bc
[bc_index
].BCType
==ChargedContact
)
55 pzonedata
->electrode
.push_back(bc_index
);
57 //pzonedata->report();
59 //if this is a semiconductor zone
60 else if(IsSemiconductor(zone
[i
].zonelabel
))
62 zonedata
[i
] = new SMCZone
;
63 SMCZone
*pzonedata
= dynamic_cast< SMCZone
* >(zonedata
[i
]);
64 pzonedata
->pzone
= &zone
[i
];
65 pzonedata
->zone_index
= zone
[i
].zone_index
;
66 pzonedata
->material
= IsSemiconductor(zone
[i
].zonelabel
);
67 pzonedata
->material_type
= Semiconductor
;
68 try{pzonedata
->mt
= new MatSemiconductor(zone
[i
].zonename
,
69 FormatSemiconductorString(zone
[i
].zonelabel
),PMIS_define
,&scale_unit
);}
71 pzonedata
->node_num
= zone
[i
].davcell
.size();
72 pzonedata
->tri_num
= zone
[i
].datri
.size();
73 pzonedata
->fs
= new SemiData
[pzonedata
->node_num
];
74 pzonedata
->aux
= new SemiAuxData
[pzonedata
->node_num
];
75 pzonedata
->electrode
.clear();
76 for(int j
=0;j
<pzonedata
->pzone
->dasegment
.size();j
++)
78 int bc_index
= pzonedata
->pzone
->dasegment
[j
].bc_index
-1;
79 if(bc
[bc_index
].BCType
==OhmicContact
||
80 bc
[bc_index
].BCType
==SchottkyContact
||
81 bc
[bc_index
].BCType
==InsulatorContact
)
82 pzonedata
->electrode
.push_back(bc_index
);
84 //pzonedata->report();
86 //oh it is an electrode,medici can generate this useless region
87 else if(IsElectrode(zone
[i
].zonelabel
))
89 zonedata
[i
] = new ElZone
;
90 ElZone
*pzonedata
= dynamic_cast< ElZone
* >(zonedata
[i
]);
91 pzonedata
->pzone
= &zone
[i
];
92 pzonedata
->zone_index
= zone
[i
].zone_index
;
93 pzonedata
->node_num
= zone
[i
].davcell
.size();
94 pzonedata
->tri_num
= zone
[i
].datri
.size();
95 pzonedata
->material_type
= Conductor
;
96 pzonedata
->material
= Conductor
;
97 try {pzonedata
->mt
= new MatConductor(zone
[i
].zonename
,
98 FormatElectrodeString(zone
[i
].zonelabel
),&scale_unit
);}
100 pzonedata
->fs
= new ELData
[pzonedata
->node_num
];
101 pzonedata
->aux
= new ELAuxData
[pzonedata
->node_num
];
102 pzonedata
->electrode
.clear();
103 for(int j
=0;j
<pzonedata
->pzone
->dasegment
.size();j
++)
105 int bc_index
= pzonedata
->pzone
->dasegment
[j
].bc_index
-1;
106 if(bc
[bc_index
].BCType
==OhmicContact
||
107 bc
[bc_index
].BCType
==SchottkyContact
||
108 bc
[bc_index
].BCType
==GateContact
)
109 pzonedata
->electrode
.push_back(bc_index
);
111 if(pzonedata
->electrode
.size()>1)
113 gss_log
.string_buf()<<"Electrode region "<<zone
[i
].zonename
<<" has more than one Contact, not supported yet.\n";
117 //pzonedata->report();
119 //Data for Vacuum zone
120 else if(IsVacuum(zone
[i
].zonelabel
))
122 zonedata
[i
] = new VacuumZone
;
123 VacuumZone
*pzonedata
= dynamic_cast< VacuumZone
* >(zonedata
[i
]);
124 pzonedata
->pzone
= &zone
[i
];
125 pzonedata
->zone_index
= zone
[i
].zone_index
;
126 pzonedata
->node_num
= zone
[i
].davcell
.size();
127 pzonedata
->tri_num
= zone
[i
].datri
.size();
128 pzonedata
->material_type
= Vacuum
;
129 pzonedata
->material
= Vacuum
;
130 try {pzonedata
->mt
= new MatVacuum(zone
[i
].zonename
,
131 FormatVacuumString(zone
[i
].zonelabel
),&scale_unit
);}
132 catch(int){return 1;}
133 pzonedata
->fs
= new VacuumData
[pzonedata
->node_num
];
134 pzonedata
->aux
= new VacuumAuxData
[pzonedata
->node_num
];
137 else if(IsPML(zone
[i
].zonelabel
))
139 zonedata
[i
] = new PMLZone
;
140 PMLZone
*pzonedata
= dynamic_cast< PMLZone
* >(zonedata
[i
]);
141 pzonedata
->pzone
= &zone
[i
];
142 pzonedata
->zone_index
= zone
[i
].zone_index
;
143 pzonedata
->node_num
= zone
[i
].davcell
.size();
144 pzonedata
->tri_num
= zone
[i
].datri
.size();
145 pzonedata
->material_type
= PML
;
146 pzonedata
->material
= PML
;
147 try {pzonedata
->mt
= new MatPML(zone
[i
].zonename
,
148 FormatPMLString(zone
[i
].zonelabel
),&scale_unit
);}
149 catch(int){return 1;}
150 pzonedata
->fs
= new PMLData
[pzonedata
->node_num
];
151 pzonedata
->aux
= new PMLAuxData
[pzonedata
->node_num
];
155 gss_log
.string_buf()<<"error, no such region type "<<zone
[i
].zonelabel
<<" specified!\n";
161 // process inter_connect here
162 for(int i
=0; i
<bc
.size(); i
++)
164 if(bc
.Get_pointer(i
)->BCType
==OhmicContact
)
166 OhmicBC
*pbc
= dynamic_cast <OhmicBC
* > (bc
.Get_pointer(i
));
167 if(pbc
->connect_elec
!="")
170 for(int j
=0;j
<bc
.size();j
++)
172 if(pbc
->connect_elec
==bc
.Get_pointer(j
)->psegment
->label
&&
173 IsSemiconductor(zone
[bc
.Get_pointer(j
)->psegment
->zone_index
].zonelabel
))
176 pbc
->inner_connect
=j
;
177 pbc
->connect_zone
= bc
.Get_pointer(j
)->psegment
->zone_index
;
178 if(bc
.Get_pointer(pbc
->inner_connect
)->BCType
==OhmicContact
)
180 OhmicBC
*om_bc
= dynamic_cast <OhmicBC
* >(bc
.Get_pointer(pbc
->inner_connect
));
181 om_bc
->inner_connect
=i
;
182 om_bc
->connect_zone
=pbc
->psegment
->zone_index
;
183 om_bc
->connect_elec
=pbc
->psegment
->label
;
184 om_bc
->pzonedata
=zonedata
[pbc
->psegment
->zone_index
];
188 sprintf(log_buf
,"\nCheck Inner Connect failed, BC %s should connect to an Ohmic/Schottky Electrode!\n",
189 bc
.Get_pointer(pbc
->inner_connect
)->psegment
->label
);
197 sprintf(log_buf
,"\nSorry, I can't find a suitable inner conect for %s!\n",pbc
->connect_elec
.c_str());
208 int BSolver::setup_init_data()
210 for(int i
=0; i
<zone_num
; i
++)
211 if(zonedata
[i
]->Init(&zone
[i
],LatticeTemp
,&scale_unit
)) return 1;
216 int BSolver::setup_doping()
218 for(int z
=0; z
<zone_num
; z
++)
219 if(zonedata
[z
]->material_type
== Semiconductor
)
221 SMCZone
*pzonedata
= dynamic_cast<SMCZone
*> (zonedata
[z
]);
222 for(int i
=0;i
<pzonedata
->node_num
;i
++)
224 double x
= pzonedata
->pzone
->danode
[i
].x
;
225 double y
= pzonedata
->pzone
->danode
[i
].y
;
226 for(int j
=0;j
<doping_func
.size();j
++)
228 double doping
= doping_func
[j
]->profile(x
,y
);
230 pzonedata
->aux
[i
].Nd
+= doping
;
232 pzonedata
->aux
[i
].Na
+= fabs(doping
);
240 int BSolver::import_doping_from_cgns(char* cgnsfile
)
242 for(int z
=0; z
<zone_num
; z
++)
244 if(zonedata
[z
]->material_type
== Semiconductor
)
246 SMCZone
*pzonedata
= dynamic_cast<SMCZone
*> (zonedata
[z
]);
247 if(pzonedata
->import_doping(cgnsfile
,&scale_unit
)) return 1;
254 int BSolver::import_mole_from_cgns(char* cgnsfile
)
256 for(int z
=0; z
<zone_num
; z
++)
258 if(IsSingleCompSemiconductor(zone
[z
].zonelabel
))
260 SMCZone
*pzonedata
= dynamic_cast<SMCZone
*> (zonedata
[z
]);
261 if(pzonedata
->import_mole(cgnsfile
,1)) return 1;
267 int BSolver::setup_bc()
270 Segment
**segment
= new Segment
*[bc_num
];
271 for(int i
=1; i
<=bc_num
;i
++)
272 segment
[i
-1] = Get_segment(i
);
273 if(bc
.InitBC(bc_num
,segment
,zone_num
,zone
,zinterface
,pcmdbuf
,LatticeTemp
,&scale_unit
)) return 1;
276 //for bc marks are assigned to edge, some nodes may have two bc marks
277 //assign this type of nodes to correct bc type
278 for(int i
=0;i
<bc
.size();i
++)
280 if(bc
[i
].psegment
->interface
==-1)
282 int zone_index
= bc
[i
].psegment
->zone_index
;
283 for(int j
=0;j
<bc
[i
].psegment
->node_array
.size();j
++)
285 int node_index
= bc
[i
].psegment
->node_array
[j
];
286 int bc_index
=zone
[zone_index
].danode
[node_index
].bc_index
;
287 if(bc
[bc_index
-1].BCType
< bc
[i
].BCType
)
289 zone
[zone_index
].danode
[node_index
].bc_index
= i
+1;
290 zone
[zone_index
].davcell
.GetPointer(node_index
)->bc_index
= i
+1;
296 int inf
= bc
[i
].psegment
->interface
;
297 int z1
= zinterface
[inf
].zone1
;
298 int z2
= zinterface
[inf
].zone2
;
299 if(z1
==bc
[i
].psegment
->zone_index
)
300 for(int j
=0;j
<zinterface
[inf
].index_array1
.size();j
++)
302 int node_index
= zinterface
[inf
].index_array1
[j
];
303 int bc_index
=zone
[z1
].danode
[node_index
].bc_index
;
304 if(bc
[bc_index
-1].BCType
< bc
[i
].BCType
)
306 zone
[z1
].danode
[node_index
].bc_index
= i
+1;
307 zone
[z1
].davcell
.GetPointer(node_index
)->bc_index
= i
+1;
310 if(z2
==bc
[i
].psegment
->zone_index
)
311 for(int j
=0;j
<zinterface
[inf
].index_array2
.size();j
++)
313 int node_index
= zinterface
[inf
].index_array2
[j
];
314 int bc_index
=zone
[z2
].danode
[node_index
].bc_index
;
315 if(bc
[bc_index
-1].BCType
< bc
[i
].BCType
)
317 zone
[z2
].danode
[node_index
].bc_index
= i
+1;
318 zone
[z2
].davcell
.GetPointer(node_index
)->bc_index
= i
+1;
328 void BSolver::reorder()
331 for(int z
=0; z
<zone_num
; z
++)
333 int * old_to_new
= reorder_zone(z
);
334 if(zonedata
[z
]->material_type
== Semiconductor
)
336 SMCZone
*pzonedata
= dynamic_cast<SMCZone
*> (zonedata
[z
]);
337 SemiData
* fs_new
= new SemiData
[pzonedata
->node_num
];
338 SemiAuxData
* aux_new
= new SemiAuxData
[pzonedata
->node_num
];
339 for(int i
=0;i
<pzonedata
->node_num
;i
++)
341 fs_new
[old_to_new
[i
]] = pzonedata
->fs
[i
];
342 aux_new
[old_to_new
[i
]] = pzonedata
->aux
[i
];
344 delete [] pzonedata
->fs
;
345 delete [] pzonedata
->aux
;
346 pzonedata
->fs
= fs_new
;
347 pzonedata
->aux
= aux_new
;
349 if(zonedata
[z
]->material_type
== Insulator
)
351 ISZone
*pzonedata
= dynamic_cast<ISZone
*> (zonedata
[z
]);
352 ISData
* fs_new
= new ISData
[zonedata
[z
]->node_num
];
353 ISAuxData
* aux_new
= new ISAuxData
[pzonedata
->node_num
];
354 for(int i
=0;i
<pzonedata
->node_num
;i
++)
356 fs_new
[old_to_new
[i
]] = pzonedata
->fs
[i
];
357 aux_new
[old_to_new
[i
]] = pzonedata
->aux
[i
];
359 delete [] pzonedata
->fs
;
360 delete [] pzonedata
->aux
;
361 pzonedata
->fs
= fs_new
;
362 pzonedata
->aux
= aux_new
;
364 if(zonedata
[z
]->material_type
== Conductor
)
366 ElZone
*pzonedata
= dynamic_cast<ElZone
*> (zonedata
[z
]);
367 ELData
* fs_new
= new ELData
[zonedata
[z
]->node_num
];
368 ELAuxData
* aux_new
= new ELAuxData
[pzonedata
->node_num
];
369 for(int i
=0;i
<pzonedata
->node_num
;i
++)
371 fs_new
[old_to_new
[i
]] = pzonedata
->fs
[i
];
372 aux_new
[old_to_new
[i
]] = pzonedata
->aux
[i
];
374 delete [] pzonedata
->fs
;
375 delete [] pzonedata
->aux
;
376 pzonedata
->fs
= fs_new
;
377 pzonedata
->aux
= aux_new
;
379 if(zonedata
[z
]->material_type
== Vacuum
)
381 VacuumZone
*pzonedata
= dynamic_cast<VacuumZone
*> (zonedata
[z
]);
382 VacuumData
* fs_new
= new VacuumData
[zonedata
[z
]->node_num
];
383 VacuumAuxData
* aux_new
= new VacuumAuxData
[pzonedata
->node_num
];
384 for(int i
=0;i
<pzonedata
->node_num
;i
++)
386 fs_new
[old_to_new
[i
]] = pzonedata
->fs
[i
];
387 aux_new
[old_to_new
[i
]] = pzonedata
->aux
[i
];
389 delete [] pzonedata
->fs
;
390 delete [] pzonedata
->aux
;
391 pzonedata
->fs
= fs_new
;
392 pzonedata
->aux
= aux_new
;
394 if(zonedata
[z
]->material_type
== PML
)
396 PMLZone
*pzonedata
= dynamic_cast<PMLZone
*> (zonedata
[z
]);
397 PMLData
* fs_new
= new PMLData
[zonedata
[z
]->node_num
];
398 PMLAuxData
* aux_new
= new PMLAuxData
[pzonedata
->node_num
];
399 for(int i
=0;i
<pzonedata
->node_num
;i
++)
401 fs_new
[old_to_new
[i
]] = pzonedata
->fs
[i
];
402 aux_new
[old_to_new
[i
]] = pzonedata
->aux
[i
];
404 delete [] pzonedata
->fs
;
405 delete [] pzonedata
->aux
;
406 pzonedata
->fs
= fs_new
;
407 pzonedata
->aux
= aux_new
;
409 delete [] old_to_new
;
415 int BSolver::build_least_squares()
417 double a
=0,b
=0,c
=0,w
=0;
418 for(int z
=0; z
<zone_num
; z
++)
419 if(zonedata
[z
]->material_type
== Semiconductor
)
421 SMCZone
*pzonedata
= dynamic_cast< SMCZone
* >(zonedata
[z
]);
422 for(int i
=0; i
<zone
[z
].davcell
.size(); i
++)
425 VoronoiCell
*pcell
= zone
[z
].davcell
.GetPointer(i
);
426 for(int k
=0;k
<pcell
->nb_num
;k
++)
428 const VoronoiCell
*ncell
= zone
[z
].davcell
.GetPointer(pcell
->nb_array
[k
]);
429 double dx
= ncell
->x
- pcell
->x
;
430 double dy
= ncell
->y
- pcell
->y
;
431 w
=1.0/sqrt(dx
*dx
+dy
*dy
);
436 if(pcell
->bc_index
&&bc
[pcell
->bc_index
-1].BCType
==InsulatorInterface
)
438 InsulatorInterfaceBC
*pbc
;
439 pbc
= dynamic_cast<InsulatorInterfaceBC
*>(bc
.Get_pointer(pcell
->bc_index
-1));
440 int n_zone
= pbc
->pinterface
->Find_neighbor_zone_index(z
);
441 int n_node
= pbc
->pinterface
->Find_neighbor_node_index(z
,i
);
442 ISZone
* pz
= dynamic_cast<ISZone
*>(zonedata
[n_zone
]);
443 const VoronoiCell
* dcell
= pz
->pzone
->davcell
.GetPointer(n_node
);
444 for(int k
=1;k
<dcell
->nb_num
-1;k
++)
446 const VoronoiCell
*ncell
= pz
->pzone
->davcell
.GetPointer(dcell
->nb_array
[k
]);
447 double dx
= ncell
->x
- dcell
->x
;
448 double dy
= ncell
->y
- dcell
->y
;
449 w
=1.0/sqrt(dx
*dx
+dy
*dy
);
455 pcell
->sa
= a
/(a
*c
-b
*b
);
456 pcell
->sb
= b
/(a
*c
-b
*b
);
457 pcell
->sc
= c
/(a
*c
-b
*b
);
463 int VacuumZone::Init(ZONE
* zone
, double Tl
,PhysicalUnitScale
*scale
)
465 for(int i
=0;i
<node_num
; i
++)
467 aux
[i
].eps
= mt
->eps0
;
473 int PMLZone::Init(ZONE
* zone
, double Tl
,PhysicalUnitScale
*scale
)
475 for(int i
=0;i
<node_num
; i
++)
477 aux
[i
].eps
= mt
->eps0
;
483 int ISZone::Init(ZONE
* zone
, double Tl
,PhysicalUnitScale
*scale
)
485 for(int i
=0;i
<node_num
; i
++)
487 mt
->mapping(&pzone
->danode
[i
],&aux
[i
],0);
488 aux
[i
].Ex
= aux
[i
].Ey
= 0;
489 aux
[i
].affinity
= mt
->basic
->Affinity(Tl
);
490 aux
[i
].density
= mt
->basic
->Density(Tl
);
491 aux
[i
].eps
= mt
->eps0
*mt
->basic
->Permittivity();
492 aux
[i
].mu
= mt
->mu0
*mt
->basic
->Permeability();
494 fs
[i
].P
= -aux
[i
].affinity
;
499 int ElZone::Init(ZONE
* zone
, double Tl
,PhysicalUnitScale
*scale
)
501 for(int i
=0;i
<node_num
; i
++)
503 aux
[i
].affinity
= mt
->basic
->Affinity(Tl
);
504 aux
[i
].density
= mt
->basic
->Density(Tl
);
505 aux
[i
].eps
= mt
->eps0
*mt
->basic
->Permittivity();
506 aux
[i
].mu
= mt
->mu0
*mt
->basic
->Permeability();
508 fs
[i
].P
= -aux
[i
].affinity
;
514 int SMCZone::Init(ZONE
* zone
, double Tl
,PhysicalUnitScale
*scale
)
516 PetscScalar e
= mt
->e
;
517 PetscScalar kb
= mt
->kb
;
518 for(int i
=0;i
<node_num
; i
++)
521 fs
[i
].Tn
=fs
[i
].Tp
=fs
[i
].T
;
522 mt
->mapping(&pzone
->danode
[i
],&aux
[i
],0);
523 double nie
= mt
->band
->nie(fs
[i
].T
);
524 double Nc
= mt
->band
->Nc(fs
[i
].T
);
525 if((aux
[i
].Nd
-aux
[i
].Na
)>0) //n-type
527 fs
[i
].n
=((aux
[i
].Nd
-aux
[i
].Na
)+sqrt(pow(aux
[i
].Nd
-aux
[i
].Na
,2)+4*nie
*nie
))/2;
528 fs
[i
].p
=nie
*nie
/fs
[i
].n
;
532 fs
[i
].p
=((aux
[i
].Na
-aux
[i
].Nd
)+sqrt(pow(aux
[i
].Na
-aux
[i
].Nd
,2)+4*nie
*nie
))/2;
533 fs
[i
].n
=nie
*nie
/fs
[i
].p
;
535 aux
[i
].affinity
= mt
->basic
->Affinity(fs
[i
].T
);
536 aux
[i
].density
= mt
->basic
->Density(fs
[i
].T
);
537 aux
[i
].eps
= mt
->eps0
*mt
->basic
->Permittivity();
538 aux
[i
].mu
= mt
->mu0
*mt
->basic
->Permeability();
539 aux
[i
].Eg
= mt
->band
->Eg(fs
[i
].T
)-mt
->band
->EgNarrow(fs
[i
].T
);
540 aux
[i
].Nc
= mt
->band
->Nc(fs
[i
].T
);
541 aux
[i
].Nv
= mt
->band
->Nv(fs
[i
].T
);
542 fs
[i
].P
= kb
*fs
[i
].T
/e
*asinh((aux
[i
].Nd
-aux
[i
].Na
)/(2*nie
)) - kb
*fs
[i
].T
/e
*log(Nc
/nie
)
543 - aux
[i
].affinity
- mt
->band
->EgNarrowToEc(fs
[i
].T
);
544 fs
[i
].Eqc
= -(e
*fs
[i
].P
+ aux
[i
].affinity
+ mt
->band
->EgNarrowToEc(fs
[i
].T
) + kb
*fs
[i
].T
*log(aux
[i
].Nc
));
545 fs
[i
].Eqv
= -(e
*fs
[i
].P
+ aux
[i
].affinity
- mt
->band
->EgNarrowToEv(fs
[i
].T
) - kb
*fs
[i
].T
*log(aux
[i
].Nv
)+ aux
[i
].Eg
);
546 aux
[i
].mun
= aux
[i
].mup
= 0;
551 void SMCZone::report()
553 gss_log
.string_buf()<<"\nThis is a semiconductor Zone.\n";
557 void ISZone::report()
559 gss_log
.string_buf()<<"\nThis is a insulator Zone.\n";
563 void ElZone::report()
565 gss_log
.string_buf()<<"\nThis is a electrode.\n";
569 void VacuumZone::report()
571 gss_log
.string_buf()<<"\nThis is vacuum area.\n";
575 void PMLZone::report()
577 gss_log
.string_buf()<<"\nThis is PML.\n";