Ejemplo n.º 1
0
        public DoubleVector Get_EnergyLevels(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot)
        {
            // interpolate the input charge density and chemical potential onto a reduced domain to simplify DFT solve
            SpinResolved_Data dft_dens = new SpinResolved_Data(new Band_Data(new DoubleVector(nz)), new Band_Data(new DoubleVector(nz)));
            Band_Data         dft_pot  = new Band_Data(new DoubleVector(nz));

            Interpolate_DFT_Grid(ref dft_dens, ref dft_pot, charge_density, chem_pot);
            Get_Potential(ref dft_pot, layers);

            DoubleHermitianMatrix    hamiltonian = Create_Hamiltonian(layers, dft_pot);
            DoubleHermitianEigDecomp eig_decomp  = new DoubleHermitianEigDecomp(hamiltonian);

            System.IO.StreamWriter sw_pot  = new System.IO.StreamWriter("tmp_pot.dat");
            System.IO.StreamWriter sw_dens = new System.IO.StreamWriter("tmp_dens.dat");

            Band_Data dft_dens_spin_summed = dft_dens.Spin_Summed_Data;

            for (int i = 0; i < dft_pot.Length; i++)
            {
                sw_dens.WriteLine(dft_dens_spin_summed[i].ToString());
                sw_pot.WriteLine(dft_pot[i].ToString());
            }

            sw_dens.Close();
            sw_pot.Close();

            return(eig_decomp.EigenValues);
        }
Ejemplo n.º 2
0
        DoubleHermitianMatrix Create_H_Using_SOIP(Band_Data dft_pot, double k)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(2 * nx * ny);

            // create the SOIP parts of the matrix
            result  = Create_SOIP_Matrix(Direction.x, Direction.y, Direction.z, k, nx, ny);
            result += Create_SOIP_Matrix(Direction.y, Direction.x, Direction.z, k, nx, ny);

            // and add the scalar terms from the k-direction
            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    // add momentum and potential terms
                    result[i * ny + j, i *ny + j] += Physics_Base.hbar * Physics_Base.hbar * k * k / (2.0 * mass) + dft_pot.mat[i, j];
                    result[i * ny + j + nx * ny, i *ny + j + nx * ny] += Physics_Base.hbar * Physics_Base.hbar * k * k / (2.0 * mass) + dft_pot.mat[i, j];

                    // add spin-orbit terms
                    result[i * ny + j, i *ny + j + nx * ny] += (-1.0 * I * alpha * dV_x.mat[i, j] - alpha * dV_y.mat[i, j]) * k;
                    result[i * ny + j + nx * ny, i *ny + j] += (I * alpha * dV_x.mat[i, j] - alpha * dV_y.mat[i, j]) * k;
                }
            }

            return(result);
        }
Ejemplo n.º 3
0
        DoubleHermitianMatrix Create_Hamiltonian(Band_Data dft_pot, double k)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(2 * nx * ny);
            DoubleHermitianMatrix h_upup, h_updn, h_dnup, h_dndn;

            // create sub-matrices with no spin orbit
            h_upup = Create_NoSOI_Hamiltonian(dft_pot, k, nx, ny);      // takes up to up (ie. H_11)
            h_dndn = Create_NoSOI_Hamiltonian(dft_pot, k, nx, ny);      // takes dn to dn (ie. H_22)
            h_updn = new DoubleHermitianMatrix(nx * ny);                // takes up to dn (ie. H_21)
            h_dnup = new DoubleHermitianMatrix(nx * ny);                // takes dn to up (ie. H_12)

            // add spin-orbit
            h_upup -= alpha * Create_SOI_Hamiltonian(Direction.y, Direction.x, k, nx, ny);
            h_dndn -= -1.0 * alpha * Create_SOI_Hamiltonian(Direction.y, Direction.x, k, nx, ny);
            h_updn -= alpha * (Create_SOI_Hamiltonian(Direction.z, Direction.y, nx, ny) - Create_SOI_Hamiltonian(Direction.y, Direction.z, nx, ny)
                               + I * Create_SOI_Hamiltonian(Direction.z, Direction.x, k, nx, ny));
            h_dnup -= alpha * (Create_SOI_Hamiltonian(Direction.z, Direction.y, nx, ny) - Create_SOI_Hamiltonian(Direction.y, Direction.z, nx, ny)
                               - I * Create_SOI_Hamiltonian(Direction.z, Direction.x, k, nx, ny));

            // recombine matrices and output result
            for (int i = 0; i < nx * ny; i++)
            {
                for (int j = 0; j < nx * ny; j++)
                {
                    result[i, j]                     = h_upup[i, j];
                    result[i, j + nx * ny]           = h_dnup[i, j];
                    result[i + nx * ny, j]           = h_updn[i, j];
                    result[i + nx * ny, j + nx * ny] = h_dndn[i, j];
                }
            }

            return(result);
        }
Ejemplo n.º 4
0
        DoubleHermitianMatrix Create_Hamiltonian(double[] V, double t, int N)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(N);

            // set off diagonal elements
            for (int i = 0; i < N; i++)
            {
                // coupling sites in the growth direction
                if (i != 0)
                {
                    result[i - 1, i] = t;
                }
                if (i != N - 1)
                {
                    result[i + 1, i] = t;
                }
            }

            // set diagonal elements
            for (int i = 0; i < N; i++)
            {
                result[i, i] = -2.0 * t + V[i];
            }

            return(result);
        }
