예제 #1
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;
            }
        }
예제 #2
0
        void Insert_DFT_Charge(ref SpinResolved_Data charge_density, SpinResolved_Data dft_dens)
        {
            for (int i = 0; i < nz; i++)
            {
                int init_index = (int)Math.Round((i * dz - zmin_pot + zmin) / dz_pot); // index for the initial domain (ie. for charge_density and band_offset)

                // no interpolation (it doesn't work...)
                charge_density.Spin_Up[init_index]   = dft_dens.Spin_Up[i];
                charge_density.Spin_Down[init_index] = dft_dens.Spin_Down[i];
            }
        }
예제 #3
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;
        }
예제 #4
0
        void Interpolate_DFT_Grid(ref SpinResolved_Data dft_dens, ref Band_Data dft_band_offset, SpinResolved_Data charge_density, Band_Data band_offset)
        {
            for (int i = 0; i < nz; i++)
            {
                int init_index = (int)Math.Round((i * dz - zmin_pot + zmin) / dz_pot); // index for the initial domain (ie. for charge_density and band_offset)

                // no interpolation (it doesn't work...)
                dft_dens.Spin_Up[i]   = charge_density.Spin_Up[init_index];
                dft_dens.Spin_Down[i] = charge_density.Spin_Down[init_index];
                dft_band_offset[i]    = band_offset[init_index];
            }
        }
예제 #5
0
        public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data density, Band_Data chem_pot)
        {
            SpinResolved_Data tmp_car = new SpinResolved_Data(new Band_Data(new DoubleVector(nz)), new Band_Data(new DoubleVector(nz)));
            SpinResolved_Data tmp_dop = new SpinResolved_Data(new Band_Data(new DoubleVector(nz)), new Band_Data(new DoubleVector(nz)));

            Get_ChargeDensity(layers, ref tmp_car, ref tmp_dop, chem_pot);

            for (int i = 0; i < nz; i++)
            {
                density.Spin_Up.vec[i]   = tmp_car.Spin_Up.vec[i] + tmp_dop.Spin_Up.vec[i];
                density.Spin_Down.vec[i] = tmp_car.Spin_Down.vec[i] + tmp_dop.Spin_Down.vec[i];
            }
        }
예제 #6
0
        protected override void Initialise_DataClasses(Dictionary <string, object> input_dict)
        {
            if (initialise_from_restart)
            {
                // initialise data classes for the density and chemical potential
                this.carrier_charge_density = new SpinResolved_Data(nz_dens);
                this.dopent_charge_density  = new SpinResolved_Data(nz_dens);
                this.chem_pot = new Band_Data(nz_dens, 0.0);
                Initialise_from_Restart(input_dict);
                // and instantiate their derivatives
                carrier_charge_density_deriv = new SpinResolved_Data(nz_dens);
                dopent_charge_density_deriv  = new SpinResolved_Data(nz_dens);

                chem_pot.Laplacian = pois_solv.Calculate_Phi_Laplacian(chem_pot);

                return;
            }
            else if (hot_start)
            {
                Initialise_from_Hot_Start(input_dict);
            }

            // try to get and the carrier and dopent density from the dictionary... they probably won't be there and if not... make them
            if (input_dict.ContainsKey("Carrier_Density"))
            {
                this.carrier_charge_density = (SpinResolved_Data)input_dict["Carrier_Density"];
            }
            else
            {
                this.carrier_charge_density = new SpinResolved_Data(nz_pot);
            }
            if (input_dict.ContainsKey("Dopent_Density"))
            {
                this.dopent_charge_density = (SpinResolved_Data)input_dict["Dopent_Density"];
            }
            else
            {
                this.dopent_charge_density = new SpinResolved_Data(nz_pot);
            }
            // and instantiate their derivatives
            carrier_charge_density_deriv = new SpinResolved_Data(nz_pot);
            dopent_charge_density_deriv  = new SpinResolved_Data(nz_pot);

            // and finally, try to get the chemical potential from the dictionary...
            if (input_dict.ContainsKey("Chemical_Potential"))
            {
                this.chem_pot = (Band_Data)input_dict["Chemical_Potential"];
            }
        }
예제 #7
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);
        }
        /// <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);
        }
예제 #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_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;
        }
