Example #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;
        }
Example #2
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();
        }
Example #3
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);
     }
 }
Example #4
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);
        }
Example #5
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();
        }
Example #6
0
        public static Band_Data Parse_Band_Data(string location, string[] input_data, int nz)
        {
            // and check that there is the right number of data points back
            if (input_data.Length != nz)
            {
                throw new Exception("Error - FlexPDE is outputting the wrong number of potential data points");
            }

            // and parse these values into a DoubleVector
            Band_Data result = new Band_Data(new DoubleVector(nz));

            for (int i = 0; i < nz; i++)
            {
                result.vec[i] = double.Parse(input_data[i]);
            }

            result.value_location = location;
            return(result);
        }
Example #7
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();
        }
Example #8
0
        public double Renew_Mixing_Parameter(Band_Data band_energy, Band_Data new_band_energy, double alpha_min, double alpha)
        {
            double[] energy_diff = Get_Array_of_Absolute_Differences(band_energy, new_band_energy);

            // the new mixing factor is the maximum absolute change, multiplied by the original mixing factor
            double new_mixing_parameter = alpha_min / energy_diff.Max();

            if (new_mixing_parameter > alpha_min && new_mixing_parameter < 0.01)
            {
                return(new_mixing_parameter);
            }
            else if (new_mixing_parameter > 0.01)
            {
                return(0.01);
            }
            else
            {
                return(alpha_min);
            }
        }
Example #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();
            }
        }
Example #10
0
        void Print_Data(Band_Data x, Band_Data v)
        {
            StreamWriter swx = new StreamWriter("x_prt.dat");
            StreamWriter swv = new StreamWriter("v_prt.dat");

            for (int i = 0; i < v.mat.Rows; i++)
            {
                for (int j = 0; j < v.mat.Cols; j++)
                {
                    swx.Write(x.mat[i, j].ToString() + '\t');
                    swv.Write(v.mat[i, j].ToString() + '\t');
                    if (j == v.mat.Cols - 1)
                    {
                        swv.WriteLine();
                        swx.WriteLine();
                    }
                }
            }

            swx.Close(); swv.Close();
        }
        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;
                    }
        }
Example #13
0
        public static Band_Data operator -(Band_Data vec1, Band_Data vec2)
        {
            Band_Data result;

            // return null if both of the inputs are null
            if (vec1 == null || vec2 == null)
            {
                return(null);
            }

            if (vec1.Dimension != vec2.Dimension)
            {
                throw new RankException();
            }

            if (vec1.Dimension == 1)
            {
                result = new Band_Data(vec1.vec - vec2.vec);
            }
            else if (vec1.Dimension == 2)
            {
                result = new Band_Data(vec1.mat - vec2.mat);
            }
            else if (vec1.Dimension == 3)
            {
                result = new Band_Data(new DoubleMatrix[vec1.vol.Length]);
                for (int i = 0; i < vec1.vol.Length; i++)
                {
                    result.vol[i] = vec1.vol[i] - vec2.vol[i];
                }
            }
            else
            {
                throw new NotImplementedException();
            }

            result.Laplacian = vec1.Laplacian - vec2.Laplacian;
            return(result);
        }
        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;
                }
        }
Example #17
0
        protected override Band_Data Get_Pot_From_External(Band_Data density)
        {
            Save_Data(density, dens_filename);

            pot = Get_Data_From_External(initcalc_location, "-p " + initcalc_parameterfile, initcalc_result_filename);
            return pot;
        }
Example #18
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;
        }
Example #19
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;
        }
Example #20
0
        /// <summary>
        /// returns the eigen-energies for the given potential and charge density
        /// </summary>
        public override DoubleVector Get_EnergyLevels(ILayer[] layers, Band_Data pot)
        {
            // convert the chemical potential into a quantum mechanical potential
            Band_Data band_pot = pot.DeepenThisCopy();
            Get_Potential(ref band_pot, layers);

            DoubleHermitianMatrix hamiltonian = Create_Hamiltonian(layers, band_pot);
            DoubleHermitianEigDecomp eig_decomp = new DoubleHermitianEigDecomp(hamiltonian);
            return eig_decomp.EigenValues;
        }
