Ejemplo n.º 1
0
        static void Calculate_1D_Band_Structure(Dictionary <string, object> inputs)
        {
            OneD_ThomasFermiPoisson.Experiment exp_init = new OneD_ThomasFermiPoisson.Experiment();

            Console.WriteLine("Performing density dopent calculation");
            Dictionary <string, object> inputs_init = new Dictionary <string, object>();

            if ((int)(double)inputs["dim"] != 1)
            {
                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("output_suffix", "_1d.dat");
                inputs_init.Add("T", inputs["T"]);
            }
            else
            {
                inputs_init = inputs.Where(s => s.Key.ToLower().EndsWith("")).ToDictionary(dict => dict.Key, dict => dict.Value);
            }


            //    Inputs_to_Dictionary.Add_Input_Parameters_to_Dictionary(ref inputs_init, "Input_Parameters_1D.txt");
            exp_init.Initialise(inputs_init);
            exp_init.Run();
            inputs.Add("Carrier_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");

            if ((int)(double)inputs["dim"] == 2)
            {
                // create a scaled data file containing the dopent density
                double scaling_factor = ((double)inputs["ny"] * (double)inputs["dy"]) / ((double)inputs["nz"] * (double)inputs["dz"]);
                Input_Band_Structure.Expand_BandStructure(exp_init.Dopent_Density, (int)(double)inputs["ny_1d"]).Spin_Summed_Data.Save_2D_Data("dens_2D_dopents.dat", (double)inputs["dy"] * ((double)inputs["ny"] + 2.0) / ((double)inputs["ny_1d"] - 1.0), scaling_factor * (double)inputs_init["dz"], -1.0 * (double)inputs["dy"] * ((double)inputs["ny"] + 2.0) / 2.0, scaling_factor * Geom_Tool.Get_Zmin(exp_init.Layers));
            }
            else if ((int)(double)inputs["dim"] == 3)
            {
                // 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");
            }
        }