Ejemplo n.º 5
0
        DoubleHermitianMatrix Create_2DEG_Hamiltonian(double[,] V, double tx, double ty, int nx, int ny, bool periodic_in_x, bool periodic_in_y)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(nx * ny);

            // set off diagonal elements
            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    // coupling sites in the transport direction
                    if (i != 0)
                    {
                        result[i * ny + j, i *ny + j - ny] = tx;
                    }
                    if (i != nx - 1)
                    {
                        result[i * ny + j, i *ny + j + ny] = tx;
                    }
                    // coupling sites in the transverse direction
                    if (j != 0)
                    {
                        result[i * ny + j, i *ny + j - 1] = ty;
                    }
                    if (j != ny - 1)
                    {
                        result[i * ny + j, i *ny + j + 1] = ty;
                    }
                }
            }

            // set diagonal elements
            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    result[i * ny + j, i *ny + j] = -2.0 * tx + -2.0 * ty + V[i, j];
                }
            }

            // and finally, add periodic boundary conditions where appropriate
            if (periodic_in_x)
            {
                for (int j = 0; j < ny; j++)
                {
                    result[j, j + (nx - 1) * ny] = tx;
                    result[j + (nx - 1) * ny, j] = tx;
                }
            }
            if (periodic_in_y)
            {
                for (int i = 0; i < nx; i++)
                {
                    result[i * ny + 1, i *ny] = ty;
                    result[i * ny, i *ny + 1] = ty;
                }
            }

            return(result);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Calculates and prints the band structure
        /// </summary>
        void Print_Band_Structure(Band_Data dft_pot, ILayer[] layers, int Nk, double dk, string outfile, int max_eigval)
        {
            // set temperature high so that all wave functions will be calculated
            double old_temperature = temperature;

            temperature = 1000.0;

            if (dV_x == null)
            {
                throw new Exception("Error - Band structure derivatives are null!  Have you initiated this type properly by calling Get_SOI_parameters(Band_Data chem_pot)?");
            }

            // calculate the energies up to a given maximum energy of the lowest state
            double k = 0;

            double[][] energies = new double[Nk][];
            for (int i = 0; i < Nk; i++)
            {
                k = i * dk;
                Console.WriteLine(i.ToString() + ": Calculating for k = " + k.ToString());
                // generate the Hamiltonian for this k value
                DoubleHermitianMatrix hamiltonian = Create_H_Using_SOIP(dft_pot, k);
                // and diagonalise it
                int max_wavefunction;
                DoubleHermitianEigDecomp eig_decomp = Diagonalise_Hamiltonian(hamiltonian, out max_wavefunction);

                // add the calculated energies up to either the maximum required eigenvalue or
                // to the maximum calculated wave function (which is 50*kb*T above the chemical potential)
                double[] tmp_energies = new double[max_eigval];
                for (int j = 0; j < max_eigval; j++)
                {
                    if (j < max_wavefunction)
                    {
                        tmp_energies[j] = eig_decomp.EigenValues[j];// - 0.5 * Physics_Base.hbar * Physics_Base.hbar * k * k / Physics_Base.mass;
                    }
                    else
                    {
                        tmp_energies[j] = eig_decomp.EigenValues[max_wavefunction - 1];// -0.5 * Physics_Base.hbar * Physics_Base.hbar * k * k / Physics_Base.mass;
                    }
                }
                energies[i] = tmp_energies;
            }

            // output the data to file
            StreamWriter sw = new StreamWriter(outfile);
            for (int i = 0; i < Nk; i++)
            {
                for (int j = 0; j < max_eigval; j++)
                {
                    sw.Write(energies[i][j].ToString() + "\t");
                }

                sw.WriteLine();
            }
            sw.Close();

            // reset temperature
            temperature = old_temperature;
        }
Ejemplo n.º 7
0
        /// <summary>
        /// returns an eigenvector decomposition for the x-direction after having calculated the density in the
        /// y-direction and storing it in "charge_density"
        /// </summary>
        /// <param name="dft_pot"></param>
        /// <param name="charge_density"></param>
        /// <returns></returns>
        private DoubleHermitianEigDecomp Solve_Eigenvector_Problem(Band_Data dft_pot, ref SpinResolved_Data charge_density)
        {
            DoubleHermitianEigDecomp eig_decomp;

            double[]     x_energy  = new double[nx];
            DoubleMatrix dens_up   = new DoubleMatrix(nx, ny, 0.0);
            DoubleMatrix dens_down = new DoubleMatrix(nx, ny, 0.0);

            // cycle over x-direction calculating the ground state energy and eigenstate in the y-direction
            for (int i = 0; i < nx; i++)
            {
                // pull out the chemical potential for this slice
                double[] y_dft_pot = new double[ny];
                for (int j = 0; j < ny; j++)
                {
                    y_dft_pot[j] = dft_pot.mat[i, j];
                }

                // calculate its eigendecomposition
                DoubleHermitianMatrix h_y = Create_Hamiltonian(y_dft_pot, ty, ny);

                eig_decomp = new DoubleHermitianEigDecomp(h_y);

                // insert the eigenstate into density and record the local confinement energy
                x_energy[i] = eig_decomp.EigenValue(0);
                for (int j = 0; j < ny; j++)
                {
                    double dens_tot = DoubleComplex.Norm(eig_decomp.EigenVector(0)[j]) * DoubleComplex.Norm(eig_decomp.EigenVector(0)[j]);
                    dens_up[i, j]   = 0.5 * dens_tot;
                    dens_down[i, j] = 0.5 * dens_tot;
                }
            }

            // check whether to enforce symmetry in the transverse direction
            if (force_symmetry)
            {
                for (int i = nx / 2 + 1; i < nx; i++)
                {
                    x_energy[i] = x_energy[nx - i - 1];
                    for (int j = 0; j < ny; j++)
                    {
                        dens_up[i, j]   = dens_up[nx - i - 1, j];
                        dens_down[i, j] = dens_down[nx - i - 1, j];
                    }
                }
            }

            // calculate the eigenstates in the x-direction
            DoubleHermitianMatrix h_x = Create_Hamiltonian(x_energy, tx, nx);

            eig_decomp = new DoubleHermitianEigDecomp(h_x);
            energies   = eig_decomp.EigenValues;

            // put the calculated densities into charge_density
            charge_density = new SpinResolved_Data(new Band_Data(dens_up), new Band_Data(dens_down));

            return(eig_decomp);
        }