예제 #10
0
        bool Check_Integration_Convergence(SpinResolved_Data density_k, double eps)
        {
            // checks whether the maximum (negative) density is less than eps
            double max_dens = 0.0;

            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    if (density_k.Spin_Up.mat[i, j] + density_k.Spin_Down.mat[i, j] < max_dens)
                    {
                        max_dens = density_k.Spin_Up.mat[i, j] + density_k.Spin_Down.mat[i, j];
                    }
                }
            }

            return(eps > -1.0 * max_dens);
        }
예제 #11
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;
        }
예제 #12
0
        public void Write_Out_Density(SpinResolved_Data h, string outfile)
        {
            Band_Data h_spin_summed = h.Spin_Summed_Data;

            System.IO.StreamWriter sw = new System.IO.StreamWriter(outfile);
            for (int i = 0; i < h_spin_summed.mat.Cols; i++)
            {
                for (int j = 0; j < h_spin_summed.mat.Rows; j++)
                {
                    sw.Write(h_spin_summed.mat[j, i].ToString() + '\t');
                    if (j == h_spin_summed.mat.Rows - 1)
                    {
                        sw.WriteLine();
                    }
                }
            }

            sw.Close();
        }
예제 #13
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);
        }
예제 #14
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);
        }
예제 #15
0
        public override SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_density_deriv, SpinResolved_Data dopent_density_deriv, Band_Data chem_pot)
        {
            // artificially deepen the copies of spin up and spin down
            Band_Data tmp_spinup   = new Band_Data(carrier_density_deriv.Spin_Up.vec.Length, 0.0);
            Band_Data tmp_spindown = new Band_Data(carrier_density_deriv.Spin_Up.vec.Length, 0.0);

            for (int i = 0; i < carrier_density_deriv.Spin_Up.vec.Length; i++)

            {
                tmp_spinup.vec[i]   = carrier_density_deriv.Spin_Up.vec[i];
                tmp_spindown.vec[i] = carrier_density_deriv.Spin_Down.vec[i];
            }

            SpinResolved_Data new_density = new SpinResolved_Data(tmp_spinup, tmp_spindown);

            // finally, get the charge density and send it to this new array
            Get_ChargeDensity_Deriv(layers, ref new_density, chem_pot);

            return(new_density);
        }
예제 #16
0
        void Initialise_from_1D(Dictionary <string, object> input_dict)
        {
            // get data from dictionary
            SpinResolved_Data tmp_1d_density = (SpinResolved_Data)input_dict["Carrier_Density"];
            SpinResolved_Data tmp_1d_dopdens = (SpinResolved_Data)input_dict["Dopent_Density"];
            Band_Data         tmp_pot_1d     = (Band_Data)input_dict["Chemical_Potential"];

            // calculate where the bottom of the 2D data is
            int offset_min = (int)Math.Round((zmin_dens - zmin_pot) / dz_pot);

            // input data from dictionary into arrays
            for (int i = 0; i < ny_dens; i++)
            {
                for (int j = 0; j < nz_dens; j++)
                {
                    chem_pot.mat[i, j] = tmp_pot_1d.vec[offset_min + j];

                    // do not add anything to the density if on the edge of the domain
                    if (i == 0 || i == ny_dens - 1 || j == 0 || j == nz_dens - 1)
                    {
                        continue;
                    }

                    // linearly interpolate with exponential envelope in the transverse direction
                    int    j_init = (int)Math.Floor(j * Dz_Dens / Dz_Pot);
                    double y      = (i - 0.5 * ny_dens) * dy_dens;
                    //double z = (j - 0.5 * nz_dens) * dz_dens;

                    // carrier data
                    double envelope = 0.0;                                                                                     //Math.Exp(-100.0 * y * y / ((double)(ny_dens * ny_dens) * dy_dens * dy_dens));// *Math.Exp(-10.0 * z * z / ((double)(nz_dens * nz_dens) * dz_dens * dz_dens));
                    carrier_charge_density.Spin_Up.mat[i, j]   = envelope * tmp_1d_density.Spin_Up.vec[offset_min + j_init];   // +(tmp_1d_density.Spin_Up.vec[offset_min + j_init + 1] - tmp_1d_density.Spin_Up.vec[offset_min + j_init]) * Dz_Dens / Dz_Pot;
                    carrier_charge_density.Spin_Down.mat[i, j] = envelope * tmp_1d_density.Spin_Down.vec[offset_min + j_init]; // +(tmp_1d_density.Spin_Down.vec[offset_min + j_init + 1] - tmp_1d_density.Spin_Down.vec[offset_min + j_init]) * Dz_Dens / Dz_Pot;

                    // dopent data
                    dopent_charge_density.Spin_Up.mat[i, j]   = tmp_1d_dopdens.Spin_Up.vec[offset_min + j_init] + (tmp_1d_dopdens.Spin_Up.vec[offset_min + j_init + 1] - tmp_1d_dopdens.Spin_Up.vec[offset_min + j_init]) * Dz_Dens / Dz_Pot;
                    dopent_charge_density.Spin_Down.mat[i, j] = tmp_1d_dopdens.Spin_Down.vec[offset_min + j_init] + (tmp_1d_dopdens.Spin_Down.vec[offset_min + j_init + 1] - tmp_1d_dopdens.Spin_Down.vec[offset_min + j_init]) * Dz_Dens / Dz_Pot;
                }
            }

            boundary_conditions.Add("surface", (double)input_dict["surface_charge"]);
        }
