示例#1
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 < nz; i++)
            {
                double z = dz * i + 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, 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.vec[i]);
                    dopent_density_deriv.Spin_Up.vec[i] = 0.5 * local_dopent_density_deriv;
                    dopent_density_deriv.Spin_Down.vec[i] = 0.5 * local_dopent_density_deriv;
                }
                else
                {
                    dopent_density_deriv.Spin_Up.vec[i] = 0.0;
                    dopent_density_deriv.Spin_Down.vec[i] = 0.0;
                }

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

            return carrier_density_deriv + dopent_density_deriv;
        }
示例#2
0
        public Band_Data Get_XC_Potential(SpinResolved_Data charge_density)
        {
            Band_Data result;
            Band_Data charge_dens_spin_summed = charge_density.Spin_Summed_Data;
            int       dim = charge_dens_spin_summed.Dimension;

            if (dim == 1)
            {
                int nx = charge_dens_spin_summed.vec.Length;
                result = new Band_Data(nx, 0.0);
                for (int i = 0; i < nx; i++)
                {
                    result.vec[i] = Get_XC_Potential(charge_dens_spin_summed.vec[i]);
                }

                return(result);
            }
            else if (dim == 2)
            {
                int nx = charge_dens_spin_summed.mat.Rows;
                int ny = charge_dens_spin_summed.mat.Cols;
                result = new Band_Data(nx, ny, 0.0);
                for (int i = 0; i < nx; i++)
                {
                    for (int j = 0; j < ny; j++)
                    {
                        result.mat[i, j] = Get_XC_Potential(charge_dens_spin_summed.mat[i, j]);
                    }
                }

                return(result);
            }
            else if (dim == 3)
            {
                int nx = charge_dens_spin_summed.vol[0].Rows;
                int ny = charge_dens_spin_summed.vol[0].Cols;
                int nz = charge_dens_spin_summed.vol.Length;
                result = new Band_Data(nx, ny, nz, 0.0);
                for (int k = 0; k < nz; k++)
                {
                    for (int i = 0; i < nx; i++)
                    {
                        for (int j = 0; j < ny; j++)
                        {
                            result.vol[k][i, j] = Get_XC_Potential(charge_dens_spin_summed.vol[k][i, j]);
                        }
                    }
                }

                return(result);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
示例#3
0
 public Band_Data DFT_diff(SpinResolved_Data car_dens)
 {
     if (alpha_dft == 0.0)
     {
         return(0.0 * dft_pot);
     }
     else
     {
         return(dft_pot - Get_XC_Potential(car_dens));
     }
 }
示例#4
0
        void Print_VP(Band_Data band_energy, Band_Data x, SpinResolved_Data car_dens, SpinResolved_Data dop_dens, IPoisson_Solve pois_solv, IDensity_Solve dens_solv)
        {
            StreamWriter sw        = new StreamWriter("vp");
            int          count_max = 100;
            double       dt        = 0.01;

            for (int i = 0; i < count_max; i++)
            {
                sw.WriteLine(calc_vp(i * dt, band_energy, x, car_dens, dop_dens, pois_solv, dens_solv).ToString());
            }

            sw.Close();
        }
示例#5
0
 public void Update_DFT_Potential(SpinResolved_Data car_dens)
 {
     if (this.dft_pot == null && alpha_dft != 0.0)
     {
         this.dft_pot = Get_XC_Potential(car_dens);
     }
     else if (alpha_dft == 0.0)
     {
         this.dft_pot = 0.0 * car_dens.Spin_Summed_Data.DeepenThisCopy();
     }
     else
     {
         this.dft_pot = (1.0 - alpha_dft) * dft_pot + alpha_dft * Get_XC_Potential(car_dens);
     }
 }
示例#6
0
        protected virtual double calc_vp(double t, Band_Data phi, Band_Data x, SpinResolved_Data car_dens, SpinResolved_Data dop_dens, IPoisson_Solve pois_solv, IDensity_Solve dens_solv)
        {
            double vp;

            SpinResolved_Data tmp_dens = dens_solv.Get_ChargeDensity(layers, car_dens, dop_dens, Physics_Base.q_e * (phi + t * x));
            Band_Data         V_Prime  = -1.0 * (phi.Laplacian + t * x.Laplacian) - tmp_dens.Spin_Summed_Data;

            vp = 0.0;
            for (int i = 0; i < x.Length; i++)
            {
                vp += V_Prime[i] * x[i];
            }

            // multiply by volume element (this works in all dimensions as default dx, dy, dz are 1.0)
            return(vp * dx_dens * dy_dens * dz_dens);
        }
示例#7
0
        public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data density, Band_Data chem_pot)
        {
            // send data to client
            NetworkComms.SendObject("layers", clientIP, clientPort, layers);
            NetworkComms.SendObject("density", clientIP, clientPort, density);
            NetworkComms.SendObject("chem_pot", clientIP, clientPort, chem_pot);

            // Call the save_density routine
            //NetworkComms.AppendGlobalIncomingPacketHandler<SpinResolved_Data>("new_density", Save_Density);

            //Start listening for incoming connections
            TCPConnection.StartListening(true);

            //Print out the IPs and ports we are now listening on
            Console.WriteLine("Server listening for TCP connection on:");
            foreach (System.Net.IPEndPoint localEndPoint in TCPConnection.ExistingLocalListenEndPoints()) Console.WriteLine("{0}:{1}", localEndPoint.Address, localEndPoint.Port);

            throw new NotImplementedException();
        }
示例#8
0
        public void Output(SpinResolved_Data data, string filename, bool with_warnings)
        {
            StreamWriter sw = new StreamWriter(filename);

            if (with_warnings)
            {
                sw.WriteLine("Warning - The data has been written out serially and there is no information as to which order the dimensions come in.");
                sw.WriteLine("Warning - Ordering compared to Band_Data objects is not guaranteed!");
            }

            // output the charge density
            Band_Data tot_charge = data.Spin_Summed_Data;

            for (int i = 0; i < tot_charge.Length; i++)
            {
                sw.WriteLine(tot_charge[i].ToString());
            }

            sw.Close();
        }
示例#9
0
        public Band_Data Get_XC_Potential_Deriv(SpinResolved_Data charge_density)
        {
            Band_Data result;
            Band_Data charge_dens_spin_summed = charge_density.Spin_Summed_Data;
            int       dim = charge_dens_spin_summed.Dimension;

            if (dim == 1)
            {
                int nx = charge_dens_spin_summed.vec.Length;
                result = new Band_Data(new DoubleVector(nx));
                for (int i = 0; i < nx; i++)
                {
                    result.vec[i] = Get_XC_Potential_Deriv(charge_dens_spin_summed.vec[i]);
                }

                return(result);
            }
            else if (dim == 2)
            {
                int nx = charge_dens_spin_summed.mat.Rows;
                int ny = charge_dens_spin_summed.mat.Cols;
                result = new Band_Data(new DoubleMatrix(nx, ny));
                for (int i = 0; i < nx; i++)
                {
                    for (int j = 0; j < ny; j++)
                    {
                        result.mat[i, j] = Get_XC_Potential_Deriv(charge_dens_spin_summed.mat[i, j]);
                    }
                }

                return(result);
            }
            else if (dim == 3)
            {
                throw new NotImplementedException();
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        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);

            double[,] xy_energy = Solve_Eigenvector_Problem(dft_pot, ref charge_density);
            double beta = 1.0 / (Physics_Base.kB * temperature);

            // multiply the z-densities by the xy-density
            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                    for (int k = 0; k < nz; k++)
                    {
                        charge_density.Spin_Up.vol[k][i, j] *= g_2d * Math.Log(1.0 + Math.Exp(-1.0 * beta * xy_energy[i, j])) / beta;
                        charge_density.Spin_Down.vol[k][i, j] *= g_2d * Math.Log(1.0 + Math.Exp(-1.0 * beta * xy_energy[i, j])) / beta;
                    }

            // and multiply the density by -e to get the charge density (as these are electrons)
            charge_density = unit_charge * charge_density;
        }
        public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data density, 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
                        ILayer current_Layer = Solver_Bases.Geometry.Geom_Tool.GetLayer(layers, x, y, z);

                        // calculate the density at the given point
                        ZeroD_Density charge_calc = new ZeroD_Density(current_Layer, temperature);
                        double local_charge_density = charge_calc.Get_CarrierDensity(chem_pot.vol[k][i, j]);

                        // as there is no spin dependence in this problem yet, just divide the charge into spin-up and spin-down components equally
                        density.Spin_Down.vol[k][i, j] = 0.5 * local_charge_density;
                        density.Spin_Up.vol[k][i, j] = 0.5 * local_charge_density;
                    }
        }