Ejemplo n.º 2
0
        public override bool Run()
        {
            if (!initialise_from_restart)
            {
                // calculate the bare potential
                Console.WriteLine("Calculating bare potential");
                chem_pot = Physics_Base.q_e * pois_solv.Get_Potential(0.0 * carrier_charge_density.Spin_Summed_Data);
                Console.WriteLine("Saving bare potential");
                (Input_Band_Structure.Get_BandStructure_Grid(layers, dx_dens, dy_dens, dz_dens, nx_dens, ny_dens, nz_dens, xmin_dens, ymin_dens, zmin_dens) - chem_pot).Save_Data("bare_pot.dat");
                Console.WriteLine("Bare potential saved");

                //if the initial carrier density was not zero, recalculate the chemical potential
                if (carrier_charge_density.Spin_Summed_Data.Max() != 0.0 || carrier_charge_density.Spin_Summed_Data.Min() != 0.0)
                {
                    chem_pot = Physics_Base.q_e * pois_solv.Get_Potential(carrier_charge_density.Spin_Summed_Data);
                }
            }

            // get the dopent density from the Poisson equation
            dopent_charge_density.Spin_Up   = -0.5 * (chem_pot.Laplacian / Physics_Base.q_e + carrier_charge_density.Spin_Summed_Data);
            dopent_charge_density.Spin_Down = -0.5 * (chem_pot.Laplacian / Physics_Base.q_e + carrier_charge_density.Spin_Summed_Data);

            //      ThreeD_ThomasFermiSolver dens_solv = new ThreeD_ThomasFermiSolver(this);
            //ThreeD_EffectiveBandSolver dft_solv = new ThreeD_EffectiveBandSolver(this);
            //  TwoplusOneD_ThomasFermiSolver dft_solv = new TwoplusOneD_ThomasFermiSolver(this);

            bool converged = false;

            // start without dft if carrier density is empty
            if (no_dft || carrier_charge_density.Spin_Summed_Data.Min() == 0.0)
            {
                dens_solv.DFT_Mixing_Parameter = 0.0;
            }
            else
            {
                dens_solv.DFT_Mixing_Parameter = dft_mixing_parameter;
            }

            // do preliminary run to correct for initial discretised form of rho_prime
            if (initial_run)
            {
                converged = Run_Iteration_Routine(dens_solv, pois_solv, tol, initial_run_steps);
                // and calculate the potential given the density from this initial run
                pois_solv.Initiate_Poisson_Solver(device_dimensions, boundary_conditions);
                chem_pot = Physics_Base.q_e * pois_solv.Get_Potential(carrier_charge_density.Spin_Summed_Data);
            }
            if (!converged || !initial_run)
            //if(true)
            {
                int count = 0;
                while (pot_init > tol_anneal && count < 20)
                {
                    if (count != 0)
                    {
                        pois_solv.Initiate_Poisson_Solver(device_dimensions, boundary_conditions);
                        chem_pot = Physics_Base.q_e * pois_solv.Get_Potential(carrier_charge_density.Spin_Summed_Data);
                    }

                    // run the iteration routine!
                    converged = Run_Iteration_Routine(dens_solv, pois_solv, tol, max_iterations);

                    count++;
                }
            }

            // save surface charge
            StreamWriter sw = new StreamWriter("surface_charge.dat"); sw.WriteLine(boundary_conditions["surface"].ToString()); sw.Close();

            // save eigen-energies

            /*DoubleVector energies = dft_solv.Get_EnergyLevels(layers, chem_pot);
             * StreamWriter sw_e = new StreamWriter("energies.dat");
             * for (int i = 0; i < energies.Length; i++)
             *  sw_e.WriteLine(energies[i]);
             * sw_e.Close();*/

            dens_solv.Output(carrier_charge_density, "carrier_density.dat");
            dens_solv.Output(carrier_charge_density - dens_solv.Get_ChargeDensity(layers, carrier_charge_density, dopent_charge_density, chem_pot), "density_error.dat");
            (Input_Band_Structure.Get_BandStructure_Grid(layers, dx_dens, dy_dens, dz_dens, nx_dens, ny_dens, nz_dens, xmin_dens, ymin_dens, zmin_dens) - chem_pot).Save_Data("potential.dat");
            Band_Data pot_exc = dens_solv.DFT_diff(carrier_charge_density) + dens_solv.Get_XC_Potential(carrier_charge_density);

            pot_exc.Save_Data("xc_pot.dat");
            (Input_Band_Structure.Get_BandStructure_Grid(layers, dx_dens, dy_dens, dz_dens, nx_dens, ny_dens, nz_dens, xmin_dens, ymin_dens, zmin_dens) - chem_pot + pot_exc).Save_Data("pot_KS.dat");
//            Band_Data ks_ke = dft_solv.Get_KS_KE(layers, chem_pot);
//            ks_ke.Save_Data("ks_ke.dat");

            // clean up intermediate data files
            File.Delete("phi.dat");
            File.Delete("new_phi.dat");
            File.Delete("x.dat");
            File.Delete("y.dat");
            File.Delete("gphi.dat");
            File.Delete("car_dens.dat");
            File.Delete("rho_prime.dat");
            File.Delete("xc_pot.dat");
            File.Delete("xc_pot_calc.dat");
            File.Delete("pot.dat");
            File.Delete("carrier_density.dat");
            File.Delete("charge_density.dat");
            File.Delete("potential.dat");
            File.Delete("lap.dat");

            Close(dens_solv.Unit_Charge, converged, max_iterations);

            return(converged);
        }
Ejemplo n.º 3
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");
        }