Ejemplo n.º 8
0
        public override void Get_ChargeDensity_Deriv(ILayer[] layers, ref SpinResolved_Data charge_density_deriv, Band_Data chem_pot)
        {
            Get_SOI_parameters(chem_pot);

            //   if (dV_x == null)
            //       throw new Exception("Error - Band structure derivatives are null!  Have you initiated this type properly by calling Get_SOI_parameters(Band_Data chem_pot)?");

            // convert the chemical potential into a quantum mechanical potential
            Band_Data dft_pot = chem_pot.DeepenThisCopy();

            Get_Potential(ref dft_pot, layers);

            // reset charge density
            charge_density_deriv = 0.0 * charge_density_deriv;

            // integrate up density from k = 0 to k = k_F
            int    count = 0;
            double k     = 0;

            // create initial hamiltonian and eigendecomposition
            int max_wavefunction_old_p, max_wavefunction_old_m;
            DoubleHermitianMatrix    hamiltonian_p    = Create_H_Using_SOIP(dft_pot, k);
            DoubleHermitianEigDecomp eig_decomp_old_p = Diagonalise_Hamiltonian(hamiltonian_p, out max_wavefunction_old_p);
            DoubleHermitianEigDecomp eig_decomp_old_m = Diagonalise_Hamiltonian(hamiltonian_p, out max_wavefunction_old_m);

            while (k < kmax)
            {
                // increment the wavevector
                k     += delta_k;
                count += 1;

                // create new decompositions for forwards and backwards analysis
                int max_wavefunction_p, max_wavefunction_m;
                DoubleHermitianEigDecomp eig_decomp_p = Diagonalise_Hamiltonian(Create_H_Using_SOIP(dft_pot, k), out max_wavefunction_p);
                DoubleHermitianEigDecomp eig_decomp_m = Diagonalise_Hamiltonian(Create_H_Using_SOIP(dft_pot, -1.0 * k), out max_wavefunction_m);

                SpinResolved_Data new_charge_deriv = new SpinResolved_Data(nx, ny);

                // cycle over each of the positive bands
                for (int i = 0; i < max_wavefunction_p; i++)
                {
                    new_charge_deriv += Calculate_Density_Derivative(eig_decomp_old_p, eig_decomp_p, i);
                }
                // and negative bands
                for (int i = 0; i < max_wavefunction_m; i++)
                {
                    new_charge_deriv += Calculate_Density_Derivative(eig_decomp_old_m, eig_decomp_m, i);
                }

                // set new eigenvalue decompositions and max_wavefunctions to the old ones
                eig_decomp_old_m       = eig_decomp_m; eig_decomp_old_p = eig_decomp_p;
                max_wavefunction_old_m = max_wavefunction_m; max_wavefunction_old_p = max_wavefunction_p;

                // and finally, add the charge density calculated
                charge_density_deriv += new_charge_deriv;
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Calculate the charge density for this potential
        /// NOTE!!! that the boundary potential is (essentially) set to infty by ringing the density with a set of zeros.
        ///         this prevents potential solvers from extrapolating any residual density at the edge of the eigenstate
        ///         solution out of the charge density calculation domain
        /// </summary>
        /// <param name="layers"></param>
        /// <param name="charge_density"></param>
        /// <param name="chem_pot"></param>
        public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot)
        {
            // convert the chemical potential into a quantum mechanical potential
            Band_Data dft_pot = chem_pot.DeepenThisCopy();

            Get_Potential(ref dft_pot, layers);

            DoubleHermitianMatrix          hamiltonian = Create_Hamiltonian(layers, dft_pot);
            DoubleHermitianEigDecompServer eig_server  = new DoubleHermitianEigDecompServer();

            eig_server.ComputeEigenValueRange(dft_pot.mat.Min(), no_kb_T * Physics_Base.kB * temperature);
            eig_server.ComputeVectors = true;
            DoubleHermitianEigDecomp eig_decomp = eig_server.Factor(hamiltonian);

            int max_wavefunction = 0;

            if (eig_decomp.EigenValues.Length != 0)
            {
                double min_eigval = eig_decomp.EigenValues.Min();
                max_wavefunction = (from val in eig_decomp.EigenValues
                                    where val < no_kb_T * Physics_Base.kB * temperature
                                    select val).ToArray().Length;
            }

            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    double dens_val = 0.0;

                    // do not add anything to the density if on the edge of the domain
                    if (i == 0 || i == nx - 1 || j == 0 || j == ny - 1)
                    {
                        charge_density.Spin_Up.mat[i, j]   = 0.0;
                        charge_density.Spin_Down.mat[i, j] = 0.0;
                        continue;
                    }

                    for (int k = 0; k < max_wavefunction; k++)
                    {
                        // and integrate the density of states at this position for this eigenvector from the minimum energy to
                        // (by default) 50 * k_b * T above mu = 0
                        dens_val += DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * Get_OneD_DoS(eig_decomp.EigenValue(k), no_kb_T);
                    }

                    // just share the densities (there is no spin polarisation)
                    charge_density.Spin_Up.mat[i, j]   = 0.5 * dens_val;
                    charge_density.Spin_Down.mat[i, j] = 0.5 * dens_val;
                }
            }

            // and multiply the density by -e to get the charge density (as these are electrons)
            charge_density = unit_charge * charge_density;
        }