示例#12
0
        public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data density, Band_Data chem_pot)
        {
            // send data to client
            NetworkComms.SendObject("layers", clientIP, clientPort, layers);
            NetworkComms.SendObject("density", clientIP, clientPort, density);
            NetworkComms.SendObject("chem_pot", clientIP, clientPort, chem_pot);

            // Call the save_density routine
            //NetworkComms.AppendGlobalIncomingPacketHandler<SpinResolved_Data>("new_density", Save_Density);

            //Start listening for incoming connections
            TCPConnection.StartListening(true);

            //Print out the IPs and ports we are now listening on
            Console.WriteLine("Server listening for TCP connection on:");
            foreach (System.Net.IPEndPoint localEndPoint in TCPConnection.ExistingLocalListenEndPoints())
            {
                Console.WriteLine("{0}:{1}", localEndPoint.Address, localEndPoint.Port);
            }

            throw new NotImplementedException();
        }
        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;
            }
        }
        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;
        }
        public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data density, Band_Data chem_pot)
        {
            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;

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

                    // get the relevant layer
                    ILayer current_Layer = Solver_Bases.Geometry.Geom_Tool.GetLayer(layers, plane, x, y, pos_z);

                    // calculate the density at the given point
                    ZeroD_Density charge_calc = new ZeroD_Density(current_Layer, temperature);
                    double local_charge_density = charge_calc.Get_CarrierDensity(chem_pot.mat[i, j]);

                    // as there is no spin dependence in this problem yet, just divide the charge into spin-up and spin-down components equally
                    density.Spin_Down.mat[i, j] = 0.5 * local_charge_density;
                    density.Spin_Up.mat[i, j] = 0.5 * local_charge_density;
                }
        }