Ejemplo n.º 4
0
        static void Main(string[] args)
        {
            Console.WriteLine("Setting Centerspace key");

            // 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");

            ////////////////////////////////////////////////
            //
            //    EDITS FOR BATCH RUNS
            //
            ////////////////////////////////////////////////

            // read in the value of vsg to be used
            Console.WriteLine("Enter split gate voltage");
            //         inputs["split_V"] = double.Parse(Console.ReadLine());
            int index = int.Parse(args[0]);

            int maxval = (int)(double)inputs["nVsg"];
            int i1     = index % maxval;
            int i2     = (index - i1) / maxval;

            // split gate with bias
//            double v1 = -0.5 - 0.25 * (double)i1;
//            double v2 = -0.5 - 0.02 * (double)i2;
//            if (v1 + v2 < -2.2 || v1 < v2)
//                return;
//            inputs["split_V1"] = v1;
//            inputs["split_V2"] = v2;
//            inputs["voltages"] = "{" + v1.ToString() + ", " + v2.ToString() + "}";
//            Console.WriteLine("Setting \"split_V1\" to " + ((double)inputs["split_V1"]).ToString() + "V");
//            Console.WriteLine("Setting \"split_V2\" to " + ((double)inputs["split_V2"]).ToString() + "V");
//            inputs["top_V"] = 0.0;
//            Console.WriteLine("Setting \"top_V\" to " + ((double)inputs["top_V"]).ToString() + "V");
//            inputs["output_suffix"] = "_sg1" + ((double)inputs["split_V1"]).ToString("F2") + "_sg2" + ((double)inputs["split_V2"]).ToString("F2") + ".dat";

            //top gated with constant side gate
            double v1 = (double)inputs["sg_init"] + (double)inputs["dVsg"] * (double)i1;

            inputs["split_V"] = v1;
            Console.WriteLine("Setting \"split_V\" to " + ((double)inputs["split_V"]).ToString() + "V");
            inputs["top_V"] = (double)inputs["tg_init"] + (double)inputs["dVtg"] * (double)i2;
            Console.WriteLine("Setting \"top_V\" to " + ((double)inputs["top_V"]).ToString() + "V");
            inputs["output_suffix"] = "_sg" + ((double)inputs["split_V"]).ToString("F3") + "_tg" + ((double)inputs["top_V"]).ToString("F3") + ".dat";

            ////////////////////////////////////////////////

            inputs["voltages"] = "{" + v1.ToString() + ", " + v1.ToString() + "}";
            // 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();
            }

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

            OneD_ThomasFermiPoisson.Experiment exp_init = new OneD_ThomasFermiPoisson.Experiment();

            // check if we should start from a precalculated density
            // consistency of band-structure, etc is the responsibility of the user...
            //if (!(bool)inputs["hot_start"])
            {
                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_to_Dictionary.Add_Input_Parameters_to_Dictionary(ref inputs_init, "Input_Parameters_1D.txt");
                exp_init.Initialise(inputs_init);
                exp_init.Run();
                inputs.Add("Carrier_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");

                //Input_Band_Structure.Expand_BandStructure(exp_init.Dopent_Density, (int)(double)inputs_init["ny_1d"]).Spin_Summed_Data.Save_2D_Data("dens_2D_dopents.dat", (double)inputs["dy"] * (double)inputs["ny"] / (double)inputs_init["ny_1d"], (double)inputs_init["dz"], -1.0 * (double)inputs["dy"] * (double)inputs["ny"] / 2.0, Geom_Tool.Get_Zmin(exp_init.Layers));

                // this is a scaled version for the dopents!
                double scaling_factor = ((double)inputs["ny"] * (double)inputs["dy"]) / ((double)inputs["nz"] * (double)inputs["dz"]);
                Input_Band_Structure.Expand_BandStructure(exp_init.Dopent_Density, (int)(double)inputs["ny_1d"]).Spin_Summed_Data.Save_2D_Data("dens_2D_dopents.dat", (double)inputs["dy"] * ((double)inputs["ny"] + 2.0) / ((double)inputs["ny_1d"] - 1.0), scaling_factor * (double)inputs_init["dz"], -1.0 * (double)inputs["dy"] * ((double)inputs["ny"] + 2.0) / 2.0, scaling_factor * Geom_Tool.Get_Zmin(exp_init.Layers));
                //       Input_Band_Structure.Expand_BandStructure(exp_init.Carrier_Density, (int)(double)inputs_init["ny_1d"]).Spin_Summed_Data.Save_2D_Data("dens_2D.dat", (double)inputs["dy"] * ((double)inputs["ny"] + 2.0) / ((double)inputs_init["ny_1d"] - 1.0), (double)inputs_init["dz"], -1.0 * (double)inputs["dy"] * ((double)inputs["ny"] + 2.0) / 2.0, Geom_Tool.Get_Zmin(exp_init.Layers));
                Console.WriteLine("Saved 1D dopent density");
            }

            if ((bool)inputs["batch_run"])
            {
                Run_Multiple_SGs(inputs);
            }
            else
            {
                Console.WriteLine("Starting experiment");
                exp.Initialise(inputs);
                // check that the dz_pot are the same for both simulations as this is needed for the interpolation of SpinResolved_Density
                if (!(bool)inputs["hot_start"] && exp_init.Dz_Pot != exp.Dz_Pot)
                {
                    throw new Exception("Error - the dz values for the potentials must be the same for \"Input_Parameters.txt\" and \"Input_Parameters_1D.txt\"");
                }
                Console.WriteLine("Experiment initialised");
                exp.Run();

                Console.WriteLine("Experiment complete");
            }
        }