예제 #17
0
        public void Write_Out_Density(SpinResolved_Data h, string outfile)
        {
            Band_Data h_spin_summed = h.Spin_Summed_Data;

            System.IO.StreamWriter sw = new System.IO.StreamWriter(outfile);
            for (int k = 0; k < h_spin_summed.vol.Length; k++)
            {
                for (int i = 0; i < h_spin_summed.vol[k].Cols; i++)
                {
                    for (int j = 0; j < h_spin_summed.vol[k].Rows; j++)
                    {
                        sw.Write(h_spin_summed.vol[k][i, j].ToString() + '\t');
                        if (i == h_spin_summed.vol[k].Cols - 1 || j == h_spin_summed.vol[k].Rows - 1)
                        {
                            sw.WriteLine();
                        }
                    }
                }
            }

            sw.Close();
        }
예제 #18
0
        public override SpinResolved_Data Get_ChargeDensity(ILayer[] layers, SpinResolved_Data carrier_charge_density, SpinResolved_Data dopent_charge_density, Band_Data chem_pot)
        {
            // artificially deepen the copies of spin up and spin down
            Band_Data tmp_spinup   = new Band_Data(new DoubleMatrix(carrier_charge_density.Spin_Up.mat.Rows, carrier_charge_density.Spin_Up.mat.Cols));
            Band_Data tmp_spindown = new Band_Data(new DoubleMatrix(carrier_charge_density.Spin_Down.mat.Rows, carrier_charge_density.Spin_Down.mat.Cols));

            for (int i = 0; i < carrier_charge_density.Spin_Up.mat.Rows; i++)
            {
                for (int j = 0; j < carrier_charge_density.Spin_Up.mat.Cols; j++)
                {
                    tmp_spinup.mat[i, j]   = carrier_charge_density.Spin_Up.mat[i, j];
                    tmp_spindown.mat[i, j] = carrier_charge_density.Spin_Down.mat[i, j];
                }
            }

            SpinResolved_Data new_density = new SpinResolved_Data(tmp_spinup, tmp_spindown);

            // finally, get the charge density and send it to this new array
            Get_ChargeDensity(layers, ref new_density, chem_pot);

            return(new_density + dopent_charge_density);
        }
예제 #19
0
        public SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_density_deriv, SpinResolved_Data dopent_density_deriv, Band_Data chem_pot)
        {
            SpinResolved_Data electron_density_deriv = carrier_density_deriv.DeepenThisCopy();
            SpinResolved_Data hole_density_deriv     = carrier_density_deriv.DeepenThisCopy();

            // remove the electron density from the hole density SpinResolved_Data and vice versa
            for (int i = 0; i < electron_density_deriv.Spin_Summed_Data.Length; i++)
            {
                if (electron_density_deriv.Spin_Summed_Data.vec[i] > 0.0)
                {
                    electron_density_deriv.Spin_Up[i]   = 0.0;
                    electron_density_deriv.Spin_Down[i] = 0.0;
                }
                if (hole_density_deriv.Spin_Summed_Data.vec[i] < 0.0)
                {
                    hole_density_deriv.Spin_Up[i]   = 0.0;
                    hole_density_deriv.Spin_Down[i] = 0.0;
                }
            }

            return(electron_dens_calc.Get_ChargeDensity_Deriv(layers, electron_density_deriv, dopent_density_deriv, chem_pot) + hole_dens_calc.Get_ChargeDensity_Deriv(layers, hole_density_deriv, dopent_density_deriv, chem_pot));
        }