Ejemplo n.º 10
0
        /// <summary>
        /// returns the eigen-energies for the given potential and charge density
        /// </summary>
        public override DoubleVector Get_EnergyLevels(ILayer[] layers, Band_Data pot)
        {
            // convert the chemical potential into a quantum mechanical potential
            Band_Data band_pot = pot.DeepenThisCopy();

            Get_Potential(ref band_pot, layers);

            DoubleHermitianMatrix    hamiltonian = Create_Hamiltonian(layers, band_pot);
            DoubleHermitianEigDecomp eig_decomp  = new DoubleHermitianEigDecomp(hamiltonian);

            return(eig_decomp.EigenValues);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Calculate the charge density for this potential
        /// NOTE!!! that the boundary potential is (essentially) set to infty by ringing the density with a set of zeros.
        ///         this prevents potential solvers from extrapolating any residual density at the edge of the eigenstate
        ///         solution out of the charge density calculation domain
        /// </summary>
        /// <param name="layers"></param>
        /// <param name="charge_density_deriv"></param>
        /// <param name="chem_pot"></param>
        public void Get_ChargeDensity_Deriv(ILayer[] layers, ref SpinResolved_Data charge_density_deriv, Band_Data chem_pot)
        {
            // interpolate the input charge density and chemical potential onto a reduced domain to simplify DFT solve
            SpinResolved_Data dft_dens_deriv = new SpinResolved_Data(nz);

            Get_ChargeDensity(layers, ref charge_density_deriv, chem_pot);
            Band_Data dft_pot = new Band_Data(new DoubleVector(nz));

            Interpolate_DFT_Grid(ref dft_dens_deriv, ref dft_pot, charge_density_deriv, chem_pot);
            Get_Potential(ref dft_pot, layers);

            //     // set dft_dens to zero so that the hamiltonian doesn't include the XC term
            //     dft_dens = 0.0 * dft_dens;

            DoubleHermitianMatrix    hamiltonian = Create_Hamiltonian(layers, dft_pot);
            DoubleHermitianEigDecomp eig_decomp  = new DoubleHermitianEigDecomp(hamiltonian);

            double min_eigval = eig_decomp.EigenValues.Min();

            max_wavefunction = (from val in eig_decomp.EigenValues
                                where val < no_kb_T * Physics_Base.kB * temperature
                                select val).ToArray().Length;

            DoubleVector dens_up_deriv   = new DoubleVector(nz, 0.0);
            DoubleVector dens_down_deriv = new DoubleVector(nz, 0.0);

            for (int j = 0; j < nz; j++)
            {
                double dens_val = 0.0;
                for (int i = 0; i < max_wavefunction; i++)
                {
                    // and integrate the density of states at this position for this eigenvector from the minimum energy to
                    // (by default) 50 * k_b * T above mu = 0
                    //dens_val += dens_of_states.Integrate(min_eigval, no_kb_T * Physics_Base.kB * temperature);
                    dens_val += DoubleComplex.Norm(eig_decomp.EigenVector(i)[j]) * DoubleComplex.Norm(eig_decomp.EigenVector(i)[j]) * Get_TwoD_DoS_Deriv(eig_decomp.EigenValue(i), no_kb_T);// *mass / (2.0 * Math.PI * Physics_Base.hbar * Physics_Base.hbar);
                }

                // just share the densities (there is no spin polarisation)
                dens_up_deriv[j]   = 0.5 * dens_val;
                dens_down_deriv[j] = 0.5 * dens_val;
            }

            // and multiply the density derivative by e to get the charge density and by e to convert it to d/dphi (as increasing phi decreases the charge: dn/dphi*-e^2 )
            dft_dens_deriv = -1.0 * unit_charge * unit_charge * new SpinResolved_Data(new Band_Data(dens_up_deriv), new Band_Data(dens_down_deriv));

            Insert_DFT_Charge(ref charge_density_deriv, dft_dens_deriv);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// returns an eigenvector decomposition for the xy-plane after having calculated the density in the
        /// z-direction and storing it in "charge_density"
        /// </summary>
        /// <param name="dft_pot"></param>
        /// <param name="charge_density"></param>
        /// <returns></returns>
        private double[,] Solve_Eigenvector_Problem(Band_Data dft_pot, ref SpinResolved_Data charge_density)
        {
            DoubleHermitianEigDecomp eig_decomp;

            double[,] xy_energy = new double[nx, ny];
            Band_Data dens_up   = new Band_Data(nx, ny, nz, 0.0);
            Band_Data dens_down = new Band_Data(nx, ny, nz, 0.0);

            // cycle over xy-plane calculating the ground state energy and eigenstate in the growth direction
            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    // pull out the chemical potential for this slice
                    double[] z_dft_pot = new double[nz];
                    for (int k = 0; k < nz; k++)
                    {
                        z_dft_pot[k] = dft_pot.vol[k][i, j];
                    }

                    // calculate its eigendecomposition
                    DoubleHermitianMatrix h_z = Create_Hamiltonian(z_dft_pot, tz, nz);

                    eig_decomp = new DoubleHermitianEigDecomp(h_z);

                    // insert the eigenstate into density and record the local confinement energy
                    xy_energy[i, j] = eig_decomp.EigenValue(0);
                    for (int k = 0; k < nz; k++)
                    {
                        double dens_tot = DoubleComplex.Norm(eig_decomp.EigenVector(0)[k]) * DoubleComplex.Norm(eig_decomp.EigenVector(0)[k]);
                        dens_up.vol[k][i, j]   = 0.5 * dens_tot;
                        dens_down.vol[k][i, j] = 0.5 * dens_tot;
                    }
                }
            }

            // calculate the eigenstates in the xy-plane

            /*DoubleHermitianMatrix h_xy = Create_2DEG_Hamiltonian(xy_energy, tx, ty, nx, ny, true, false);
             * eig_decomp = new DoubleHermitianEigDecomp(h_xy);
             * energies = eig_decomp.EigenValues;*/

            // put the calculated densities into charge_density
            charge_density = new SpinResolved_Data(dens_up, dens_down);

            return(xy_energy);
        }
Ejemplo n.º 13
0
        public void Write_Out_Hamiltonian(DoubleHermitianMatrix h)
        {
            System.IO.StreamWriter sw = new System.IO.StreamWriter("hamiltonian.dat");
            for (int i = 0; i < h.Cols; i++)
            {
                for (int j = 0; j < h.Rows; j++)
                {
                    sw.Write(h[i, j].Real.ToString() + '\t');
                    if (j == h.Rows - 1)
                    {
                        sw.WriteLine();
                    }
                }
            }

            sw.Close();
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Calculate the charge density for this potential
        /// NOTE!!! that the boundary potential is (essentially) set to infty by ringing the density with a set of zeros.
        ///         this prevents potential solvers from extrapolating any residual density at the edge of the eigenstate
        ///         solution out of the charge density calculation domain
        /// </summary>
        /// <param name="layers"></param>
        /// <param name="charge_density_deriv"></param>
        /// <param name="chem_pot"></param>
        public override void Get_ChargeDensity_Deriv(ILayer[] layers, ref SpinResolved_Data charge_density_deriv, Band_Data chem_pot)
        {
            // convert the chemical potential into a quantum mechanical potential
            Band_Data dft_pot = chem_pot.DeepenThisCopy();

            Get_Potential(ref dft_pot, layers);

            DoubleHermitianMatrix    hamiltonian = Create_Hamiltonian(layers, dft_pot);
            DoubleHermitianEigDecomp eig_decomp  = new DoubleHermitianEigDecomp(hamiltonian);

            double min_eigval       = eig_decomp.EigenValues.Min();
            int    max_wavefunction = (from val in eig_decomp.EigenValues
                                       where val < no_kb_T * Physics_Base.kB * temperature
                                       select val).ToArray().Length;

            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    double dens_val_deriv = 0.0;

                    // do not add anything to the density if on the edge of the domain
                    if (i == 0 || i == nx - 1 || j == 0 || j == ny - 1)
                    {
                        charge_density_deriv.Spin_Up.mat[i, j]   = 0.0;
                        charge_density_deriv.Spin_Down.mat[i, j] = 0.0;
                        continue;
                    }

                    for (int k = 0; k < max_wavefunction; k++)
                    {
                        // and integrate the density of states at this position for this eigenvector from the minimum energy to
                        // (by default) 50 * k_b * T above mu = 0
                        dens_val_deriv += DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * Get_OneD_DoS_Deriv(eig_decomp.EigenValue(k), no_kb_T);
                    }

                    // just share the densities (there is no spin polarisation)
                    charge_density_deriv.Spin_Up.mat[i, j]   = 0.5 * dens_val_deriv;
                    charge_density_deriv.Spin_Down.mat[i, j] = 0.5 * dens_val_deriv;
                }
            }

            // and multiply the density derivative by e to get the charge density and by e to convert it to d/dphi (as increasing phi decreases the charge: dn/dphi*-e^2 )
            charge_density_deriv = unit_charge * unit_charge * charge_density_deriv;
        }