Example #21
0
        protected string Generate_Output_String(int count, Band_Data x, Band_Data dens_diff)
        {
            string output_string = "Iter = " + count.ToString() + "\tDens = " + dens_diff.Max().ToString("F4") + "\tPot = " + (Physics_Base.q_e * x.InfinityNorm()).ToString("F6") + "\tt = " + t.ToString("F6");

            return(output_string);
        }
Example #22
0
        public static Band_Data operator *(double scalar, Band_Data data)
        {
            Band_Data result;

            // return null if the inputs is null
            if (data == null)
                return null;

            if (data.Dimension == 1)
                result = new Band_Data(scalar * data.vec);
            else if (data.Dimension == 2)
                result = new Band_Data(scalar * data.mat);
            else if (data.Dimension == 3)
            {
                result = new Band_Data(new DoubleMatrix[data.vol.Length]);
                for (int i = 0; i < data.vol.Length; i++)
                    result.vol[i] = scalar * data.vol[i];
            }
            else
                throw new NotImplementedException();

            result.Laplacian = scalar * data.Laplacian;
            return result;
        }
Example #23
0
 protected abstract Band_Data Get_Pot_From_External(Band_Data density);
Example #24
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();
 }
Example #25
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();
        }
Example #26
0
 public override DoubleVector Get_EnergyLevels(ILayer[] layers, Band_Data chem_pot)
 {
     throw new NotImplementedException();
 }
 public SpinResolved_Data(Band_Data spin_up, Band_Data spin_down)
 {
     spin_data    = new Band_Data[2];
     spin_data[0] = spin_up; spin_data[1] = spin_down;
 }
 public SpinResolved_Data(int nx)
 {
     spin_data    = new Band_Data[2];
     spin_data[0] = new Band_Data(nx, 0.0); spin_data[1] = new Band_Data(nx, 0.0);
 }
Example #29
0
 protected override void Save_Data(Band_Data density, string input_file_name)
 {
     density.Save_Data(input_file_name);
 }
Example #30
0
 public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot)
 {
     throw new NotImplementedException();
 }
Example #31
0
 public abstract void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot);
Example #32
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));
        }
Example #33
0
 public abstract Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi);
Example #34
0
 protected override Band_Data Get_Pot_On_Regular_Grid(Band_Data density)
 {
     throw new NotImplementedException();
 }
Example #35
0
        public static Band_Data Parse_Band_Data(string location, string[] input_data, int ny, int nz)
        {
            // and check that there is the right number of data points back
            if (input_data.Length != ny * nz)
                throw new Exception("Error - FlexPDE is outputting the wrong number of potential data points");

            // and parse these values into a DoubleVector
            Band_Data result = new Band_Data(new DoubleMatrix(ny, nz));
            for (int i = 0; i < ny; i++)
            {
                for (int j = 0; j < nz; j++)
                    result.mat[i, j] = double.Parse(input_data[j * ny + i]);
            }

            result.value_location = location;
            return result;
        }
Example #36
0
 protected override void Save_Data(Band_Data density, string input_file_name)
 {
     density.Save_Data(input_file_name);
 }
Example #37
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;
        }
Example #38
0
 public void Reset_DFT_Potential()
 {
     this.dft_pot = null;
 }
Example #39
0
        DoubleHermitianMatrix Create_Hamiltonian(ILayer[] layers, Band_Data pot)
        {
            DoubleHermitianMatrix result = new DoubleHermitianMatrix(nx * ny);

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

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

            return result;
        }
Example #40
0
 /// <summary>
 /// Initiates a laplacian for this Band_Data class of the correct size
 /// </summary>
 public void Initiate_Laplacian()
 {
     this.laplacian_band_data = 0.0 * this;
 }
