Exemple #1
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);
        }
Exemple #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);
        }
Exemple #3
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");
        }