예제 #20
0
        public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data carrier_density, ref SpinResolved_Data dopent_density, Band_Data chem_pot)
        {
            Band_Data car_dens_spin_summed = carrier_density.Spin_Summed_Data;
            Band_Data dop_dens_spin_summed = dopent_density.Spin_Summed_Data;

            for (int i = 0; i < nz; i++)
            {
                double z = dz * i + zmin;

                double local_dopent_density;
                double local_carrier_density = car_dens_spin_summed.vec[i];

                // get the relevant layer and if it's frozen out, don't recalculate the charge
                ILayer current_Layer = Solver_Bases.Geometry.Geom_Tool.GetLayer(layers, z);

                // calculate the density at the given point
                ZeroD_Density charge_calc = new ZeroD_Density(current_Layer, temperature);
                if (!current_Layer.Dopents_Frozen_Out(temperature))
                {
                    local_dopent_density  = charge_calc.Get_DopentDensity(chem_pot.vec[i]);
                    local_carrier_density = charge_calc.Get_CarrierDensity(chem_pot.vec[i]);
                }
                else
                {
                    // if the density is frozen out, on the first step, this will add the carrier density to the dopent density
                    // to give a total, frozen-out charge.  After that, the local carrier density is set to zero and so this value
                    // should not change
                    local_dopent_density  = dop_dens_spin_summed.vec[i];
                    local_carrier_density = charge_calc.Get_CarrierDensity(chem_pot.vec[i]);
                }

                // as there is no spin dependence in this problem yet, just divide the charge into spin-up and spin-down components equally
                dopent_density.Spin_Down.vec[i]  = 0.5 * local_dopent_density;
                dopent_density.Spin_Up.vec[i]    = 0.5 * local_dopent_density;
                carrier_density.Spin_Down.vec[i] = 0.5 * local_carrier_density;
                carrier_density.Spin_Up.vec[i]   = 0.5 * local_carrier_density;
            }
        }
예제 #21
0
        void Initialise_from_1D(Dictionary <string, object> input_dict)
        {
            // get data from dictionary
            SpinResolved_Data tmp_1d_density = (SpinResolved_Data)input_dict["Carrier_Density"];
            SpinResolved_Data tmp_1d_dopdens = (SpinResolved_Data)input_dict["Dopent_Density"];
            Band_Data         tmp_pot_1d     = (Band_Data)input_dict["Chemical_Potential"];

            // calculate where the bottom of the 3D data is
            int offset_min = (int)Math.Round((zmin_dens - zmin_pot) / dz_pot);

            // this is the charge density modulation in the (x, y) plane so, initially, just put it in uniformly
            for (int k = 0; k < nz_dens; k++)
            {
                for (int i = 0; i < nx_dens; i++)
                {
                    for (int j = 0; j < ny_dens; j++)
                    {
                        chem_pot.vol[k][i, j] = tmp_pot_1d.vec[offset_min + j];

                        // do not add anything to the density at the top or bottom of the domain
                        if (k == 0 || k == nz_dens - 1)
                        {
                            continue;
                        }

                        // carrier data
                        carrier_charge_density.Spin_Up.vol[k][i, j]   = tmp_1d_density.Spin_Up.vec[k + offset_min];
                        carrier_charge_density.Spin_Down.vol[k][i, j] = tmp_1d_density.Spin_Down.vec[k + offset_min];

                        // dopent data
                        dopent_charge_density.Spin_Up.vol[k][i, j]   = tmp_1d_dopdens.Spin_Up.vec[k + offset_min];
                        dopent_charge_density.Spin_Down.vol[k][i, j] = tmp_1d_dopdens.Spin_Down.vec[k + offset_min];
                    }
                }
            }

            boundary_conditions.Add("surface", (double)input_dict["surface_charge"]);
        }