Example #41
0
 public abstract SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_charge_density, SpinResolved_Data dopent_charge_density, Band_Data chem_pot);
Example #42
0
        public Band_Data DeepenThisCopy()
        {
            Band_Data tmp_result = null;

            if (dim == 1)
            {
                DoubleVector result = new DoubleVector(Length);
                for (int i = 0; i < Length; i++)
                    result[i] = this[i];

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

                tmp_result = new Band_Data(result);
            }
            else if (dim == 3)
            {
                int nx = vol[0].Rows;
                int ny = vol[0].Cols;
                int nz = vol.Length;

                Band_Data 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] = this.vol[k][i, j];

                tmp_result = result;
            }
            else
                throw new NotImplementedException();

            if (this.Laplacian != null)
                tmp_result.Laplacian = this.Laplacian.DeepenThisCopy();

            return tmp_result;
        }
Example #43
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);
        }
Example #44
0
 public abstract DoubleVector Get_EnergyLevels(ILayer[] layers, Band_Data chem_pot);
Example #45
0
 protected override Band_Data Get_Pot_On_Regular_Grid(Band_Data density)
 {
     throw new NotImplementedException();
 }
Example #46
0
 //       protected override Band_Data Get_ChemPot_From_External(Band_Data density)
 //       {
 //           Save_Data(density, dens_filename);
 //
 //           return Get_Data_From_External(flexpde_script, initcalc_result_filename);
 //       }
 /// <summary>
 /// Calculates the Laplacian for the given band structure of the input potential
 /// ie. returns d(eps * d(input))
 /// NOTE: the input should be a potential so make sure you divide all band energies by q_e
 /// </summary>
 public Band_Data Calculate_Phi_Laplacian(Band_Data input)
 {
     DoubleTriDiagMatrix lap_mat = Generate_Laplacian(exp.Layers);
     return new Band_Data(MatrixFunctions.Product(lap_mat, input.vec));
 }