Ejemplo n.º 15
0
        DoubleHermitianMatrix Create_Hamiltonian(ILayer[] layers, Band_Data pot)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(nz);

            // set off diagonal elements
            for (int i = 0; i < nz - 1; i++)
            {
                result[i + 1, i] = t; result[i, i + 1] = t;
            }

            // set diagonal elements
            for (int i = 0; i < nz; i++)
            {
                result[i, i] = -2.0 * t + pot[i];
            }

            return(result);
        }
Ejemplo n.º 16
0
        DoubleHermitianMatrix Create_NoSOI_Hamiltonian(Band_Data dft_pot, double k, int nx, int ny)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(nx * ny);

            // set off diagonal elements
            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    // coupling sites in the growth direction
                    if (i != 0)
                    {
                        result[i * ny + j, i *ny + j - ny] = tx;
                    }
                    if (i != nx - 1)
                    {
                        result[i * ny + j, i *ny + j + ny] = tx;
                    }
                    // coupling sites in the transverse direction
                    if (j != 0)
                    {
                        result[i * ny + j, i *ny + j - 1] = ty;
                    }
                    if (j != ny - 1)
                    {
                        result[i * ny + j, i *ny + j + 1] = ty;
                    }
                }
            }

            double[,] potential = new double[nx, ny];
            // set diagonal elements
            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    potential[i, j]  = dft_pot.mat[i, j];
                    potential[i, j] += Physics_Base.hbar * Physics_Base.hbar * k * k / (2.0 * mass);
                    result[i * ny + j, i *ny + j] = -2.0 * tx + -2.0 * ty + potential[i, j];
                }
            }

            return(result);
        }
Ejemplo n.º 17
0
        public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot)
        {
            // interpolate the input charge density and chemical potential onto a reduced domain to simplify DFT solve
            SpinResolved_Data dft_dens = new SpinResolved_Data(nz);
            Band_Data         dft_pot  = new Band_Data(new DoubleVector(nz));

            Interpolate_DFT_Grid(ref dft_dens, ref dft_pot, charge_density, chem_pot);
            Get_Potential(ref dft_pot, layers);

            DoubleHermitianMatrix    hamiltonian = Create_Hamiltonian(layers, dft_pot);
            DoubleHermitianEigDecomp eig_decomp  = new DoubleHermitianEigDecomp(hamiltonian);

            double min_eigval = eig_decomp.EigenValues.Min();

            max_wavefunction = (from val in eig_decomp.EigenValues
                                where val < no_kb_T * Physics_Base.kB * temperature
                                select val).ToArray().Length;

            DoubleVector dens_up   = new DoubleVector(nz, 0.0);
            DoubleVector dens_down = new DoubleVector(nz, 0.0);

            for (int j = 0; j < nz; j++)
            {
                double dens_val = 0.0;
                for (int i = 0; i < max_wavefunction; i++)
                {
                    // and integrate the density of states at this position for this eigenvector from the minimum energy to
                    // (by default) 50 * k_b * T above mu = 0
                    //dens_val += dens_of_states.Integrate(min_eigval, no_kb_T * Physics_Base.kB * temperature);
                    dens_val += DoubleComplex.Norm(eig_decomp.EigenVector(i)[j]) * DoubleComplex.Norm(eig_decomp.EigenVector(i)[j]) * Get_TwoD_DoS(eig_decomp.EigenValue(i), no_kb_T);
                }

                // just share the densities (there is no spin polarisation)
                dens_up[j]   = 0.5 * dens_val;
                dens_down[j] = 0.5 * dens_val;
            }

            // and multiply the density by -e to get the charge density (as these are electrons)
            dft_dens = unit_charge * new SpinResolved_Data(new Band_Data(dens_up), new Band_Data(dens_down));

            Insert_DFT_Charge(ref charge_density, dft_dens);
        }
Ejemplo n.º 18
0
        DoubleHermitianMatrix Create_Hamiltonian(ILayer[] layers, Band_Data pot)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(nx * ny);

            // set off diagonal elements
            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    // coupling sites in the transverse direction
                    if (i != 0)
                    {
                        result[i * ny + j, i *ny + j - ny] = tx;
                    }
                    if (i != nx - 1)
                    {
                        result[i * ny + j, i *ny + j + ny] = tx;
                    }
                    // coupling sites in the growth direction
                    if (j != 0)
                    {
                        result[i * ny + j, i *ny + j - 1] = ty;
                    }
                    if (j != ny - 1)
                    {
                        result[i * ny + j, i *ny + j + 1] = ty;
                    }
                }
            }

            double[,] potential = new double[nx, ny];
            // set diagonal elements
            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    result[i * ny + j, i *ny + j] = -2.0 * tx + -2.0 * ty + pot.mat[i, j];
                }
            }

            return(result);
        }
Ejemplo n.º 19
0
        DoubleHermitianEigDecomp Diagonalise_Hamiltonian(DoubleHermitianMatrix hamiltonian, out int max_wavefunction)
        {
            DoubleHermitianEigDecomp eig_decomp;

            DoubleHermitianEigDecompServer eig_server = new DoubleHermitianEigDecompServer();

            eig_server.ComputeEigenValueRange(E_min, no_kb_T * Physics_Base.kB * temperature);
            eig_server.ComputeVectors = true;
            eig_decomp = eig_server.Factor(hamiltonian);

            max_wavefunction = 0;
            if (eig_decomp.EigenValues.Length != 0)
            {
                double min_eigval = eig_decomp.EigenValues.Min();
                max_wavefunction = (from val in eig_decomp.EigenValues
                                    where val < no_kb_T * Physics_Base.kB * temperature
                                    select val).ToArray().Length;
            }

            return(eig_decomp);
        }
Ejemplo n.º 20
0
 DoubleComplexMatrix Product(DoubleHermitianMatrix A, DoubleComplexMatrix B)
 {
     return new DoubleComplexMatrix(NMathFunctions.Product(MatrixFunctions.ToGeneralMatrix(A), B));
 }
