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
        /// <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.º 3
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.º 4
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.º 5
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.º 6
0
        double Interpolate_Fermi_Function_Derivative(DoubleHermitianEigDecomp eig_decomp_old, DoubleHermitianEigDecomp eig_decomp_new, int wavefunction)
        {
            double E0    = eig_decomp_old.EigenValue(wavefunction);
            double dE_dk = (eig_decomp_new.EigenValue(wavefunction) - eig_decomp_old.EigenValue(wavefunction)) / delta_k;

            double beta = 1.0 / (Physics_Base.kB * temperature);
            OneVariableFunction dos_integrand = new OneVariableFunction((Func <double, double>)((double k) => - 1.0 * beta * Math.Exp(beta * (E0 + dE_dk * k)) * Math.Pow(Math.Exp(beta * (E0 + dE_dk * k)) + 1, -2.0)));

            dos_integrand.Integrator = new GaussKronrodIntegrator();

            return(dos_integrand.Integrate(0, delta_k));
        }
Ejemplo n.º 7
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.º 8
0
        public override DoubleVector Get_EnergyLevels(ILayer[] layers, 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);

            // diagonalise matrix for k = 0
            int tmp = 0;
            DoubleHermitianEigDecomp eig_decomp = Diagonalise_Hamiltonian(Create_Hamiltonian(dft_pot, 0.0), out tmp);

            return(eig_decomp.EigenValues);
        }
Ejemplo n.º 9
0
        void Output_Wavefunctions(DoubleHermitianEigDecomp eig, int no_wavefunctions)
        {
            for (int i = 0; i < no_wavefunctions; i++)
            {
                System.IO.StreamWriter sw = new System.IO.StreamWriter("wav_" + i.ToString("00"));

                for (int j = 0; j < nx; j++)
                {
                    sw.WriteLine((eig.EigenVector(i)[j].Real * Math.Sqrt(Get_OneD_DoS(eig.EigenValue(i), no_kb_T))).ToString());
                }

                sw.Close();
            }
        }
Ejemplo n.º 10
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.º 11
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.º 12
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.º 13
0
        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);

            DoubleHermitianEigDecomp eig_decomp = Solve_Eigenvector_Problem(dft_pot, ref charge_density);

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

            double[] dens_x = new double[nx];
            // and generate a density for the y-direction
            for (int i = 0; i < nx; i++)
            {
                for (int k = 0; k < max_wavefunction; k++)
                {
                    dens_x[i] += DoubleComplex.Norm(eig_decomp.EigenVector(k)[i]) * DoubleComplex.Norm(eig_decomp.EigenVector(k)[i]) * Get_OneD_DoS(energies[k], no_kb_T);
                }
            }

            // multiply the z-densities by the y-density
            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    // 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;
                    }

                    charge_density.Spin_Up.mat[i, j]   *= dens_x[i];
                    charge_density.Spin_Down.mat[i, j] *= dens_x[i];
                }
            }

            // and multiply the density by -e to get the charge density (as these are electrons)
            charge_density = unit_charge * charge_density;
        }
Ejemplo n.º 14
0
        void Write_Out_Wavefunction_Densities(DoubleHermitianEigDecomp eig_decomp)
        {
            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 k = 0; k < max_wavefunction; k++)
            {
                System.IO.StreamWriter sw  = new System.IO.StreamWriter("dens_wavefunction_" + k.ToString("00"));
                DoubleMatrix           tmp = new DoubleMatrix(nx, ny, 0.0);

                for (int i = 0; i < nx; i++)
                {
                    for (int j = 0; j < ny; j++)
                    {
                        // 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)
                        {
                            continue;
                        }

                        // 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
                        tmp[i, j] = unit_charge * 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);
                    }
                }

                for (int i = 0; i < nx; i++)
                {
                    for (int j = 0; j < ny; j++)
                    {
                        sw.Write(tmp[i, j].ToString() + '\t');
                        if (j == ny - 1)
                        {
                            sw.WriteLine();
                        }
                    }
                }

                sw.Close();
            }
        }