示例#16
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"];
        }
示例#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 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();
        }
示例#18
0
        public override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data g_phi)
        {
            DoubleTriDiagMatrix lap_mat = -1.0 * Generate_Laplacian(exp.Layers);
            Band_Data rho_prime_spin_summed = rho_prime.Spin_Summed_Data;

            // check that lap_mat and rho_prime have the same dimension
            if (rho_prime_spin_summed.Length != lap_mat.Rows)
                throw new Exception("Error - the Laplacian generated by pois_solv has a different order to rho_prime!");

            for (int i = 0; i < rho_prime_spin_summed.Length; i++)
                lap_mat[i, i] -= rho_prime_spin_summed.vec[i];

            DoubleTriDiagFact lu_newt_step = new DoubleTriDiagFact(lap_mat);

            // calculate newton step and its laplacian
            Band_Data result = new Band_Data(lu_newt_step.Solve(-1.0 * g_phi.vec));
            result.Laplacian = Calculate_Phi_Laplacian(result);

            return result;
        }
示例#19
0
        public override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi)
        {
            Save_Data(gphi, gphi_filename);
            Save_Data(rho_prime.Spin_Summed_Data, densderiv_filename);
            Create_NewtonStep_File(top_length, split_width, split_length, flexpde_script, T);

            return Get_Data_From_External(newton_location, flexpde_options, newton_result_filename);
        }
示例#20
0
 public void Update_DFT_Potential(SpinResolved_Data car_dens)
 {
     // set the dft potential for the electrons and holes separately
     // NOTE!!!!!  V_xc is set using the total carrier density so its value includes the density due to electrons
     // this is a bug, but shouldn't be a problem as there should be no chance of getting holes where there are electrons and vice versa
     electron_dens_calc.Update_DFT_Potential(car_dens);
     hole_dens_calc.Update_DFT_Potential(car_dens);
 }
示例#21
0
 public void Output(SpinResolved_Data data, string filename)
 {
     throw new NotImplementedException();
 }