예제 #22
0
        public override SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_density_deriv, SpinResolved_Data dopent_density_deriv, Band_Data chem_pot)
        {
            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    // leave the edges zeroed
                    if (i == 0 || i == nx - 1 || j == 0 || j == ny - 1)
                    {
                        continue;
                    }

                    double x = dx * i + xmin;
                    double y = dy * j + ymin;

                    // get the relevant layer and if it's frozen out, don't recalculate the dopent charge
                    ILayer current_Layer = Solver_Bases.Geometry.Geom_Tool.GetLayer(layers, plane, x, y, pos_z);

                    ZeroD_Density charge_calc = new ZeroD_Density(current_Layer, temperature);
                    if (!current_Layer.Dopents_Frozen_Out(temperature))
                    {
                        double local_dopent_density_deriv = charge_calc.Get_DopentDensityDeriv(chem_pot.mat[i, j]);
                        dopent_density_deriv.Spin_Up.mat[i, j]   = 0.5 * local_dopent_density_deriv;
                        dopent_density_deriv.Spin_Down.mat[i, j] = 0.5 * local_dopent_density_deriv;
                    }
                    else
                    {
                        dopent_density_deriv.Spin_Up.mat[i, j]   = 0.0;
                        dopent_density_deriv.Spin_Down.mat[i, j] = 0.0;
                    }

                    carrier_density_deriv.Spin_Up.mat[i, j]   = 0.5 * charge_calc.Get_CarrierDensityDeriv(chem_pot.mat[i, j]);
                    carrier_density_deriv.Spin_Down.mat[i, j] = 0.5 * charge_calc.Get_CarrierDensityDeriv(chem_pot.mat[i, j]);
                }
            }

            return(carrier_density_deriv + dopent_density_deriv);
        }
예제 #23
0
        public override SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_density_deriv, SpinResolved_Data dopent_density_deriv, Band_Data chem_pot)
        {
            for (int i = 0; i < nx; i++)
            {
                for (int j = 0; j < ny; j++)
                {
                    for (int k = 0; k < nz; k++)
                    {
                        double x = dx * i + xmin;
                        double y = dy * j + ymin;
                        double z = dz * k + zmin;

                        // get the relevant layer and if it's frozen out, don't recalculate the dopent charge
                        ILayer current_Layer = Solver_Bases.Geometry.Geom_Tool.GetLayer(layers, x, y, z);

                        ZeroD_Density charge_calc = new ZeroD_Density(current_Layer, temperature);
                        if (!current_Layer.Dopents_Frozen_Out(temperature))
                        {
                            double local_dopent_density_deriv = charge_calc.Get_DopentDensityDeriv(chem_pot.vol[k][i, j]);
                            dopent_density_deriv.Spin_Up.vol[k][i, j]   = 0.5 * local_dopent_density_deriv;
                            dopent_density_deriv.Spin_Down.vol[k][i, j] = 0.5 * local_dopent_density_deriv;
                        }
                        else
                        {
                            dopent_density_deriv.Spin_Up.vol[k][i, j]   = 0.0;
                            dopent_density_deriv.Spin_Down.vol[k][i, j] = 0.0;
                        }

                        carrier_density_deriv.Spin_Up.vol[k][i, j]   = 0.5 * charge_calc.Get_CarrierDensityDeriv(chem_pot.vol[k][i, j]);
                        carrier_density_deriv.Spin_Down.vol[k][i, j] = 0.5 * charge_calc.Get_CarrierDensityDeriv(chem_pot.vol[k][i, j]);
                    }
                }
            }

            return(carrier_density_deriv + dopent_density_deriv);
        }
예제 #24
0
        public SpinResolved_Data Get_ChargeDensity(ILayer[] layers, SpinResolved_Data carrier_charge_density, SpinResolved_Data dopent_charge_density, Band_Data chem_pot)
        {
            SpinResolved_Data electron_density = carrier_charge_density.DeepenThisCopy();
            SpinResolved_Data hole_density     = carrier_charge_density.DeepenThisCopy();

            // remove the electron density from the hole density SpinResolved_Data and vice versa
            for (int i = 0; i < electron_density.Spin_Summed_Data.Length; i++)
            {
                if (electron_density.Spin_Summed_Data.vec[i] > 0.0)
                {
                    electron_density.Spin_Up[i]   = 0.0;
                    electron_density.Spin_Down[i] = 0.0;
                }
                if (hole_density.Spin_Summed_Data.vec[i] < 0.0)
                {
                    hole_density.Spin_Up[i]   = 0.0;
                    hole_density.Spin_Down[i] = 0.0;
                }
            }

            // must remove one lot of dopents due to double counting
            return(electron_dens_calc.Get_ChargeDensity(layers, electron_density, dopent_charge_density, chem_pot) + hole_dens_calc.Get_ChargeDensity(layers, hole_density, dopent_charge_density, chem_pot)
                   - dopent_charge_density);
        }