Ejemplo n.º 15
0
        public Band_Data Get_KS_KE(ILayer[] layers, 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);

            // create temporary density for input into...
            DoubleMatrix      dens_up   = new DoubleMatrix(nx, ny, 0.0);
            DoubleMatrix      dens_down = new DoubleMatrix(nx, ny, 0.0);
            SpinResolved_Data dens      = new SpinResolved_Data(new Band_Data(dens_up), new Band_Data(dens_down));

            // calculate eigenvectors
            DoubleHermitianEigDecomp eig_decomp = Solve_Eigenvector_Problem(dft_pot, ref dens);

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

            // generate kinetic energy data
            Band_Data ke           = new Band_Data(nx, ny, 0.0);
            Band_Data dens_tot     = dens.Spin_Summed_Data;
            double    ke_prefactor = -0.5 * Physics_Base.hbar * Physics_Base.hbar / mass;

            for (int i = 1; i < nx - 1; i++)
            {
                for (int j = 1; j < ny - 1; j++)
                {
                    for (int k = 0; k < max_wavefunction; k++)
                    {
                        double dy2psi = (dens_tot.mat[i, j + 1] + dens_tot.mat[i, j - 1] - 2.0 * dens_tot.mat[i, j]) * DoubleComplex.Norm(eig_decomp.EigenVector(k)[i]);
                        double dx2psi = DoubleComplex.Norm(eig_decomp.EigenVector(k)[i + 1] + eig_decomp.EigenVector(k)[i - 1] - 2.0 * eig_decomp.EigenVector(k)[i]) * dens_tot.mat[i, j];

                        double psi_div2psi = (dens_tot.mat[i, j] * DoubleComplex.Norm(eig_decomp.EigenVector(k)[i])) * (dx2psi + dy2psi);

                        ke.mat[i, j] += ke_prefactor * psi_div2psi * Get_OneD_DoS(eig_decomp.EigenValue(k), no_kb_T);
                    }
                }
            }

            return(ke);
        }
Ejemplo n.º 16
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.º 17
0
        SpinResolved_Data Calculate_Density_Derivative(DoubleHermitianEigDecomp eig_decomp_old, DoubleHermitianEigDecomp eig_decomp_new, int wavefunction)
        {
            DoubleMatrix dens_up_deriv   = new DoubleMatrix(nx, ny, 0.0);
            DoubleMatrix dens_down_deriv = new DoubleMatrix(nx, ny, 0.0);

            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    // 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)
                    {
                        continue;
                    }

                    // calculate the density of this spin configuration this hamiltonian
                    dens_up_deriv[i, j]   += g_1D * DoubleComplex.Norm(eig_decomp_old.EigenVector(wavefunction)[i * ny + j]) * DoubleComplex.Norm(eig_decomp_old.EigenVector(wavefunction)[i * ny + j]) * Interpolate_Fermi_Function_Derivative(eig_decomp_old, eig_decomp_new, wavefunction);
                    dens_down_deriv[i, j] += g_1D * DoubleComplex.Norm(eig_decomp_old.EigenVector(wavefunction)[i * ny + j + nx * ny]) * DoubleComplex.Norm(eig_decomp_old.EigenVector(wavefunction)[i * ny + j + nx * ny]) * Interpolate_Fermi_Function_Derivative(eig_decomp_old, eig_decomp_new, wavefunction);
                }
            }

            // and multiply the density by -e to get the charge density (as these are electrons)
            return(unit_charge * unit_charge * new SpinResolved_Data(new Band_Data(dens_up_deriv), new Band_Data(dens_down_deriv)));
        }
Ejemplo n.º 18
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.º 19
0
 void Output_Wavefunctions(DoubleHermitianEigDecomp eig, int no_wavefunctions)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 20