Ejemplo n.º 21
0
        DoubleHermitianMatrix Create_SOI_Hamiltonian(Direction dV, Direction p, double k, int nx, int ny)
        {
            DoubleHermitianMatrix result = 0.0 * new DoubleHermitianMatrix(nx * ny);
            Band_Data             dV_data;

            if (dV == Direction.x)
            {
                return(result);
            }
            else if (dV == Direction.y)
            {
                dV_data = dV_x;
            }
            else if (dV == Direction.z)
            {
                dV_data = dV_y;
            }
            else
            {
                throw new Exception("Error - It's completely impossible to get here");
            }

            if (p == Direction.x)
            {
                for (int i = 0; i < nx; i++)
                {
                    for (int j = 0; j < ny; j++)
                    {
                        result[i * ny + j, i *ny + j] = Physics_Base.hbar * k * dV_data.mat[i, j];
                    }
                }
            }
            else if (p == Direction.y)
            {
                for (int i = 0; i < nx; i++)
                {
                    for (int j = 0; j < ny; j++)
                    {
                        if (i != nx - 1)
                        {
                            result[i * ny + j, i *ny + j + ny] = -0.5 * I * Physics_Base.hbar * dV_data.mat[i, j] / dx;
                        }
                        if (i != 0)
                        {
                            result[i * ny + j, i *ny + j - ny] = 0.5 * I * Physics_Base.hbar * dV_data.mat[i, j] / dx;
                        }
                    }
                }
            }
            else if (p == Direction.z)
            {
                for (int i = 0; i < nx; i++)
                {
                    for (int j = 0; j < ny; j++)
                    {
                        if (i != nx - 1)
                        {
                            result[i * ny + j, i *ny + j + 1] = -0.5 * I * Physics_Base.hbar * dV_data.mat[i, j] / dy;
                        }
                        if (i != 0)
                        {
                            result[i * ny + j, i *ny + j - 1] = 0.5 * I * Physics_Base.hbar * dV_data.mat[i, j] / dy;
                        }
                    }
                }
            }
            else
            {
                throw new Exception("Error - It's completely impossible to get here");
            }

            return(result);
        }
Ejemplo n.º 22
0
 DoubleComplexMatrix Product(DoubleHermitianMatrix A, DoubleComplexMatrix B)
 {
     return(new DoubleComplexMatrix(NMathFunctions.Product(MatrixFunctions.ToGeneralMatrix(A), B)));
 }
Ejemplo n.º 23
0
        private DoubleHermitianMatrix Create_SOIP_Matrix(Direction p, Direction dV, Direction sigma, double k, int nx, int ny)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(2 * nx * ny);

            double    theta;
            Band_Data dV_data;

            if (dV == Direction.x)
            {
                dV_data = dV_x;
                theta   = theta_x;
            }
            else if (dV == Direction.y)
            {
                dV_data = dV_y;
                theta   = theta_y;
            }
            else if (dV == Direction.z)
            {
                dV_data = new Band_Data(nx, ny, 0.0);
                theta   = 0.0;
            }
            else
            {
                throw new Exception("Error - It's completely impossible to get here");
            }


            if (p == Direction.x)
            {
                if (sigma == Direction.x)
                {
                    throw new InvalidArgumentException("Error - no spin-orbit interaction between p_x and sigma_x");
                }
                else if (sigma == Direction.y)
                {
                    throw new NotImplementedException();
                }
                else if (sigma == Direction.z)
                {
                    for (int i = 0; i < nx; i++)
                    {
                        for (int j = 0; j < ny; j++)
                        {
                            // off-diagonal couplings in x backward
                            if (i != 0)
                            {
                                // for up -> up
                                result[i * ny + j, i *ny + j - ny] = NMathFunctions.Exp(-1.0 * I * theta * dV_data.mat[i, j]) * tx;
                                // for down -> down
                                result[i * ny + j + nx * ny, i *ny + j - ny + nx * ny] = NMathFunctions.Exp(I * theta * dV_data.mat[i, j]) * tx;
                            }
                            // off-diagonal couplings in x forward
                            if (i != nx - 1)
                            {
                                // for up -> up
                                result[i * ny + j, i *ny + j + ny] = NMathFunctions.Exp(-1.0 * I * theta * dV_data.mat[i, j]) * tx;
                                // for down -> down
                                result[i * ny + j + nx * ny, i *ny + j + ny + nx * ny] = NMathFunctions.Exp(I * theta * dV_data.mat[i, j]) * tx;
                            }
                            // and diagonal couplings
                            result[i * ny + j, i *ny + j] = -2.0 * Math.Cos(theta * dV_data.mat[i, j]) * tx;
                            result[i * ny + j + nx * ny, i *ny + j + nx * ny] = -2.0 * Math.Cos(theta * dV_data.mat[i, j]) * tx;
                        }
                    }
                }
                else
                {
                    throw new Exception("Error - It's completely impossible to get here");
                }
            }
            else if (p == Direction.y)
            {
                if (sigma == Direction.x)
                {
                    throw new NotImplementedException();
                }
                else if (sigma == Direction.y)
                {
                    throw new InvalidArgumentException("Error - no spin-orbit interaction between p_y and sigma_y");
                }
                else if (sigma == Direction.z)
                {
                    for (int i = 0; i < nx; i++)
                    {
                        for (int j = 0; j < ny; j++)
                        {
                            // off-diagonal couplings in y backward
                            if (j != 0)
                            {
                                // for up -> up
                                result[i * ny + j, i *ny + j - 1] = NMathFunctions.Exp(-1.0 * I * theta * dV_data.mat[i, j]) * ty;
                                // for down -> down
                                result[i * ny + j + nx * ny, i *ny + j - 1 + nx * ny] = NMathFunctions.Exp(I * theta * dV_data.mat[i, j]) * ty;
                            }
                            // off-diagonal couplings in y forward
                            if (j != ny - 1)
                            {
                                // for up -> up
                                result[i * ny + j, i *ny + j + 1] = NMathFunctions.Exp(-1.0 * I * theta * dV_data.mat[i, j]) * ty;
                                // for down -> down
                                result[i * ny + j + nx * ny, i *ny + j + 1 + nx * ny] = NMathFunctions.Exp(I * theta * dV_data.mat[i, j]) * ty;
                            }
                            // and diagonal couplings
                            result[i * ny + j, i *ny + j] = -2.0 * Math.Cos(theta * dV_data.mat[i, j]) * ty;
                            result[i * ny + j + nx * ny, i *ny + j + nx * ny] = -2.0 * Math.Cos(theta * dV_data.mat[i, j]) * ty;
                        }
                    }
                }
                else
                {
                    throw new Exception("Error - It's completely impossible to get here");
                }
            }
            else if (p == Direction.z)
            {
                throw new NotImplementedException("Error - at the moment, when momentum is in the direction of the wire, you should use a different method");
            }
            else
            {
                throw new Exception("Error - It's completely impossible to get here");
            }

            return(result);
        }