예제 #25
0
        public override SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_density_deriv, SpinResolved_Data dopent_density_deriv, Band_Data chem_pot)
        {
            // artificially deepen the copies of spin up and spin down
            Band_Data tmp_spinup   = new Band_Data(carrier_density_deriv.Spin_Up.vol[0].Rows, carrier_density_deriv.Spin_Up.vol[0].Cols, carrier_density_deriv.Spin_Up.vol.Length, 0.0);
            Band_Data tmp_spindown = new Band_Data(carrier_density_deriv.Spin_Down.vol[0].Rows, carrier_density_deriv.Spin_Down.vol[0].Cols, carrier_density_deriv.Spin_Down.vol.Length, 0.0);

            for (int k = 0; k < carrier_density_deriv.Spin_Up.vol.Length; k++)
            {
                // fill with data
                for (int i = 0; i < carrier_density_deriv.Spin_Up.vol[0].Rows; i++)
                {
                    for (int j = 0; j < carrier_density_deriv.Spin_Up.vol[0].Cols; j++)
                    {
                        tmp_spinup.vol[k][i, j]   = carrier_density_deriv.Spin_Up.vol[k][i, j];
                        tmp_spindown.vol[k][i, j] = carrier_density_deriv.Spin_Down.vol[k][i, j];
                    }
                }
            }

            SpinResolved_Data new_density = new SpinResolved_Data(tmp_spinup, tmp_spindown);

            // finally, get the charge density and send it to this new array
            Get_ChargeDensity_Deriv(layers, ref new_density, chem_pot);

            return(new_density + dopent_density_deriv);
        }
예제 #26
0
 public abstract void Get_ChargeDensity_Deriv(ILayer[] layers, ref SpinResolved_Data density, Band_Data chem_pot);
예제 #27
0
 /// <summary>
 /// sets the edges to be the same as their nearest neighbour.
 /// traditionally, would expect the edges to have zero charge but this will be different for simulations in the plane of the 2deg
 /// </summary>
 /// <param name="carrier_density"></param>
 void Set_Edges(SpinResolved_Data carrier_density)
 {
     Set_Edges(carrier_density.Spin_Up);
     Set_Edges(carrier_density.Spin_Down);
 }