示例#22
0
        /// <summary>
        /// calculates an optimal t based on bisection
        /// </summary>
        /// <param name="t"></param>
        /// <param name="phi"></param>
        /// <param name="x"></param>
        /// <param name="car_dens"></param>
        /// <param name="dop_dens"></param>
        /// <param name="pois_solv"></param>
        /// <param name="dens_solv"></param>
        /// <returns></returns>
        protected double Calculate_optimal_t(double t, Band_Data phi, Band_Data x, SpinResolved_Data car_dens, SpinResolved_Data dop_dens, IPoisson_Solve pois_solv, IDensity_Solve dens_solv, double minval)
        {
            double            maxval        = 3.0;
            SpinResolved_Data car_dens_copy = car_dens.DeepenThisCopy();
            SpinResolved_Data dop_dens_copy = dop_dens.DeepenThisCopy();

            double vpa    = calc_vp(t, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv);
            double vpb    = calc_vp(div_fact * t, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv);
            double t_orig = t;

            // work out whether this is going in the right direction (assuming vp is monotonic)
            if (Math.Abs(vpb) < Math.Abs(vpa))
            {
                // if 0.5 * t was going downhill, first, halve t seeing as you've already done this step
                t = div_fact * t;
                // then halve the damping parameter and check whether you've found a root yet
                while (Math.Sign(vpb) == Math.Sign(vpa))
                {
                    t = div_fact * t;
                    if (t < minval)
                    {
                        if (Math.Sign(calc_vp(1.0, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv)) == Math.Sign(vpb))
                        {
                            return(0.5);
                        }
                        //return 1.0 / div_fact;
                        else
                        {
                            return(Calculate_optimal_t(1.0, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv, minval));
                        }
                    }


                    vpa = vpb;
                    vpb = calc_vp(t, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv);
                }

                //return 0.5 * (1.0 + (1.0 / div_fact)) * t;
                return(t - t * (1.0 - 1.0 / div_fact) * vpb / (vpa - vpb));
            }
            else
            {
                // if 0.5 * t was going uphill, then we need to be doubling t and looking for the root
                while (Math.Sign(vpb) == Math.Sign(vpa))
                {
                    t = (1.0 / div_fact) * t;
                    if (t > maxval)
                    {
                        return(maxval);
                    }

                    vpa = vpb;
                    vpb = calc_vp(t, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv);
                }

                //return 0.5 * (1.0 + div_fact) * t;
                return(t - t * (1.0 - div_fact) * vpb / (vpb - vpa));
            }
        }
        /// <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;
        }
        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);
            double[,] xy_energy = new double[nx, ny];

            xy_energy = 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_xy = new double[nx, ny];
            // and generate a density for the y-direction
            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                    for (int k = 0; k < max_wavefunction; k++)
                        dens_xy[i, j] += DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * Get_Fermi_Function(energies[k]);
            */

            IExperiment exp_green;
            exp_green = new Iterative_Greens_Function_Test.Experiment();
            Iterative_Greens_Function_Test.Iterative_Greens_Function iter = new Iterative_Greens_Function_Test.Iterative_Greens_Function(exp_green, xy_energy);
            double[,] dens_xy = new double[nx, ny];
            double max_energy = Physics_Base.kB * temperature * no_kb_T;
            DoubleMatrix xy_energy_mat = new DoubleMatrix(xy_energy);
            double min_energy = xy_energy_mat.Min();
            double dE = 0.1;
            //double min_energy = -1.0 * max_energy;
            int n_slices = (int)((max_energy - min_energy) / dE);

            for (int n = 1; n < n_slices-1; n++)
            {
                double energy = min_energy + n * dE;
                double[,] dens_per_E = iter.GetDoS(energy);
                double fermi_func = Get_Fermi_Function(energy);

                for (int i = 0; i < nx; i++)
                    for (int j = 0; j < ny; j++)
                    {
                        dens_xy[i, j] += dens_per_E[i,j] * fermi_func;
                    }
            }

            //double fermi_fact_max = Math.Exp(max_energy / (Physics_Base.kB * temperature)) + 1;
            //double fermi_fact_min = 2.0;
            double[,] dens_per_E_max = iter.GetDoS(max_energy);
            double[,] dens_per_E_min = iter.GetDoS(min_energy);
            double fermi_func_max = Get_Fermi_Function(max_energy);
            double fermi_func_min = Get_Fermi_Function(min_energy);

            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                {
                    dens_xy[i, j] += 0.5*(dens_per_E_max[i, j] * fermi_func_max + dens_per_E_min[i,j] * fermi_func_min);
                }

            // multiply the z-densities by the xy-density
            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                    for (int k = 0; k < nz; k++)
                    {
                        charge_density.Spin_Up.vol[k][i, j] *= dens_xy[i, j];
                        charge_density.Spin_Down.vol[k][i, j] *= dens_xy[i, j];
                    }

            // and multiply the density by -e to get the charge density (as these are electrons)
            charge_density = unit_charge * charge_density;
        }
示例#25
0
 public abstract SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_charge_density, SpinResolved_Data dopent_charge_density, Band_Data chem_pot);
示例#26
0
 public void Print_DFT_diff(SpinResolved_Data car_dens)
 {
     Console.WriteLine("Maximum absolute difference in DFT potentials = " + DFT_diff(car_dens).InfinityNorm().ToString("F6"));
 }
