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; }
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); }