예제 #28
0
        protected override bool Run_Iteration_Routine(IDensity_Solve dens_solv, IPoisson_Solve pois_solv, double tol, int max_iterations)
        {
            dens_solv.Reset_DFT_Potential();
            dens_solv.Update_DFT_Potential(carrier_charge_density);

            int  count     = 0;
            bool converged = false;

            if (!no_dft)
            {
                dens_solv.DFT_Mixing_Parameter = 0.1;
            }
            dens_diff_lim = 0.12;


            while (!converged)
            {
                Stopwatch stpwch = new Stopwatch();
                stpwch.Start();

                // save old density data
                Band_Data dens_old = carrier_charge_density.Spin_Summed_Data.DeepenThisCopy();

                // Get charge rho(phi) (not dopents as these are included as a flexPDE input)
                dens_solv.Get_ChargeDensity(layers, ref carrier_charge_density, ref dopent_charge_density, chem_pot);
                Set_Edges(carrier_charge_density);

                // Generate an approximate charge-dependent part of the Jacobian, g'(phi) = - d(eps * d( )) - rho'(phi) using the Thomas-Fermi semi-classical method
                SpinResolved_Data rho_prime = dens_solv.Get_ChargeDensity_Deriv(layers, carrier_charge_density_deriv, dopent_charge_density_deriv, chem_pot);
                Set_Edges(rho_prime);

                // Solve stepping equation to find raw Newton iteration step, g'(phi) x = - g(phi)
                gphi = -1.0 * chem_pot.Laplacian / Physics_Base.q_e - carrier_charge_density.Spin_Summed_Data - dopent_charge_density.Spin_Summed_Data;
                Set_Edges(gphi);
                x = pois_solv.Calculate_Newton_Step(rho_prime, gphi, carrier_charge_density, dens_solv.DFT_Potential, dens_solv.Get_XC_Potential(carrier_charge_density));
                // chem_pot = pois_solv.Chemical_Potential;

                // Calculate optimal damping parameter, t, (but damped damping....)
                if (t == 0.0)
                {
                    t = t_min;
                }

                t = t_damp * Calculate_optimal_t(t / t_damp, chem_pot / Physics_Base.q_e, x, carrier_charge_density, dopent_charge_density, pois_solv, dens_solv, t_min);
                if (t < 0.0)
                {
                    Console.WriteLine("Iterator has stalled, setting t = 0");
                    t = 0.0;
                }

                // and check convergence of density
                Band_Data dens_diff            = carrier_charge_density.Spin_Summed_Data - dens_old;
                Band_Data car_dens_spin_summed = carrier_charge_density.Spin_Summed_Data;
                double    carrier_dens_abs_max = Math.Max(Math.Abs(car_dens_spin_summed.Min()), Math.Abs(car_dens_spin_summed.Max()));
                // using the relative absolute density difference
                for (int i = 0; i < dens_diff.Length; i++)
                {
                    // only calculate density difference for densities more than 1% of the maximum value
                    if (Math.Abs(car_dens_spin_summed[i]) > 0.01 * carrier_dens_abs_max)
                    {
                        dens_diff[i] = Math.Abs(dens_diff[i] / car_dens_spin_summed[i]);
                    }
                    else
                    {
                        dens_diff[i] = 0.0;
                    }
                }

                // only renew DFT potential when the difference in density has converged and the iterator has done at least 3 iterations
                if (dens_diff.Max() < dens_diff_lim && t > 10.0 * t_min && count > 3)
                {
                    // and set the DFT potential
                    if (dens_solv.DFT_Mixing_Parameter != 0.0)
                    {
                        dens_solv.Print_DFT_diff(carrier_charge_density);
                    }
                    dens_solv.Update_DFT_Potential(carrier_charge_density);

                    // also... if the difference in the old and new dft potentials is greater than for the previous V_xc update, reduce the dft mixing parameter
                    double current_vxc_diff = Math.Max(dens_solv.DFT_diff(carrier_charge_density).Max(), (-1.0 * dens_solv.DFT_diff(carrier_charge_density).Min()));
                    if (current_vxc_diff > max_vxc_diff && dens_diff_lim / 2.0 > min_dens_diff || no_dft)
                    {
                        dens_diff_lim /= 2.0;
                        Console.WriteLine("Minimum percentage density difference reduced to " + dens_diff_lim.ToString());
                    }
                    max_vxc_diff = current_vxc_diff;

                    // solution is converged if the density accuracy is better than half the minimum possible value for changing the dft potential
                    if (dens_diff.Max() < min_dens_diff / 2.0 && current_vxc_diff < min_vxc_diff && Physics_Base.q_e * x.InfinityNorm() < tol && t != t_min)
                    {
                        converged = true;
                    }
                }

                // update t for Poisson solver
                pois_solv.T = t;
                chem_pot    = chem_pot + t * Physics_Base.q_e * x;

                base.Checkpoint();

                if (count == 0)
                {
                    pot_init = Physics_Base.q_e * x.InfinityNorm();
                }

                stpwch.Stop();
                Console.WriteLine("Iter = " + count.ToString() + "\tDens = " + dens_diff.Max().ToString("F4") + "\tPot = " + (Physics_Base.q_e * x.InfinityNorm()).ToString("F6") + "\tt = " + t.ToString("F5") + "\ttime = " + stpwch.Elapsed.TotalMinutes.ToString("F"));
                count++;

                //    File.Copy("split_gate.pg6", "split_gate_" + count.ToString("000") + ".pg6");

                // reset the potential if the added potential t * x is too small
                if (converged || count > max_iterations)
                {
                    Console.WriteLine("Maximum potential change at end of iteration was " + (t * Physics_Base.q_e * x.InfinityNorm()).ToString());
                    break;
                }
            }

            Console.WriteLine("Iteration complete");
            return(converged);
        }
예제 #29
0
 public Band_Data Get_XC_Potential_Deriv(SpinResolved_Data charge_density)
 {
     throw new NotImplementedException();
 }
예제 #30
0
 public Band_Data DFT_diff(SpinResolved_Data car_dens)
 {
     throw new NotImplementedException();
 }