示例#27
0
 public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot)
 {
     throw new NotImplementedException();
 }
示例#28
0
        public override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi)
        {
            Save_Data(rho_prime.Spin_Summed_Data, densderiv_filename);
            Save_Data(gphi, gphi_filename);

            Band_Data x = Get_Data_From_External(newton_location, "-p " + newton_parameterfile, newton_result_filename);
            return x;
        }
示例#29
0
 public abstract void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot);
示例#30
0
 public abstract Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi, SpinResolved_Data carrier_density, Band_Data dft_pot, Band_Data dft_calc);
        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);

            double[,] xy_energy = Solve_Eigenvector_Problem(dft_pot, ref charge_density_deriv);
            double beta = 1.0 / (Physics_Base.kB * temperature);

            // multiply the z-densities by the xy-density
            for (int i = 0; i < nx; i++)
                for (int j = 0; j < ny; j++)
                    for (int k = 0; k < nz; k++)
                    {
                        charge_density_deriv.Spin_Up.vol[k][i, j] *= g_2d * Get_Fermi_Function(xy_energy[i, j]);
                        charge_density_deriv.Spin_Down.vol[k][i, j] *= g_2d * Get_Fermi_Function(xy_energy[i, j]);
                    }

            // 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;
        }
示例#32
0
 public Band_Data Get_XC_Potential_Deriv(SpinResolved_Data charge_density)
 {
     throw new NotImplementedException();
 }
示例#33
0
 /// <summary>
 /// for this method, it is assumed that the dopent density is frozen out (and therefore not altered) unless overriden
 /// </summary>
 public virtual void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data carrier_charge_density, ref SpinResolved_Data dopent_charge_density, Band_Data chem_pot)
 {
     Get_ChargeDensity(layers, ref carrier_charge_density, chem_pot);
 }
示例#34
0
 public void Print_DFT_diff(SpinResolved_Data car_dens)
 {
 }
示例#35
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;
            }
        }
示例#36
0
        public override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi, SpinResolved_Data car_dens, Band_Data dft_pot, Band_Data dft_calc)
        {
            Save_Data(car_dens.Spin_Summed_Data, dens_filename);
            Save_Data(dft_pot, xc_pot_filename);
            Save_Data(dft_calc, "xc_pot_calc.dat");

            return(Calculate_Newton_Step(rho_prime, gphi));
        }
示例#37
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;
        }
示例#38
0
 public override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi, SpinResolved_Data carrier_density, Band_Data dft_pot, Band_Data dft_calc)
 {
     throw new NotImplementedException();
 }
示例#39
0
 public Band_Data DFT_diff(SpinResolved_Data car_dens)
 {
     throw new NotImplementedException();
 }
示例#40
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;
        }
示例#41
0
        public void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot)
        {
            SpinResolved_Data electron_density = charge_density.DeepenThisCopy();
            SpinResolved_Data hole_density = 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;
                }
            }

            electron_dens_calc.Get_ChargeDensity(layers, ref electron_density, chem_pot);
            hole_dens_calc.Get_ChargeDensity(layers, ref hole_density, chem_pot);

            charge_density = electron_density + hole_density;
        }
示例#42
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;
        }
示例#43
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;
        }
示例#44
0
 public void Output(SpinResolved_Data data, string filename)
 {
     Output(data, filename, true);
 }
示例#45
0
 /// <summary>
 /// for this method, it is assumed that the dopent density is frozen out (and therefore not altered) unless overriden
 /// </summary>
 public void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data carrier_charge_density, ref SpinResolved_Data dopent_charge_density, Band_Data chem_pot)
 {
     Get_ChargeDensity(layers, ref carrier_charge_density, chem_pot);
 }
示例#46
0
        public override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi, SpinResolved_Data car_dens, Band_Data dft_pot, Band_Data dft_calc)
        {
            Save_Data(car_dens.Spin_Summed_Data, dens_filename);
            Save_Data(dft_pot, xc_pot_filename);
            Save_Data(dft_calc, "xc_pot_calc.dat");

            return Calculate_Newton_Step(rho_prime, gphi);
        }
示例#47
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);
        }
示例#48
0
 public abstract Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi);
示例#49
0
 public override SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_charge_density, SpinResolved_Data dopent_charge_density, Band_Data chem_pot)
 {
     throw new NotImplementedException();
 }