Ejemplo n.º 24
0
        public void Write_Out_Hamiltonian(DoubleHermitianMatrix h)
        {
            System.IO.StreamWriter sw = new System.IO.StreamWriter("hamiltonian.dat");
            for (int i = 0; i < h.Cols; i++)
                for (int j = 0; j < h.Rows; j++)
                {
                    sw.Write(h[i, j].Real.ToString() + '\t');
                    if (j == h.Rows - 1)
                        sw.WriteLine();
                }

            sw.Close();
        }
Ejemplo n.º 25
0
        DoubleHermitianEigDecomp Diagonalise_Hamiltonian(DoubleHermitianMatrix hamiltonian, out int max_wavefunction)
        {
            DoubleHermitianEigDecomp eig_decomp;

            DoubleHermitianEigDecompServer eig_server = new DoubleHermitianEigDecompServer();
            eig_server.ComputeEigenValueRange(E_min, no_kb_T * Physics_Base.kB * temperature);
            eig_server.ComputeVectors = true;
            eig_decomp = eig_server.Factor(hamiltonian);

            max_wavefunction = 0;
            if (eig_decomp.EigenValues.Length != 0)
            {
                double min_eigval = eig_decomp.EigenValues.Min();
                max_wavefunction = (from val in eig_decomp.EigenValues
                                    where val < no_kb_T * Physics_Base.kB * temperature
                                    select val).ToArray().Length;
            }

            return eig_decomp;
        }
Ejemplo n.º 26
0
        private DoubleHermitianMatrix Create_SOIP_Matrix(Direction p, Direction dV, Direction sigma, double k, int nx, int ny)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(2 * nx * ny);

            double theta;
            Band_Data dV_data;

            if (dV == Direction.x)
            {
                dV_data = dV_x;
                theta = theta_x;
            }
            else if (dV == Direction.y)
            {
                dV_data = dV_y;
                theta = theta_y;
            }
            else if (dV == Direction.z)
            {
                dV_data = new Band_Data(nx, ny, 0.0);
                theta = 0.0;
            }
            else
                throw new Exception("Error - It's completely impossible to get here");

            if (p == Direction.x)
                if (sigma == Direction.x)
                    throw new InvalidArgumentException("Error - no spin-orbit interaction between p_x and sigma_x");
                else if (sigma == Direction.y)
                    throw new NotImplementedException();
                else if (sigma == Direction.z)
                {
                    for (int i = 0; i < nx; i++)
                        for(int j = 0; j < ny; j++)
                        {
                            // off-diagonal couplings in x backward
                            if (i != 0)
                            {
                                // for up -> up
                                result[i * ny + j, i * ny + j - ny] = NMathFunctions.Exp(-1.0 * I * theta * dV_data.mat[i, j]) * tx;
                                // for down -> down
                                result[i * ny + j + nx * ny, i * ny + j - ny + nx * ny] = NMathFunctions.Exp(I * theta * dV_data.mat[i, j]) * tx;
                            }
                            // off-diagonal couplings in x forward
                            if (i != nx - 1)
                            {
                                // for up -> up
                                result[i * ny + j, i * ny + j + ny] = NMathFunctions.Exp(-1.0 * I * theta * dV_data.mat[i, j]) * tx;
                                // for down -> down
                                result[i * ny + j + nx * ny, i * ny + j + ny + nx * ny] = NMathFunctions.Exp(I * theta * dV_data.mat[i, j]) * tx;
                            }
                            // and diagonal couplings
                            result[i * ny + j, i * ny + j] = -2.0 * Math.Cos(theta * dV_data.mat[i, j]) * tx;
                            result[i * ny + j + nx * ny, i * ny + j + nx * ny] = -2.0 * Math.Cos(theta * dV_data.mat[i, j]) * tx;
                        }
                }
                else
                    throw new Exception("Error - It's completely impossible to get here");
            else if (p == Direction.y)
                if (sigma == Direction.x)
                    throw new NotImplementedException();
                else if (sigma == Direction.y)
                    throw new InvalidArgumentException("Error - no spin-orbit interaction between p_y and sigma_y");
                else if (sigma == Direction.z)
                {
                    for (int i = 0; i < nx; i++)
                        for (int j = 0; j < ny; j++)
                        {
                            // off-diagonal couplings in y backward
                            if (j != 0)
                            {
                                // for up -> up
                                result[i * ny + j, i * ny + j - 1] = NMathFunctions.Exp(-1.0 * I * theta * dV_data.mat[i, j]) * ty;
                                // for down -> down
                                result[i * ny + j + nx * ny, i * ny + j - 1 + nx * ny] = NMathFunctions.Exp(I * theta * dV_data.mat[i, j]) * ty;
                            }
                            // off-diagonal couplings in y forward
                            if (j != ny - 1)
                            {
                                // for up -> up
                                result[i * ny + j, i * ny + j + 1] = NMathFunctions.Exp(-1.0 * I * theta * dV_data.mat[i, j]) * ty;
                                // for down -> down
                                result[i * ny + j + nx * ny, i * ny + j + 1 + nx * ny] = NMathFunctions.Exp(I * theta * dV_data.mat[i, j]) * ty;
                            }
                            // and diagonal couplings
                            result[i * ny + j, i * ny + j] = -2.0 * Math.Cos(theta * dV_data.mat[i, j]) * ty;
                            result[i * ny + j + nx * ny, i * ny + j + nx * ny] = -2.0 * Math.Cos(theta * dV_data.mat[i, j]) * ty;
                        }
                }
                else
                    throw new Exception("Error - It's completely impossible to get here");
            else if (p == Direction.z)
                throw new NotImplementedException("Error - at the moment, when momentum is in the direction of the wire, you should use a different method");
            else
                throw new Exception("Error - It's completely impossible to get here");

            return result;
        }
Ejemplo n.º 27
0
        DoubleHermitianMatrix Create_NoSOI_Hamiltonian(Band_Data dft_pot, double k, int nx, int ny)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(nx * ny);

            // set off diagonal elements
            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                {
                    // coupling sites in the growth direction
                    if (i != 0)
                        result[i * ny + j, i * ny + j - ny] = tx;
                    if (i != nx - 1)
                        result[i * ny + j, i * ny + j + ny] = tx;
                    // coupling sites in the transverse direction
                    if (j != 0)
                        result[i * ny + j, i * ny + j - 1] = ty;
                    if (j != ny - 1)
                        result[i * ny + j, i * ny + j + 1] = ty;
                }

            double[,] potential = new double[nx, ny];
            // set diagonal elements
            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                {
                    potential[i, j] = dft_pot.mat[i, j];
                    potential[i, j] += Physics_Base.hbar * Physics_Base.hbar * k * k / (2.0 * mass);
                    result[i * ny + j, i * ny + j] = -2.0 * tx + -2.0 * ty + potential[i, j];
                }

            return result;
        }