Example #47
0
        static void Main(string[] args)
        {
            // set nmath license key
            CenterSpace.NMath.Core.NMathConfiguration.LicenseKey = License.NMath_License_Key;

            Console.WriteLine("Program starting");

            Console.WriteLine("Loading input parameters from file");
            Dictionary<string, object> inputs = new Dictionary<string, object>();
            Inputs_to_Dictionary.Add_Input_Parameters_to_Dictionary(ref inputs, "Input_Parameters.txt");
            Inputs_to_Dictionary.Add_Input_Parameters_to_Dictionary(ref inputs, "Solver_Config.txt");
            Console.WriteLine("Input parameters loaded");

            // read in the value of vsg to be used
            Console.WriteLine("Enter split gate voltage");
            inputs["split_V"] = double.Parse(Console.ReadLine());
            Console.WriteLine("Setting \"split_V\" to " + ((double)inputs["split_V"]).ToString() + "V");

            // check to make sure it's negative
            if ((double)inputs["split_V"] > 0)
            {
                Console.WriteLine("\"split_V\" has been set positive at " + ((double)inputs["split_V"]).ToString() + "V.  Are you sure you want to do this?");
                Console.ReadKey();
            }

            // temporarily, just set the output suffix to something boring
            inputs.Add("output_suffix", ".dat");

            // initialise the band structure experiment
            Experiment exp = new Experiment();
            OneD_ThomasFermiPoisson.Experiment exp_init = new OneD_ThomasFermiPoisson.Experiment();

            Console.WriteLine("Performing density dopent calculation");
            Dictionary<string, object> inputs_init = new Dictionary<string, object>();
            inputs_init = inputs.Where(s => s.Key.ToLower().EndsWith("_1d")).ToDictionary(dict => dict.Key.Remove(dict.Key.Length - 3), dict => dict.Value);
            inputs_init.Add("BandStructure_File", inputs["BandStructure_File"]);
            inputs_init.Add("T", inputs["T"]);
            inputs_init.Add("output_suffix", "_1d.dat");

            exp_init.Initialise(inputs_init);
            exp_init.Run();
            inputs.Add("SpinResolved_Density", exp_init.Carrier_Density);
            inputs.Add("Dopent_Density", exp_init.Dopent_Density);
            inputs.Add("Chemical_Potential", exp_init.Chemical_Potential);
            inputs.Add("nz_pot_1d", inputs_init["nz"]);
            inputs.Add("zmin_pot_1d", inputs_init["zmin"]);
            inputs.Add("zmax_pot_1d", inputs_init["zmax"]);
            // get the frozen out surface charge at 70K
            if (!inputs.ContainsKey("surface_charge")) inputs.Add("surface_charge", exp_init.Surface_Charge(70.0));
            else Console.WriteLine("Surface charge set from Input_Parameters.txt to " + ((double)inputs["surface_charge"]).ToString());
            Console.WriteLine("Calculated 1D density for dopents");

            // this is a scaled version for the dopents!
            double y_scaling = ((double)inputs["nx"] * (double)inputs["dx"]) / ((double)inputs["ny"] * (double)inputs["dy"]);
            double z_scaling = ((double)inputs["nx"] * (double)inputs["dx"]) / ((double)inputs["nz"] * (double)inputs["dz"]);
            // extract the dopent layer (leaving the top and bottom set to zero)
            int dopent_min = -1;
            int dopent_max = -2;
            ILayer dopent_layer = exp_init.Layers[0];
            for (int i = 0; i < exp_init.Layers.Length; i++)
                if (exp_init.Layers[i].Donor_Conc != 0.0 || exp_init.Layers[i].Acceptor_Conc != 0)
                {
                    dopent_layer = exp_init.Layers[i];
                    dopent_min = (int)Math.Round((dopent_layer.Zmin - Geom_Tool.Get_Zmin(exp_init.Layers)) / (int)(double)inputs_init["dz"]);
                    dopent_max = (int)Math.Round((dopent_layer.Zmax - Geom_Tool.Get_Zmin(exp_init.Layers)) / (int)(double)inputs_init["dz"]);
                }
            Band_Data tmp_dop_dens_1D = new Band_Data(dopent_max - dopent_min, 0.0);
            for (int i = dopent_min + 1; i < dopent_max - 1; i++)
                tmp_dop_dens_1D.vec[i - dopent_min] = exp_init.Dopent_Density.Spin_Summed_Data.vec[i];
            // and expand into the correct data structure
            Band_Data tmp_dop_dens = Input_Band_Structure.Expand_BandStructure(tmp_dop_dens_1D.vec, (int)(double)inputs["nx_1d"], (int)(double)inputs["ny_1d"]);
            tmp_dop_dens.Save_3D_Data("dens_3D_dopents.dat", (double)inputs["dx"] * ((double)inputs["nx"] + 1.0) / ((double)inputs["nx_1d"] - 1.0), y_scaling * (double)inputs["dy"] * ((double)inputs["ny"] + 1.0) / ((double)inputs["ny_1d"] - 1.0),  z_scaling * (double)inputs["dz_1d"], -1.0 * (double)inputs["dx"] * ((double)inputs["nx"] + 1.0) / 2.0, -1.0 * y_scaling * (double)inputs["dy"] * ((double)inputs["ny"] + 1.0) / 2.0, z_scaling * dopent_layer.Zmin);
            Console.WriteLine("Saved 1D dopent density");

            Console.WriteLine("Starting experiment");
            exp.Initialise(inputs);
            Console.WriteLine("Experiment initialised");
            exp.Run();
            Console.WriteLine("Experiment complete");
        }