0
        void Output_Wavefunctions(DoubleHermitianEigDecomp eig, int no_wavefunctions)
        {
            for (int i = 0; i < no_wavefunctions; i++)
            {
                System.IO.StreamWriter sw = new System.IO.StreamWriter("wav_" + i.ToString("00"));

                for (int j = 0; j < nx; j++)
                    sw.WriteLine((eig.EigenVector(i)[j].Real * Math.Sqrt(Get_OneD_DoS(eig.EigenValue(i), no_kb_T))).ToString());

                sw.Close();
            }
        }
Ejemplo n.º 21
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.º 22
0
        double Interpolate_Fermi_Function_Derivative(DoubleHermitianEigDecomp eig_decomp_old, DoubleHermitianEigDecomp eig_decomp_new, int wavefunction)
        {
            double E0 = eig_decomp_old.EigenValue(wavefunction);
            double dE_dk = (eig_decomp_new.EigenValue(wavefunction) - eig_decomp_old.EigenValue(wavefunction)) / delta_k;

            double beta = 1.0 / (Physics_Base.kB * temperature);
            OneVariableFunction dos_integrand = new OneVariableFunction((Func<double, double>)((double k) => -1.0 * beta * Math.Exp(beta * (E0 + dE_dk * k)) * Math.Pow(Math.Exp(beta * (E0 + dE_dk * k)) + 1, -2.0)));
            dos_integrand.Integrator = new GaussKronrodIntegrator();

            return dos_integrand.Integrate(0, delta_k);
        }
Ejemplo n.º 23
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.º 24
0
        SpinResolved_Data Calculate_Density_Derivative(DoubleHermitianEigDecomp eig_decomp_old, DoubleHermitianEigDecomp eig_decomp_new, int wavefunction)
        {
            DoubleMatrix dens_up_deriv = new DoubleMatrix(nx, ny, 0.0);
            DoubleMatrix dens_down_deriv = new DoubleMatrix(nx, ny, 0.0);

            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                {
                    // 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)
                        continue;

                    // calculate the density of this spin configuration this hamiltonian
                    dens_up_deriv[i, j] += g_1D * DoubleComplex.Norm(eig_decomp_old.EigenVector(wavefunction)[i * ny + j]) * DoubleComplex.Norm(eig_decomp_old.EigenVector(wavefunction)[i * ny + j]) * Interpolate_Fermi_Function_Derivative(eig_decomp_old, eig_decomp_new, wavefunction);
                    dens_down_deriv[i, j] += g_1D * DoubleComplex.Norm(eig_decomp_old.EigenVector(wavefunction)[i * ny + j + nx * ny]) * DoubleComplex.Norm(eig_decomp_old.EigenVector(wavefunction)[i * ny + j + nx * ny]) * Interpolate_Fermi_Function_Derivative(eig_decomp_old, eig_decomp_new, wavefunction);
                }

            // and multiply the density by -e to get the charge density (as these are electrons)
            return unit_charge * unit_charge * new SpinResolved_Data(new Band_Data(dens_up_deriv), new Band_Data(dens_down_deriv));
        }
        /// <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>
        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;
                    }
                }

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

            return xy_energy;
        }
 void Output_Wavefunctions(DoubleHermitianEigDecomp eig, int no_wavefunctions)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 27
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.º 28
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.º 29
0
        void Write_Out_Wavefunction_Densities(DoubleHermitianEigDecomp eig_decomp)
        {
            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 k = 0; k < max_wavefunction; k++)
            {
                System.IO.StreamWriter sw = new System.IO.StreamWriter("dens_wavefunction_" + k.ToString("00"));
                DoubleMatrix tmp = new DoubleMatrix(nx, ny, 0.0);

                for (int i = 0; i < nx; i++)
                    for (int j = 0; j < ny; j++)
                    {
                        // 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)
                            continue;

                        // 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
                        tmp[i, j] = unit_charge * 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);
                    }

                for (int i = 0; i < nx; i++)
                    for (int j = 0; j < ny; j++)
                    {
                        sw.Write(tmp[i, j].ToString() + '\t');
                        if (j == ny - 1)
                            sw.WriteLine();
                    }

                sw.Close();
            }
        }
Ejemplo n.º 30
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);
        }