Ejemplo n.º 28
0
        DoubleHermitianMatrix Create_H_Using_SOIP(Band_Data dft_pot, double k)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(2 * nx * ny);

            // create the SOIP parts of the matrix
            result = Create_SOIP_Matrix(Direction.x, Direction.y, Direction.z, k, nx, ny);
            result += Create_SOIP_Matrix(Direction.y, Direction.x, Direction.z, k, nx, ny);

            // and add the scalar terms from the k-direction
            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                {
                    // add momentum and potential terms
                    result[i * ny + j, i * ny + j] += Physics_Base.hbar * Physics_Base.hbar * k * k / (2.0 * mass) + dft_pot.mat[i, j];
                    result[i * ny + j + nx * ny, i * ny + j + nx * ny] += Physics_Base.hbar * Physics_Base.hbar * k * k / (2.0 * mass) + dft_pot.mat[i, j];

                    // add spin-orbit terms
                    result[i * ny + j, i * ny + j + nx * ny] += (-1.0 * I * alpha * dV_x.mat[i, j] - alpha * dV_y.mat[i, j]) * k;
                    result[i * ny + j + nx * ny, i * ny + j] += (I * alpha * dV_x.mat[i, j] - alpha * dV_y.mat[i, j]) * k;
                }

            return result;
        }
Ejemplo n.º 29
0
        DoubleHermitianMatrix Create_Hamiltonian(Band_Data dft_pot, double k)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(2 * nx * ny);
            DoubleHermitianMatrix h_upup, h_updn, h_dnup, h_dndn;

            // create sub-matrices with no spin orbit
            h_upup = Create_NoSOI_Hamiltonian(dft_pot, k, nx, ny);      // takes up to up (ie. H_11)
            h_dndn = Create_NoSOI_Hamiltonian(dft_pot, k, nx, ny);      // takes dn to dn (ie. H_22)
            h_updn = new DoubleHermitianMatrix(nx * ny);                                // takes up to dn (ie. H_21)
            h_dnup = new DoubleHermitianMatrix(nx * ny);                                // takes dn to up (ie. H_12)

            // add spin-orbit
            h_upup -= alpha * Create_SOI_Hamiltonian(Direction.y, Direction.x, k, nx, ny);
            h_dndn -= -1.0 * alpha * Create_SOI_Hamiltonian(Direction.y, Direction.x, k, nx, ny);
            h_updn -= alpha * (Create_SOI_Hamiltonian(Direction.z, Direction.y, nx, ny) - Create_SOI_Hamiltonian(Direction.y, Direction.z, nx, ny)
                                + I * Create_SOI_Hamiltonian(Direction.z, Direction.x, k, nx, ny));
            h_dnup -= alpha * (Create_SOI_Hamiltonian(Direction.z, Direction.y, nx, ny) - Create_SOI_Hamiltonian(Direction.y, Direction.z, nx, ny)
                                - I * Create_SOI_Hamiltonian(Direction.z, Direction.x, k, nx, ny));

            // recombine matrices and output result
            for (int i = 0; i < nx * ny; i++)
                for (int j = 0; j < nx * ny; j++)
                {
                    result[i, j] = h_upup[i, j];
                    result[i, j + nx * ny] = h_dnup[i, j];
                    result[i + nx * ny, j] = h_updn[i, j];
                    result[i + nx * ny, j + nx * ny] = h_dndn[i, j];
                }

            return result;
        }
        DoubleHermitianMatrix Create_2DEG_Hamiltonian(double[,] V, double tx, double ty, int nx, int ny, bool periodic_in_x, bool periodic_in_y)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(nx * ny);

            // set off diagonal elements
            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                {
                    // coupling sites in the transport direction
                    if (i != 0)
                        result[i * ny + j, i * ny + j - ny] = tx;
                    if (i != nx - 1)
                        result[i * ny + j, i * ny + j + ny] = tx;
                    // coupling sites in the transverse direction
                    if (j != 0)
                        result[i * ny + j, i * ny + j - 1] = ty;
                    if (j != ny - 1)
                        result[i * ny + j, i * ny + j + 1] = ty;
                }

            // set diagonal elements
            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                    result[i * ny + j, i * ny + j] = -2.0 * tx + -2.0 * ty + V[i, j];

            // and finally, add periodic boundary conditions where appropriate
            if (periodic_in_x)
                for (int j = 0; j < ny; j++)
                {
                    result[j, j + (nx - 1) * ny] = tx;
                    result[j + (nx - 1) * ny, j] = tx;
                }
            if (periodic_in_y)
                for (int i = 0; i < nx; i++)
                {
                    result[i * ny + 1, i * ny] = ty;
                    result[i * ny, i * ny + 1] = ty;
                }

            return result;
        }
Ejemplo n.º 31
0
        DoubleHermitianMatrix Create_Hamiltonian(ILayer[] layers, Band_Data pot)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(nz);

            // set off diagonal elements
            for (int i = 0; i < nz - 1; i++)
            {
                result[i + 1, i] = t; result[i, i + 1] = t;
            }

            // set diagonal elements
            for (int i = 0; i < nz; i++)
            {
                result[i, i] = -2.0 * t + pot[i];
            }

            return result;
        }
Ejemplo n.º 32
0
        DoubleHermitianMatrix Create_Hamiltonian(ILayer[] layers, Band_Data pot)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(nx * ny);

            // set off diagonal elements
            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                {
                    // coupling sites in the transverse direction
                    if (i != 0)
                        result[i * ny + j, i * ny + j - ny] = tx;
                    if (i != nx - 1)
                        result[i * ny + j, i * ny + j + ny] = tx;
                    // coupling sites in the growth direction
                    if (j != 0)
                        result[i * ny + j, i * ny + j - 1] = ty;
                    if (j != ny - 1)
                        result[i * ny + j, i * ny + j + 1] = ty;
                }

            double[,] potential = new double[nx, ny];
            // set diagonal elements
            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                    result[i * ny + j, i * ny + j] = -2.0 * tx + -2.0 * ty + pot.mat[i, j];

            return result;
        }
        DoubleHermitianMatrix Create_Hamiltonian(double[] V, double t, int N)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(N);

            // set off diagonal elements
            for (int i = 0; i < N; i++)
            {
                // coupling sites in the growth direction
                if (i != 0)
                    result[i - 1, i] = t;
                if (i != N - 1)
                    result[i + 1, i] = t;
            }

            // set diagonal elements
            for (int i = 0; i < N; i++)
                result[i, i] = -2.0 * t + V[i];

            return result;
        }