-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathmosfet2D.cpp
140 lines (118 loc) · 5.25 KB
/
mosfet2D.cpp
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
#include <algorithm>
#include <chrono>
#include <iostream>
#include <memory>
#include <ParticleHandler/emcBasicParticleHandler.hpp>
#include <PoissonSolver/emcSORSolver.hpp>
#include <SurfaceScatterMechanisms/emcConstantSurfaceScatterMechanism.hpp>
#include <emcDevice.hpp>
#include <emcSimulation.hpp>
#include "../SiliconFunctions.hpp"
#include "NECSchemeVWD.hpp"
#include "electronVWD.hpp"
const SizeType Dim = 2;
const std::string fileNamePrefix = "mosfet";
using namespace std::chrono;
using NumType = double;
using MaterialType = emcMaterial<NumType>;
using DeviceType = emcDevice<NumType, Dim>;
using PMScheme = emcNECSchemeVWD<NumType, DeviceType>;
using ParticleHandler = emcBasicParticleHandler<NumType, DeviceType, PMScheme>;
using PoissonSolver = emcSORSolver<NumType, DeviceType, ParticleHandler>;
using SimulationType = emcSimulation<NumType, DeviceType, PoissonSolver,
ParticleHandler, PMScheme>;
using ValueVec = DeviceType::ValueVec;
/// adapts potential to the ViennaWD-Output
NumType adaptPotential(const NumType &pot, const DeviceType &device) {
return device.getMaterial().getBandGap() / 2 -
pot * device.getThermalVoltage();
}
const std::vector<NumType> Vds = {1.};
const std::vector<NumType> Vgs = {1.};
bool includeParameterInFileName = true;
/// parameters to include surface roughness at the Si-SiO2 interface
bool addRoughnessToOxideInterface = false;
/// probability of a specular scattering (in the other times diffusive
/// scattering is performed)
NumType probSpecularScattering = 0.5;
//! number of used threads (in parallel region)
const SizeType nrThreads = 4;
/// creates an nChannel-MOSFET using the same parameter as ViennaWD Example 1
int main() {
#ifdef _OPENMP
omp_set_num_threads(nrThreads);
std::cout << ">> Parallel version, using " << nrThreads << " threads.\n\n";
#else
std::cout << "\n>> Sequential version.\n\n";
#endif
for (auto &Vg : Vgs) {
for (auto &Vd : Vds) {
// create Device (n-channel MOSFET)
const ValueVec deviceMaxPos = {125e-9, 100e-9}; // m
const ValueVec spacing = {1e-9, 1e-9}; // m
DeviceType device{Silicon::getSiliconMaterial<NumType>(), deviceMaxPos,
spacing};
device.setDeviceWidth(1e-6);
// add doping regions
device.addConstantDopingRegion({0, 30e-9}, {125e-9, 100e-9},
-5e23); // bulk
device.addConstantDopingRegion({0, 0}, {51e-9, 30e-9}, 5e25); // source
device.addConstantDopingRegion({51e-9, 0}, {75e-9, 30e-9}, -5e24); // gate
device.addConstantDopingRegion({75e-9, 0}, {125e-9, 30e-9},
5e25); // drain
// add Contacts
device.addOhmicContact(emcBoundaryPos::YMAX, 0, {0},
{125e-9}); // substrate
device.addOhmicContact(emcBoundaryPos::YMIN, 0, {0}, {51e-9}); // source
device.addGateContact(emcBoundaryPos::YMIN, Vg, {51e-9}, {75e-9}, 3.9,
1.2e-9,
device.getMaterial().getBandGap() / 2.); // gate
device.addOhmicContact(emcBoundaryPos::YMIN, Vd, {75e-9},
{125e-9}); // drain
std::cout << "Applied Voltages:\n";
std::cout << "\tVd = " << Vd << " V\n";
std::cout << "\tVg = " << Vg << " V\n";
// create Poisson Solver + PMScheme
PoissonSolver solver(device, 1e-4, 1.8);
PMScheme pmScheme;
// set simulation parameter + create simulation
emcSimulationParameter<NumType, DeviceType> param;
param.setTimes(10e-12, 1.5e-16, 5e-12);
param.setAdaptPotentialForWriteFunction(adaptPotential);
std::string parameter = "";
if (includeParameterInFileName) {
parameter += "Vd" + std::to_string((int)(Vd * 1e3));
parameter += "Vg" + std::to_string((int)(Vg * 1e3));
}
param.setNamePrefix(fileNamePrefix + parameter);
param.setNrStepsBetweenShowProgress(1000);
param.setNrStepsForFinalAvg(6667);
// add particle types that should be simulated
auto electron = std::make_unique<electronVWD<NumType, DeviceType>>();
Silicon::addXValley(electron);
std::vector<int> idxRegions(
device.getDopingProfile().getNrDopingRegions());
std::iota(idxRegions.begin(), idxRegions.end(), 0);
Silicon::addAcousticScattering(0, electron, device, idxRegions);
Silicon::addCoulombScattering(0, electron, device, idxRegions);
Silicon::addZeroOrderInterValleyScattering(0, electron, device,
idxRegions);
if (addRoughnessToOxideInterface) {
electron->setSurfaceScatterMechanism(
emcBoundaryPos::YMIN,
std::make_unique<
emcConstantSurfaceScatterMechanism<NumType, DeviceType>>(
probSpecularScattering, device.getMaxPos()));
}
param.addParticleType(std::move(electron));
SimulationType simulation(param, device, solver, pmScheme);
// execute + time simulation
auto start = high_resolution_clock::now();
simulation.execute();
auto end = high_resolution_clock::now();
std::cout << "CPU time: " << duration_cast<seconds>(end - start).count()
<< " s\n";
}
}
return 0;
}