|
| |
Grids and Geometry
1. Grids
1.1 Material grid
1.2 Physical grid
1.3 Stefan's grid (Multiple grid points)
1.3.1 3D
1.3.2 2D
1.3.3 1D
2. Quantum regions
3. Structure functions (Grid mapping)
3.1 3D
3.2 2D
3.3 1D
4. Rotations
4.1 1D Simulation
4.2 2D Simulation
4.3 3D Simulation
Note: The way the grid is processed via the
input file was changed. In the original setup, the coordinates in the input file
determined the material grid points as described below and
resulting from this definition, the physical grid points were defined
accordingly. Now it is the opposite way. In the input file, the input file
determines the physical grid points and material grid points are defined with
respect to this new definiton. You can ask
Matthias Sabathil for more
details. The description and the pictures below are not applicable any more, in
principle, but still helpful.
New:
- Number of physical grid points as specified in input file: nx,
ny, nz
- Number of material grid points: nx-1, ny-1, nz-1
At the simulation boundaries, only physical grid points are defined.
The material grid points correspond to a volume grid.
The physical grid corresponds to the grid lines and nodes as specified in the
input file.
Old:
- Number of material grid points as specified in input file: N
- Number of physical grid points: N+1
At the simulation boundaries, both physical and material grid points are
defined.
1.1 Material grid (volume grid)
The
Input Parser creates a rectangular mesh with varying grid size. For each
mesh point information about material data
can be obtained. This grid supplied by the Input System will be called
material grid in the following.
|
 |