Example #48
0
        public double Get_Surface_Charge(Band_Data chem_pot, ILayer[] layers)
        {
            // calculate the electric field just below the surface
            int surface = (int)(-1.0 * Math.Floor(Geom_Tool.Get_Zmin(layers) / exp.Dz_Pot));
            double eps = Geom_Tool.Find_Layer_Below_Surface(layers).Permitivity;
            // by Gauss' theorem, rho = - epsilon_0 * epsilon_r * dV/dz
            double surface_charge = -1.0 * eps * (chem_pot[surface-1] - chem_pot[surface - 2]) / exp.Dz_Pot;
            // divide by - q_e to convert the chemical potential into a potential
            surface_charge /= -1.0 * Physics_Base.q_e;

            return surface_charge;
        }
Example #49
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);
Example #50
0
 protected override Band_Data Get_Pot_From_External(Band_Data density)
 {
     throw new NotImplementedException();
 }
Example #51
0
 protected abstract Band_Data Get_Pot_On_Regular_Grid(Band_Data density);
Example #52
0
        protected override Band_Data Get_Pot_On_Regular_Grid(Band_Data charge_density)
        {
            // set the top and bottom boundary conditions where [0] is the bottom of the device
            charge_density.vec[0] = bottom_bc * -1.0 * bottom_eps / (exp.Dz_Pot * exp.Dz_Pot);
            charge_density.vec[charge_density.Length - 1] = top_bc * -1.0 * top_eps / (exp.Dz_Pot * exp.Dz_Pot);

            // solve Poisson's equation
            Band_Data potential = new Band_Data(lu_fact.Solve(-1.0 * charge_density.vec));
            // and save its laplacian
            potential.Laplacian = Calculate_Phi_Laplacian(potential);

            return potential;
        }
Example #53
0
 protected abstract void Save_Data(Band_Data density, string input_file_name);
Example #54
0
 protected override void Save_Data(Band_Data density, string input_file_name)
 {
     density.Save_1D_Data(input_file_name, exp.Dz_Pot, exp.Zmin_Pot);
 }
Example #55
0
        public static Band_Data operator -(Band_Data vec1, Band_Data vec2)
        {
            Band_Data result;

            // return null if both of the inputs are null
            if (vec1 == null || vec2 == null)
                return null;

            if (vec1.Dimension != vec2.Dimension)
                throw new RankException();

            if (vec1.Dimension == 1)
                result = new Band_Data(vec1.vec - vec2.vec);
            else if (vec1.Dimension == 2)
                result = new Band_Data(vec1.mat - vec2.mat);
            else if (vec1.Dimension == 3)
            {
                result = new Band_Data(new DoubleMatrix[vec1.vol.Length]);
                for (int i = 0; i < vec1.vol.Length; i++)
                    result.vol[i] = vec1.vol[i] - vec2.vol[i];
            }
            else
                throw new NotImplementedException();

            result.Laplacian = vec1.Laplacian - vec2.Laplacian;
            return result;
        }
Example #56
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;
        }
Example #57
0
        public static Band_Data Parse_Band_Data(string location, string[] input_data, int nx, int ny, int nz)
        {
            // and check that there is the right number of data points back
            if (input_data.Length != nx * ny * nz)
                throw new Exception("Error - FlexPDE is outputting the wrong number of potential data points");

            // and parse these values into a DoubleVector
            Band_Data 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] = double.Parse(input_data[k * nx * ny + j * nx + i]);

            result.value_location = location;
            return result;
        }
 public SpinResolved_Data(int nx, int ny, int nz)
 {
     spin_data    = new Band_Data[2];
     spin_data[0] = new Band_Data(nx, ny, nz, 0.0); spin_data[1] = new Band_Data(nx, ny, nz, 0.0);
 }
Example #59
0
 /// <summary>
 /// Initiates a laplacian for this Band_Data class of the correct size
 /// </summary>
 public void Initiate_Laplacian()
 {
     this.laplacian_band_data = 0.0 * this;
 }
Example #60
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();
 }