-
Notifications
You must be signed in to change notification settings - Fork 79
Expand file tree
/
Copy pathmos_physics.py
More file actions
170 lines (147 loc) · 6.54 KB
/
mos_physics.py
File metadata and controls
170 lines (147 loc) · 6.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# Copyright 2013 DEVSIM LLC
#
# SPDX-License-Identifier: Apache-2.0
from devsim import contact_equation, element_from_edge_model, equation, get_dimension
from devsim.python_packages.model_create import (
CreateElementModel2d,
CreateElementModelDerivative2d,
)
def CreateElementElectronContinuityEquation(device, region, current_model):
"""
Uses element current model for equation
"""
equation(
device=device,
region=region,
name="ElectronContinuityEquation",
variable_name="Electrons",
time_node_model="NCharge",
node_model="ElectronGeneration",
element_model=current_model,
variable_update="positive",
)
# TODO: expand for circuit
def CreateElementContactElectronContinuityEquation(device, contact, current_model):
"""
Uses element current model for equation
"""
contact_electrons_name = "{0}nodeelectrons".format(contact)
contact_equation(
device=device,
contact=contact,
name="ElectronContinuityEquation",
node_model=contact_electrons_name,
element_current_model=current_model,
)
#### this version is from the direction of current flow
#### TODO: version from interface normal distance
def CreateNormalElectricFieldFromInterfaceNormal(device, region, interface):
### assume the interface normal already exists
#### Get the electric field on the element
element_from_edge_model(edge_model="ElectricField", device=device, region=region)
element_from_edge_model(
edge_model="ElectricField", device=device, region=region, derivative="Potential"
)
#### Get the normal e field to current flow /// need to figure out sign importance for electron/hole
Enormal = "{0}_normal_x * ElectricField_x + {0}_normal_y * ElectricField_y".format(
interface
)
CreateElementModel2d(device, region, "Enormal", Enormal)
CreateElementModelDerivative2d(device, region, "Enormal", Enormal, "Potential")
###### make this on a per carrier basis function
###### assume that low field model already exists, but not projected
def CreateNormalElectricFieldFromCurrentFlow(device, region, low_curr):
dimension = get_dimension(device=device)
if dimension != 2:
raise ValueError("Supported in 2d only")
element_from_edge_model(edge_model=low_curr, device=device, region=region)
element_from_edge_model(
edge_model=low_curr, device=device, region=region, derivative="Potential"
)
element_from_edge_model(
edge_model=low_curr, device=device, region=region, derivative="Electrons"
)
element_from_edge_model(
edge_model=low_curr, device=device, region=region, derivative="Holes"
)
#### Get the current magnitude on the element
#### do we need the derivative, since this is only scaling the direction?
#### Worry about small denominator 1e-300 is about the limit
J_lf_mag = "pow({0}_x^2 + {0}_y^2 + 1e-300, 0.5)".format(low_curr)
CreateElementModel2d(
device, region, "{0}_mag".format(low_curr), "{0}".format(J_lf_mag)
)
for j in ("Electrons", "Holes", "Potential"):
for i in ("@en0", "@en1", "@en2"):
ex = "({0}_x * {0}_x:{1}{2} + {0}_y * {0}_y:{1}{2})/{0}_mag".format(
low_curr, j, i
)
CreateElementModel2d(
device, region, "{0}_mag:{1}{2}".format(low_curr, j, i), ex
)
### This calculates the normalized current in each direction
for i in ("x", "y"):
J_norm = "{0}_{1} / {0}_mag".format(low_curr, i)
CreateElementModel2d(device, region, "{0}_norm_{1}".format(low_curr, i), J_norm)
CreateElementModelDerivative2d(
device,
region,
"{0}_norm_{1}".format(low_curr, i),
J_norm,
"Electrons",
"Holes",
"Potential",
)
#### Get the electric field on the element
element_from_edge_model(edge_model="ElectricField", device=device, region=region)
element_from_edge_model(
edge_model="ElectricField", device=device, region=region, derivative="Potential"
)
#### Get the parallel e field to current flow
Eparallel_J = "{0}_norm_x * ElectricField_x + {0}_norm_y * ElectricField_y".format(
low_curr
)
CreateElementModel2d(device, region, "Eparallel_{0}".format(low_curr), Eparallel_J)
CreateElementModelDerivative2d(
device, region, "Eparallel_{0}".format(low_curr), Eparallel_J, "Potential"
)
# magnitude e field
ElectricField_mag = "pow(ElectricField_x^2 + ElectricField_y^2 + 1e-300, 0.5)"
CreateElementModel2d(device, region, "ElectricField_mag", ElectricField_mag)
# the , turns this into an actual tuple
for j in ("Potential",):
for i in ("@en0", "@en1", "@en2"):
ex = "(ElectricField_x * ElectricField_x:{0}{1} + ElectricField_y * ElectricField_y:{0}{1})/ElectricField_mag".format(
j, i
)
CreateElementModel2d(
device, region, "ElectricField_mag:{0}{1}".format(j, i), ex
)
#### Get the normal e field to current flow
Enormal_J = "pow(max(ElectricField_mag^2 - Eparallel_{0}^2,1e-300), 0.5)".format(
low_curr
)
CreateElementModel2d(device, region, "Enormal_{0}".format(low_curr), Enormal_J)
# CreateElementModelDerivative2d $device $region Enormal_{low_curr} {Enormal_J} Electrons Holes Potential
for j in ("Electrons", "Holes", "Potential"):
for i in ("@en0", "@en1", "@en2"):
ex = "(ElectricField_mag * ElectricField_mag:{0}{1} - Eparallel_{2} * Eparallel_{2}:{0}{1})/Enormal_{2}".format(
j, i, low_curr
)
CreateElementModel2d(
device, region, "Enormal_{0}:{1}{2}".format(low_curr, j, i), ex
)
def CreateElementElectronCurrent2d(device, region, name, mobility_model):
Jn = "ElectronCharge*{0}*EdgeInverseLength*V_t*kahan3(Electrons@en1*Bern01, Electrons@en1*vdiff, -Electrons@en0*Bern01)".format(
mobility_model
)
CreateElementModel2d(device, region, name, Jn)
for i in ("Electrons", "Holes", "Potential"):
CreateElementModelDerivative2d(device, region, name, Jn, i)
def CreateElementHoleCurrent2d(device, region, name, mobility_model):
Jp = "-ElectronCharge*{0}*EdgeInverseLength*V_t*kahan3(Holes@en1*Bern01, -Holes@en0*Bern01, -Holes@en0*vdiff)".format(
mobility_model
)
CreateElementModel2d(device, region, name, Jp)
for i in ("Electrons", "Holes", "Potential"):
CreateElementModelDerivative2d(device, region, name, Jp, i)