|
Fig. 1: Material grid: Rectangular
mesh with varying grid size. |
The main characteristics of the material grid can
be obtained via MODULE
define_geometry:
The mesh points are (irrespective of dimension
1D/2D/3D) numbered from 1 to n_material_points,
and each mesh point contains a material number in material_gridV which is the
number of the cluster (specified in the Input File) which this point belongs
to.
In order to transform the point number (1 to n_material_points)
to grid coordinates (i,j,k) in 3D for the x-, y- and z-axis [respectively (i,j)
in 2D for the x- and y-axis] one can use the functions subroutine i_j_k_to_ijk,
subroutine ijk_to_i_j_k
and subroutine
material_coordinates in
MODULE input_block_one.
--> x(1), x(2), x(3), x(4), ...
--> y(1), y(2), y(3), y(4), ...
--> z(1), z(2), z(3), z(4), ...
The subroutine
material_coordinates
provides the coordinates (x,y,z) of
the corresponding mesh point on the material grid.
material_coordinates(i) -> x(i), y(i), z(i)
For 2D and 1D the same applies.
Note that in 1D subroutine i_j_k_to_ijk
and subroutine ijk_to_i_j_k
do not make sense and so they do not exist at all.
1.2 Physical grid
The grid on which
physical calculations are done, is derived from the material grid by the following
convention:
All grid points are placed in
the middle (of the cell) between material grid points. This is called the
physical grid
in the following. Thus the number of x nodes of the
physical grid is equal to the number of x nodes of material grid plus 1. (Be
aware, that if a material grid point lies at the corner (or at the left or right
side in 1D), a physical grid point is placed there as well. For details, see
picture below.)
2D example (see picture further below):
Material grid points and corresponding
physical grid point:
y
^
|
|
o
o
|
(x1,y2)
(x2,y2)
|
|
o
|
( (x1+x2)/2 , (y1+y2)/2) )
|
|
o
o
|
(x1,y1)
(x2,y1)
|
----------------------------------------------------> x
For boundaries, the physical grid points are
lying directly between 2 of the material grid points.
o
o
o
(x1,y20)
( (x1+x2)/2 , y20 )
(x2,y20)
For material grid points lying at the vertexes
(~corners), the physical grid points are identical to material grid points.
o
/
o
(x1,y1)
/
(x1,y1)
So each mesh point on the physical
grid contains in each octant exactly one of material grid points (in
3D!). We
will call them octants also
for 2D and 1D in the following although there are only 4 and 2 neighboring
points, respectively.
Definition of interfaces:
The mesh points of the physical grid are placed exactly on interfaces
between different materials.
(In old versions it held: Actually, the interfaces are defined by this definition and not by the input
file.)
(In new versions it holds: Actually, the interfaces are defined by the input
file.)
The whole information about the
grid is stored in
MODULE
gitter:
For a mesh point (i,j,k)
on the physical grid it holds:
i=1,...,n_1
, j=1,...,n_2 ,
k=1,...,n_3
in 3D.
[ i=1,...,n_1 ,
j=1,...,n_2 in 2D and
i=1,...,n_1 in 1D].
The distance between the
points is stored in h_1V(1...n_1-1), h_2V(1...n_2-1)
and h_3D(1...n_3-1)
in meter [m].
(x_0,y_0,z_0)
is the absolute position of point (i=1,j=1,k=1) in [m].
As pointed out before, the whole
device is decomposed into material regions with different material numbers.
The variable num_materials
in MODULE
gitter contains the number of different kinds of
materials specified.
All these variables are allocated
and defined in subroutine
generate_mesh3D [generate_mesh2D, generate_mesh1D].
1.3 Stefan's grid (=physical grid plus multiple points)
In order to be able to handle
discontinuous quantities at interfaces (e.g. densities), one has to introduce
multiple
points at interfaces. These
multiple points have the same geometric coordinates and they describe the
physical quantity
in dependence of the direction from
which one approaches the interface.
Attention: Multiple points have different
letters in different dimensions!
1D: punktartCV =
! doesn't exist
2D: punktartCV = 'v' !
is called 'v' (German vier = 4 = four)
3D: punktartCV = 'a' ! is called 'a' (German
acht = 8 = eight)
1.3.1 In 3D this is done as follows:
The program loops through all
points of the physical grid and gets the eight adjoining points on the material grid as well as their
material number.
The eight adjoining points on
the material grid are stored in
adjoining_coord3DM(n_1,n_2,n_3,1:8)
= (i_j_k1,...,i_j_k8)
[numbering
(i-,j-,k-)
(i+,j-,k-)
(i-,j+,k-)
(i+,j+,k-)
(i-,j-,k+)
(i+,j-,k+)
(i-,j+,k+)
(i+,j+,k+)]
In case the material numbers are
not identical, a multiple point is defined. The multiple points are numbered
from 1 to
num_mult_points. It holds:
(i,j,k) a
single
point <==>
PointInfoM(i,j,k)
= 0
(i,j,k) a
multiple point <==>
PointInfoM(i,j,k)
contains the number of the multiple point
(1..num_mult_points).
The multiple points are
further characterized in punktartCV(1..num_mult_points):
- Interface perpendicular to
x-axis:
punktartCV = '|' ,
i.e. a double point is set [numbering (i-,j,k) ,
(i+,j,k) ]
- Interface perpendicular to
y-axis:
punktartCV = '-' ,
i.e. a double point is set [numbering (i,j-,k) ,
(i,j+,k) ]
- Interface perpendicular to
z-axis:
punktartCV = '/' ,
i.e. a double point is set [numbering (i,j,k-) ,
(i,j,k+) ]
- All other cases:
punktartCV = 'a' ,
i.e. an eightfold point is assumed ('a' comes from
the German word "acht"=eight).
[numbering (i-,j-,k-)
(i+,j-,k-)
(i-,j+,k-)
(i+,j+,k-)
(i-,j-,k+)
(i+,j-,k+)
(i-,j+,k+)
(i+,j+,k+)]
The grid which additionally
comprises multiple points is called Stefan's grid in the following.
All mesh points on Stefan's
grid are numbered from 1 to lengvecV.
The mapping from physical
grid to Stefan's grid and vice versa is done via
addressM and
phys_gridM:
-
addressM(i,j,k)
contains the position of the point (i,j,k) - or in case of a multiple point the
position of the first of them -
on Stefan's grid, so:
if (i,j,k) is an eightfold point,
the position for the eight octants are contained in
[addressM(i,j,k),...,addressM(i,j,k)+7]
-
phys_gridM(1..lengvecV,1..3)
is the inverse operation: it contains for
each point on Stefan's grid the position on the
physical grid, i.e.
phys_gridM(addressM(i,j,k),1) = i
phys_gridM(addressM(i,j,k),2) = j
phys_gridM(addressM(i,j,k),3) = k
In order to obtain the
coordinates of multiple points, one can use
coord_mult_points3DM(1:num_mult_points,3):
coord_mult_pointsM(n,1:3) = (i,j,k)
of nth multiple point on physical grid.
Because material numbers
are used very often they are also stored on Stefan's grid in mat_numberV.
All these variables are
allocated and defined in subroutine
generate_multiple_points3D.
1.3.2 In 2D the situation is analogous:
The program loops through all
points of the physical grid and gets the four adjoining points on material grid
as well as their material number.
The four adjoining points on
the material grid are stored in adjoining_coord2DM(n_1,n_2,1:4)
= (i_j_k1,...,i_j_k4)
[numbering
(i-,j-),(i+,j-),(i-,j+),(i+,j+)]
In case the material numbers are
not identical, a multiple point is defined. The multiple points are numbered
from 1 to num_mult_points. It holds:
(i,j) a
single point
<==>
PointInfoM(i,j,k=1)
=0
(i,j) a
multiple point
<==>
PointInfoM(i,j,k=1)
contains the number of the multiple point (1..num_mult_points).
The multiple points are
further characterized in punktartCV(1..num_mult_points):
-
Interface perpendicular to
x-axis:
punktartCV = '|' ,
i.e. a double point is set [numbering
(i-,j), (i+,j ]
-
Interface perpendicular to
y-axis:
punktartCV = '-' ,
i.e. a double point is set [numbering
(i,j-),
(i,j+)]
- All other cases:
punktartCV = 'v' ,
i.e. a fourfold point is assumed [numbering
(i-,j-),(i+,j-),(i-,j+),(i+,j+)]
('v' comes from the German word "vier"=four)
The grid which additionally
comprises multiple points is called Stefan's grid in the following.
All mesh points on Stefan's
grid are numbered from 1 to lengvecV.
The mapping from physical
grid to Stefan's grid and vice versa is done via addressM and phys_gridM:
-
addressM(i,j,k=1)
contains the
position of the point (i,j) - or in case of a multiple point the position of the
first of them - on Stefan's
grid, so:
if (i,j)
is an fourfold point, the position for the four "octants" are contained in
[addressM(i,j,k=1),...,addressM(i,j,k=1)+3]
-
phys_gridM(1..lengvecV,1..2)
is the inverse operation: it contains for each point on Stefan's grid the
position on the physical
grid, i.e.
phys_gridM(addressM(i,j,k=1),1) = i
phys_gridM(addressM(i,j,k=1),2) = j
In order to obtain the
coordinates of multiple points, one can use
coord_mult_points2DM(1:num_mult_points,2):
coord_mult_pointsM(n,1:2) = (i,j)
of nth multiple point on physical grid.
Because material numbers
are used very often they are also stored on Stefan's grid in mat_numberV.
All these variables are
allocated and defined in subroutine
generate_multiple_points2D.
1.3.3 In 1D the situation is analogous:
The program loops through all
points of the physical grid and gets the two adjoining points on material grid
as well as their material
number.
In case the material numbers are
not identical, a multiple point is defined. The multiple points are numbered
from 1 to num_mult_points. It holds:
(i) a single point
<==>
PointInfoM(i,j=1,k=1)
= 0
(i) a multiple point
<==>
PointInfoM(i,j=1,k=1)
contains the number of the double point (1..num_mult_points).
The grid which additionally
comprises multiple points is called Stefan's grid in the following.
All mesh points on Stefan's
grid are numbered from 1 to lengvecV.
The mapping from physical
grid to Stefan's grid and vice versa is done via
addressM and phys_gridM:
-
addressM(i,j=1,k=1)
contains the
position of the point (i) - or in case of a multiple point the position of the
first of them - on Stefan's grid, so:
if (i) is a double point, the
position for the two "octants" are contained in
[addressM(i,j=1,k=1),...,addressM(i,j=1,k=1)+1]
-
phys_gridM(1..lengvecV,1)
is
the inverse operation: it contains for each point on Stefan's grid the position
on the physical grid, i.e.
phys_gridM(addressM(i,j=1,k=1),1) = i
In order to obtain the
coordinates of multiple points, one can use
coord_mult_points1DV(1:num_mult_points,1):
coord_mult_points1DV(n,1) = (i) of
nth multiple point on physical grid.
Because material numbers
are used very often they are also stored on Stefan's grid in mat_numberV.
All these variables are
allocated and defined in subroutine
generate_multiple_points1D.
Quantum regions are specified
independently from material regions. Therefore they must be separately
stored in an additional vector.
The input system provides
information about quantumregions in
MODULE
define_geometry:
iquantumregions
... number of quantum regions
quantum_guentherV
(1..n_material_points) ... contains for each point on material grid which quantum region it belongs
to,
= 0 , if it does
not belong to any
In subroutine
setup_quantumregion these quantum regions are projected
on the physical grid by the following convention:
For each point on the physical
grid the adjoining point on the material grid with the highest quantum region
number defines which quantum
region this point belongs to.
In each quantum region n, the
points are numbered from 1 to dim_qrV(n),
so dim_qrV(1..num_qr_regions) contains
for each quantum region the
dimension (num_qr_regions
is the number of quantum regions).
The point number within a
quantum region can be obtained via quantumreg_numM:
quantum_gridM(i,j,k) contains the quantum region number for point (i,j,k) on
physical grid
quantumreg_numM(i,j,k) contains the point number (1..dim_qrV(n)) of the point (i,j,k) within the
corresponding
quantum region.
- The inverse of this
mapping is stored in
inv_quantumreg_numM(1:num_qr_regions,1:max(dim_qrV),1:3):
inv_quantumreg_numM(n,iqr,1:3) contains for quantum region n and point number iqr within quantum region n the coordinates (i,j,k) of the
corresponding point on the physical grid.
- One can also do this mapping
between quantum region points and Stefan's grid (i.e. including multiple
points):
dim_qr_dbleV
contains for each quantum region the number of points including multiple
points (Note:
For
any point (i,j,k) on the physical grid all multiple points which are on the
position of (i,j,k) are included.
This also applies to boundary
points.)
quantumreg_num_dbleV(adr) provides for point number adr
on Stefan's grid (adr=1..lengvecV) the point
number within the corresponding quantum region.
map_qr_guentherV(1:num_qr_regions)
[MODULE gitter] contains for each quantum region the grid points,
which are contained in that
quantum region on material grid (i.e. the point numbers on material grid):
-
map_qr_guentherV(num_qr)%number_of_points
--> number of points
-
map_qr_guentherV(num_qr)%guenther_grid_points(1..number of points) -->
position of
the point on material grid
Often one wants to know the
inverse mapping: Given a point on material grid, the position of that point in
the set
defined by
map_qr_guentherV(num_qr)%guenther_grid_points(1..number of points)
is obtained via:
number_guent_whole_to_qr(i_guent)
[ is zero for i_guent not in a quantum region ].
Thus, it is:
number_guent_whole_to_qr(map_qr_guentherV(num_qr)%guenther_grid_points(k)) =
k
MODULE gitter also contains
the normalization vectors for the wavefunctions in each quantum cluster:
norm_sgV(1..num_qc,1..dim_qrV) :
The norm is defined as:
< Psi | Psi > =
sum( PsiV*PsiV*norm_sgV(num_qc,:) )
Note: norm_sgV is used to
normalize wavefunctions for k.p and single-band Schrödinger equation.
In 1D, however, norm_sgV does not
exist (Comment: Is this true? It exists for single-band! And it seems that it is
necessary in order to normalize the wavefunction to '1'.) and the normalization vector for k.p is norm_kpV in
MODULE
normalization_factors_sg.
For treating Schrödinger
equation it is necessary to know which band number is valid
since in a quantum region different
material numbers may be present and the band numbering and order is just
proposed to be consistent within one material, we have to distinguish between
different material kinds in
a quantum region:
This is done by
map_qr_to_materialV(1..num_materials,1..num_qr_regions)
1 2 ...
num_materials
--------------------------------------
1 | 0 1 ...
2
|
2 | 1 2 ...
0
|
. |
. |
. |
|
num_qr_regions | 0 0 ...
0
---------------------------------------
means that in quantum regions
number 1
- Index 1 refers to material 2.
- Index
2 refers to material 'num_materials'.
- Material number 1 is not
contained in quantum regions number 1.
in quantum regions number 2
- Index 1 refers to material 1.
- Index 2 refers to material 2.
- Material number 'num_materials'
is not contained in quantum region number 2.
The following picture
illustrates and summarizes the grid conventions:

There are several subroutines in MODULE
structure_functions
which help to handle grid mappings:
3.1 3D
MODULE structure_functions contains
1. subroutine get_octants_3D
2. subroutine get_octants_qr3D
3. subroutine convert_guenther_to_phys3D
4. subroutine get_addresses_from_phys3D
5. function get_address3D
!-----------------------------------------------------------------------------
subroutine get_octants_3D(i,j,k,materialV)
!-----------------------------------------------------------------------------
!
! input: i,j,k
! output: materialV(1:8)
!
! provides for point (i,j,k) on physical grid the material numbers of each
! oktand (i=1..n_1,j=1..n_2,k=1,n_3)
! see in 2D for an example
!-----------------------------------------------------------------------------
!-----------------------------------------------------------------------------
subroutine get_octants_qr3D(i,j,k,qu_regV)
!-----------------------------------------------------------------------------
!
! input: i,j,k
! output: qu_regV
!
! provides for point (i,j,k) on physical grid the quantum region of each
! oktand
! see in 2D for an example
!-----------------------------------------------------------------------------
!----------------------------------------------------------------------------
subroutine convert_guenther_to_phys3D(i_j_k,coordM)
!----------------------------------------------------------------------------
!
! input: i_j_k
! output: coordM(1:8,1:4)
!
! i_j_k number in guenthers whole vector
! coordM(i,1:3) coordinates on physical grid of adjoining grid points in octant
number i
! coordM(i,4) address of point in that octant from that point of view
! at boundaries the adjoining octant is valid
!
! see in 2D for an example
!----------------------------------------------------------------------------
!---------------------------------------------------------------------------
subroutine get_addresses_from_phys3D(i,j,k,octV)
!---------------------------------------------------------------------------
!
! input: i,j,k
! output: octV(1:8)
!
! provides for point (i,j,k) on physical grid in
! octV(1..8) the address in the whole vector of the eight octants
!
! see in 2D for an example
!------------------------------------------------------------------------
!----------------------------------------------------------------------------
function get_address3D(i,j,k,ch) result(adr)
!----------------------------------------------------------------------------
! returns for a point (i,j,k) on stefan's grid and
! ch='n' for a single point
! (ch = '1',...'8' being the number of the octant otherwise)
! the address in the whole one-dim. vectors
!
! see in 2D for an example
!----------------------------------------------------------------------------
3.2 2D
MODULE structure_functions contains
1. subroutine get_octants_2D
2. subroutine get_octants_qr2D
3. subroutine convert_guenther_to_phys2D
4. subroutine get_addresses_from_phys2D
5. function get_address2D
!-----------------------------------------------------------------------------
subroutine get_octants_2D(i,j,materialV)
!-----------------------------------------------------------------------------
!
! input: i,j
! output: materialV(1:4)
!
! provides for point (i,j) on physical grid the material numbers of each
! oktand (i=1..n_1,j=1..n_2)
!
! example:
!
! Imagine following situation: mat_i denotes the material number (mat2=material
number 2,
!
mat3=material number 3)
! These material numbers are given on Guenther's grid. We consider now the
situation (on the material grid):
!
. .
!
. .
!
. .
!
... mat7 mat2 ...
!
... mat3 mat4 ...
!
. .
!
. .
!
. .
!
! on the physical Grid we have following situation:
!
!
(i,j+1)
!
|
!
mat7 |
mat2
!
|
!
(i-1,j)------------(i,j)--------------(i+1,j)
!
|
!
mat3 |
mat4
!
|
!
(i,j-1)
!
! --> OUTPUT:
! materialV(1)=mat3
! materialV(2)=mat4
! materialV(3)=mat7
! materialV(4)=mat2
!-----------------------------------------------------------------------------
!-----------------------------------------------------------------------------
subroutine get_octants_qr2D(i,j,qu_regV)
!-----------------------------------------------------------------------------
!
! input: i,j
! output: qu_regV(1:4)
!
! provides for point (i,j) on physical grid the quantum region of each
! oktand
!
! example:
!
! Imagine following situation: qr_i denotes the quantum region number (=0, if
not contained in any quantum region).
! These quantum region numbers are originally given on Guenther's grid. We
consider now the situation (on the
! material grid):
!
. .
!
. .
!
. .
!
... qr1 0 ...
!
... 0 0
...
!
. .
!
. .
!
. .
!
! on the physical Grid we have following situation:
!
!
(i,j+1)
!
|
!
mat7 |
mat2
!
|
!
(i-1,j)------------(i,j)--------------(i+1,j)
!
|
!
mat3 |
mat4
!
|
!
(i,j-1)
!
! --> OUTPUT:
! materialV(1)=0
! materialV(2)=0
! materialV(3)=qr1
! materialV(4)=0
!
! NOTE:
!------------
!
! This subroutine is only used to construct the array quantum_gridM(i,j,1) out
of the information
! of the input parser. Later on in the program, for each point on the physical
Grid (i,j) the array
! quantum_gridM(i,j,1) says if this point is contained in a quantum
reagion.
!-----------------------------------------------------------------------------
!----------------------------------------------------------------------------
subroutine convert_guenther_to_phys2D(i_j_k,coordM)
!----------------------------------------------------------------------------
!
!
! input: i_j_k
! output: coordM(1:4,1:3)
!
! i_j_k number in guenthers whole vector
! coordM(i,1:2) coordinates on physical grid of adjoining grid points
! coordM(i,3) address of point in that octant from that point of view
! at boundaries the adjoining octant is valid
!
! example:
!
! material grid (2x2 grid -> points numbered from 1...4):
!
! g3 g4
! g1 g2
!
! --> physical Grid:
!
! (1,3) (2,3)
(3,3)
! g3
g4
! (1,2) (2,2)
(3,2)
! g1
g2
! (1,1) (2,1)
(3,1)
!
! Suppose that g1 and g3 have the same material A, g2 and g4 the same material B
(A different from B)
! Then the points (2,1),(2,2),(2,3) on the physical grid are double points.
! So the numbering in the whole vector (1..lengvecV) is as follows:
!
! 9 10|11 12
! g3 g4
! 5 6|7
8
! g1 g2
! 1 2|3
4
!
! so for example:
!
! input: i_j_k=g3
!
! output: coordM(1,1:2) = (1,2)
!
coordM(2,1:2) = (2,2)
!
coordM(3,1:2) = (1,3)
!
coordM(4,1:2) = (2,3)
!
! coordM(1,3)
= 5
! coordM(2,3)
= 6
! coordM(3,3)
= 9
! coordM(4,3)
= 10
!----------------------------------------------------------------------------
!---------------------------------------------------------------------------
subroutine get_addresses_from_phys2D(i,j,octV)
!---------------------------------------------------------------------------
! input: i,j
! output: octV(1:4)
!
! provides for point (i,j) on physical grid in
! octV(1..4) the address in the whole vector of the four octants
!
! take the example above:
!
! material grid (2x2 grid -> points numbered from 1...4):
!
! g3 g4
! g1 g2
!
! --> physical Grid:
!
! (1,3) (2,3)
(3,3)
! g3
g4
! (1,2) (2,2)
(3,2)
! g1
g2
! (1,1) (2,1)
(3,1)
!
! Suppose that g1 and g3 have the same material A, g2 and g4 the same
material B (A different from B)
! Then the points (2,1),(2,2),(2,3) on the physical Grid are double points.
! So the numbering in the whole vector (1..lengvecV) is as follows:
!
! 9 10|11 12
! g3 g4
! 5 6|7
8
! g1 g2
! 1 2|3
4
!
! input: i=2, j=2
!
! --> the four octants have the addresses: 6
| 7
!
----------
!
6 | 7
!
! so: octV(1)= 6
! octV(2)= 7
! octV(3)= 6
! octV(4)= 7
!
!------------------------------------------------------------------------
!----------------------------------------------------------------------------
function get_address2D(i,j,ch) result(adr)
!----------------------------------------------------------------------------
! returns for a point (i,j) on stefan's grid and
! ch='n' for a single point
! (ch = '1',...'4' being the number of the octant otherwise)
! the address in the whole one-dim. vectors
!
! in the above example:
!
! input : i=2, j=2 , ch='1' --> adr = octV(1) = 6
! i=2, j=2 , ch='2'
--> adr = octV(2) = 7
! i=2, j=2 , ch='3'
--> adr = octV(3) = 6
! i=2, j=2 , ch='4'
--> adr = octV(4) = 7
!----------------------------------------------------------------------------
3.3 1D
MODULE structure_functions contains
1. subroutine get_octants_1D
2. subroutine get_octants_qr1D
3. subroutine extract_octants1D
subroutine get_octants_1D(i,materialV)
Provides for point (i) on Stefan's grid the material numbers of each oktant
(i=1..n_1)
(left and right octant).
subroutine get_octants_qr1D(i,qu_regV)
Provides for point (i) on Stefan's grid the quantum region numbers of each
oktant.
subroutine extract_octants1D(octV,i)
Extracts from vector vecV(1:lengvecV) the two relevant octants for point with coord (i) on
Stefan's grid: octV(1..2)
There are principally two coordinate systems as
described:
-
Crystal system
-
a) Simulation system
b)
Calculation system)
For a fixed vector k_vec the
relation holds:
k_vec{simulation-system} = RM . k_vec{crystal-system}
ksi = R.kcr
This rotation matrix RM is provided by the
function rotate_crystal_to_sim in
MODULE rotations.
Transformation: Crystal fixed cartesian coordinate system ->
Simulation coordinate system
There are two coordinate systems:
- Crystal system
describes a vector in terms of the basis vectors in the crystal system.
In wurtzite these basis vectors are by default:
miller-direction-of-cx
x = 1 0 -1 0
miller-direction-of-cy
y = -1 2 -1 0
miller-direction-of-cz
z = 0 0 0 1
where the directions are defined as [h k i
l] with i=-(h+k). In wurtzite the
four-digit indices are called Miller-Bravais indices.
In zincblende they are defined by:
miller-direction-of-cx
x = 1 0 0
miller-direction-of-cy
y = 0 1 0
miller-direction-of-cz
z = 0 0 1
Note that the crystal is a cartesian system.
- Simulation system
The simulation system is a cartesian system (x, y, z) in which the simulation
variables are defined.
The relative position of the simulation system to the crystal
system is unambigously determined. Thus the rotation matrix R
can be defined as follows:
ksimulation=R.kcrystal
for a fixed vector k.
Note that in the rotation of the k.p Hamiltonian the
rotation matrix was defined the same way as the rotation matrix above.
The crystal is oriented with respect to the simulation coordinate system by
specifying two simulation coordinate axes in terms of Miller directions in the
crystal. In this way, the orientation of the crystal is uniquely defined with
respect to the simulation coordinate system. However, orientation dependent
material parameters have to be defined in the database also with respect to a
crystal fixed coordinate system. These axes of crystal fixed cartesian
coordinate systems are defined in the database by their Miller directions in the
crystal. In wurtzite the four-digit
indices are called Miller-Bravais indices.
Note, that the choice is in such a way, that the
orientation of the crystal fixed cartesian coordinate
system is independent of the lattice constants.
For wurtzite materials, this crystal fixed
cartesian coordinate system is
chosen as
miller-direction-of-cx
= 1 0 -1 0 !
miller-direction-of-cy
= -1 2 -1 0 !
miller-direction-of-cz
= 0 0 0 1 !
and for zincblende materials as
miller-direction-of-cx
= 1 0 0
!
miller-direction-of-cy
= 0 1 0
!
miller-direction-of-cz
= 0 0 1
!
The transformation matrix B which transforms vectors,
given in components of the crystal fixed cartesian
coordinate system, to the simulation cartesian coordinate
system is constructed in such a way, that
kxyz-simulation= MATMUL(B,kxyz-crystal)
Up to the mass tensor of the band minima, all quantities in the database and
the input must be given in the xyz-crystal system. The mass tensor is specified
in its principal axes system.
The principal axes of the corresponding minima are specified in the xyz-crystal
system for each material by its eigenvalues. To obtain the mass tensor in the
simulation coordinate system, a transformation from the principal axis
system to the xyz-crystal system is required. The corresponding
transformation matrix can be accessed by
A=cb_trans_matrix_mass(mat_num,band_num,min,alloyc)
MCxyz =ATMp-axis A
A ... transformation
matrix
MCxyz ... mass tensor in
cartesian crystal coordinate system
Mp-axis ... mass
tensor in principal axis system
From the cartesian crystal coordinate system, the mass
tensor transforms to the simulation cartesian coordinate
system as
MSxyz = BMCxyzBT
4.1 1D simulation
In 1D, the simulation direction [=growth
direction] can be the x-, y- or z-axis. In the program, however, one only has
one direction (which is the z-direction) and parallel directions (x and y).
Consequently, one has to carry out an additional rotation, which rotates
the simulation direction to the z-direction (the
ordering of x- and y-direction is unique in case one
assumes an even permutation of the axes).
This additional rotation:
k_vec{calculation-system} = RM
k_vec{simulation-system}
kca = R.ksi
is provided by the function
rotate_sim_to_calculation in MODULE rotations.
(Note: In case the simulation direction is
the z-axis in the simulation system, this rotation is the identity.)
function
inv_rotate_sim_to_calculation in MODULE rotations calculates the inverse (=transpose) of this
matrix.
Total rotation from crystal system to
calculation system:
k_vec{calculation-system} = R_gesM
k_vec{crystal-system}
kca = Rges.kcr
R_gesM =
RM_{simulation_to_calculation} . RM_{crystal_to_simulation}
Rges = Rsi-ca.Rcr-si
This matrix is provided by the function
rotate_crystal_to_calc in MODULE rotations.
NOTE: This is the matrix which is used
for rotation of k.p-Hamiltonian because
discretization is always carried out along z-direction in calculation system.
Transformation of matrices:
k_sim_1_T E_sim k_sim_2 = (RM k_cryst_1)T E RM k_cryst_2 =
= k_cryst_1_T RM_T E_sim RM k_cryst_2 = k_cryst_1_T E_cryst
k_cryst_2
---> E_cryst = RM_T
E_sim RM and E_sim = RM
E_cryst RM_T
ksi1T.Esi.ksi2 = (R.kcr1)T.Esi.R.kcr2 =
= kcr1T.RT.Esi.R.kcr2 =
kcr1T.Ecr.kcr2
---> Ecr =
RT.Esi.R and
Esi = R.Ecr.RT
4.2 2D simulation
In 2D, the simulation plane is determined by
two of the x-, y- or z-axes. In the program (= calculation system), however, one has two
fixed directions (which form the (x,y) plane) and one perpendicular direction (z-axis).
Consequently, one has to carry out an additional rotation, which rotates
the simulation plane to the (x,y) plane (the
ordering of x- and y-direction is unique in case one
assumes an even permutation of the axes).
This additional rotation:
k_vec{calculation-system} = RM
k_vec{simulation-system}
kca = R.ksi
is provided by the FUNCTION
rotate_sim_to_calculation
in MODULE rotations.
(Note: In case the simulation directions are
the (x,y)-plane in the simulation system, this rotation is the identity.)
FUNCTION
inv_rotate_sim_to_calculation in MODULE rotations calculates the inverse (=transposed) of this
matrix.
Total rotation from crystal system to
calculation system:
k_vec{calculation-system} = R_gesM
k_vec{crystal-system}
kca = Rges.kc
R_gesM =
RM_{simulation_to_calculation} * RM_{crystal_to_simulation}
Rges = Rsi-ca.Rcr-si
This matrix is provided by the FUNCTION
rotate_crystal_to_calc in MODULE rotations.
NOTE: This is the matrix which is used
for rotation of k.p-Hamiltonian because
discretization is always carried out in (x,y)-plane in calculation
system.
Question: When we have 2D simulation we can specify as simulation
domain [1 0 1] or [1 1 0 ] or [0 1 1].
What is x and what is y in the simulation domain?
Answer:
|
[x y z] |
simulation
system |
calculation
sytem = x,y system |
|
[1 0 1] |
(x,z)-plane |
x=x, y=z |
|
[1 1 0] |
(x,y)-plane |
x=x, y=y |
|
[0 1 1]
|
(y,z)-plane |
x=y, y=z |
4.3 3D simulation
In 3D, analogous functions are defined in
MODULE rotations.
Note that the calculation and simulation system are identical.
|