Ejemplo n.º 5
0
        public override bool Run()
        {
            // get temperatures to run the experiment at
            double[] run_temps   = Freeze_Out_Temperatures();
            double   target_temp = temperature;

            // run experiment using Thomas-Fermi solver
            for (int i = 0; i < run_temps.Length; i++)
            {
                current_temperature = run_temps[i];
                this.temperature    = current_temperature;
                if (surface_charge.ContainsKey(current_temperature))
                {
                    no_dft = false;
                    continue;
                }

                OneD_ThomasFermiSolver dens_solv = new OneD_ThomasFermiSolver(this, Dz_Pot, Zmin_Pot, Nz_Pot);
                dens_solv.DFT_Mixing_Parameter = 0.0;

                if (!Geom_Tool.GetLayer(layers, zmin_pot).Dopents_Frozen_Out(current_temperature) && !fix_bottom_V)
                {
                    boundary_conditions["bottom_V"] = dens_solv.Get_Chemical_Potential(zmin_pot, layers, current_temperature) / (Physics_Base.q_e * Physics_Base.energy_V_to_meVpzC);
                }

                // reset the converged flag for every temperature
                converged = false;
                if (dopents_calculated)
                {
                    continue;
                }

                if (illuminated && i == run_temps.Length - 1)
                {
                    for (int j = 0; j < dopent_charge_density.Spin_Summed_Data.Length - 1; j++)
                    {
                        double pos = Zmin_Pot + j * Dz_Pot;
                        dopent_charge_density.Spin_Up[j]   = 0.5 * Physics_Base.q_e * (Geom_Tool.GetLayer(layers, pos).Donor_Conc - Geom_Tool.GetLayer(layers, pos).Acceptor_Conc);
                        dopent_charge_density.Spin_Down[j] = 0.5 * Physics_Base.q_e * (Geom_Tool.GetLayer(layers, pos).Donor_Conc - Geom_Tool.GetLayer(layers, pos).Acceptor_Conc);
                    }
                }

                converged = Run_Iteration_Routine(dens_solv, pois_solv, tol, max_iterations);
                if (!converged)
                {
                    temperature = target_temp;
                    no_dft      = true;
                    return(converged);
                }

                // save the surface charge for this temperature
                surface_charge.Add(current_temperature, pois_solv.Get_Surface_Charge(chem_pot, layers));

                pois_solv.Reset();
            }

            if (!no_dft)
            {
                // reset the converged flag for the quantum calculation
                converged = false;

                // get the correct density solver
                IOneD_Density_Solve dft_solv;
                if (carrier_type == Carrier.electron || carrier_type == Carrier.hole)
                {
                    dft_solv = new OneD_DFTSolver(this, carrier_type);
                }
                else if (carrier_type == Carrier.both)
                {
                    dft_solv = new OneD_eh_DFTSolver(this);
                }
                else
                {
                    throw new NotImplementedException();
                }

                dft_solv.DFT_Mixing_Parameter = 1.0;                 //NOTE: This method doesn't mix in the DFT potential, it is stable enough when V_xc is calculated every iteration
                dft_solv.Zmin_Pot             = zmin_pot; dft_solv.Dz_Pot = dz_pot;

                // and then run the DFT solver at the base temperature
                Console.WriteLine("Starting DFT calculation");
                converged = Run_Iteration_Routine(dft_solv, pois_solv, tol, max_iterations);

                pois_solv.Reset();

                (Input_Band_Structure.Get_BandStructure_Grid(layers, dz_pot, nz_pot, zmin_pot) - chem_pot).Save_Data("potential" + output_suffix);
            }

            // calculate the density of the negative and positive charges separately
            double neg_dens = (from val in carrier_charge_density.Spin_Summed_Data.vec
                               where val < 0.0
                               select - 1.0e14 * val * dz_dens / Physics_Base.q_e).ToArray().Sum();
            double pos_dens = (from val in carrier_charge_density.Spin_Summed_Data.vec
                               where val > 0.0
                               select 1.0e14 * val * dz_dens / Physics_Base.q_e).ToArray().Sum();

            double unit_charge = -1.0 * Physics_Base.q_e;

            if (pos_dens == 0.0)
            {
                Console.WriteLine("Electron carrier density at heterostructure interface: \t" + neg_dens.ToString("e3") + " cm^-2");
            }
            else if (neg_dens == 0.0)
            {
                Console.WriteLine("Hole carrier density at heterostructure interface: \t" + pos_dens.ToString("e3") + " cm^-2");
                unit_charge = Physics_Base.q_e;
            }
            else
            {
                Console.WriteLine("WARNING!  Carriers of both charges found on the interface");
                Console.WriteLine("Electron density at heterostructure interface: \t" + neg_dens.ToString("e3") + " cm^-2");
                Console.WriteLine("Hole density at heterostructure interface: \t" + pos_dens.ToString("e3") + " cm^-2");
            }

            // there is no iteration timeout for the 1D solver so if it gets to this point the solution will definitely have converged
            Close(unit_charge, converged, max_iterations);

            return(converged);
        }
Ejemplo n.º 6
0
        private void step_button_Click(object sender, EventArgs e)
        {
            dimension = 1;

            conduction_band.Series["conduction_band_data"].Points.Clear();
            conduction_band.Series["valence_band_data"].Points.Clear();
            conduction_band.Series["x_data"].Points.Clear();
            density.Series["car_dens_data"].Points.Clear();
            density.Series["dop_dens_data"].Points.Clear();
            density.Series["gphi_data"].Points.Clear();

            int nz;
            int i = int.Parse(count_no_label.Text);

            if (!int.TryParse(nz1Dval.Text, out nz))
            {
                MessageBox.Show("Format of Nz for dopent potential is invalid");
                return;
            }

            // initialise dopent experiment if the count is zero
            if (i == 0)
            {
                exp1d = new OneD_ThomasFermiPoisson.Experiment();

                car_dens = new SpinResolved_Data(nz);
                dop_dens = new SpinResolved_Data(nz);

                Dictionary <string, object> inputs_tmp = Create_Dictionary();
                foreach (KeyValuePair <string, object> option in inputs_tmp)
                {
                    inputs.Add(option.Key.Replace("_1d", ""), option.Value);
                }


                inputs["surface_charge"] = 0.0;
                inputs["max_iterations"] = 0.0;

                exp1d.Initialise(inputs);
            }

            converged = exp1d.Run();

            ILayer[] layers = exp1d.Layers;
            double   dz     = exp1d.Dz_Pot;
            double   zmin   = exp1d.Zmin_Pot;

            car_dens = exp1d.Carrier_Density;
            dop_dens = exp1d.Dopent_Density;
            Band_Data x    = Physics_Base.q_e * exp1d.X;
            Band_Data gphi = exp1d.GPhi;

            chem_pot = (Input_Band_Structure.Get_BandStructure_Grid(layers, dz, nz, zmin) - exp1d.Chemical_Potential);        // + x);
            val_pot  = (-1.0 * Input_Band_Structure.Get_BandStructure_Grid(layers, dz, nz, zmin) - exp1d.Chemical_Potential); // + x);

            for (int j = 0; j < chem_pot.Length; j++)
            {
                double pos = zmin + dz * j;
                conduction_band.Series["conduction_band_data"].Points.AddXY(pos, chem_pot[j]);
                conduction_band.Series["valence_band_data"].Points.AddXY(pos, val_pot[j]);
                conduction_band.Series["x_data"].Points.AddXY(pos, x[j]);
                density.Series["car_dens_data"].Points.AddXY(pos, car_dens.Spin_Summed_Data[j]);
                density.Series["dop_dens_data"].Points.AddXY(pos, dop_dens.Spin_Summed_Data[j]);
                density.Series["gphi_data"].Points.AddXY(pos, gphi[j]);
            }

            Set_Plot_Axes(dens_xmin_val.Text, dens_xmax_val.Text, density.ChartAreas["ChartArea1"].AxisX);
            Set_Plot_Axes(dens_ymin_val.Text, dens_ymax_val.Text, density.ChartAreas["ChartArea1"].AxisY);
            Set_Plot_Axes(pot_xmin_val.Text, pot_xmax_val.Text, conduction_band.ChartAreas["ChartArea1"].AxisX);
            Set_Plot_Axes(pot_ymin_val.Text, pot_ymax_val.Text, conduction_band.ChartAreas["ChartArea1"].AxisY);

            conduction_band.Refresh();
            density.Refresh();
            this.count_no_label.Text        = (i + 1).ToString();
            this.temperature_val_label.Text = exp1d.Current_Temperature.ToString() + " K";

            this.carrier_dopent_density_Text.Text = (from val in car_dens.Spin_Summed_Data.vec
                                                     where val < 0.0
                                                     select - 1.0e14 * val * dz / Physics_Base.q_e).ToArray().Sum().ToString("e3");
        }