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); }
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"); } }
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"); }
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"); } }
public override void Initialise(Dictionary <string, object> input_dict) { // simulation domain inputs Get_From_Dictionary <double>(input_dict, "dz", ref dz_dens); dz_pot = dz_dens; Get_From_Dictionary(input_dict, "nz", ref nz_dens); nz_pot = nz_dens; // physics parameters are done by the base method base.Initialise(input_dict); Get_From_Dictionary <bool>(input_dict, "illuminated", ref illuminated, true); // check that the size of the domain [(nz_pot-1) * dz_pot] is not larger than the band structure if (layers[layers.Length - 1].Zmax - Geom_Tool.Get_Zmin(layers) < (Nz_Pot - 1) * Dz_Pot) { throw new Exception("Error - the band structure provided is smaller than the simulation domain!\nUse nz = " + (int)Math.Ceiling((layers[layers.Length - 1].Zmax - Geom_Tool.Get_Zmin(layers)) / Dz_Pot) + " instead"); } // and check that the top of the domain is the surface (unless this check is overloaded) bool surface_override = false; Get_From_Dictionary <bool>(input_dict, "surface_check", ref surface_override, true); if (!surface_override && Geom_Tool.Find_Layer_Below_Surface(layers).Zmax - Geom_Tool.Get_Zmin(layers) - Nz_Pot * Dz_Pot != 0.0) { throw new Exception("Error - the top of the domain is not the surface!\nUse the input \"surface_check\" to override"); } // calculate the top and bottom of the domain input_dict["zmin"] = Geom_Tool.Get_Zmin(layers); input_dict["zmax"] = Geom_Tool.Get_Zmin(layers) + dz_pot * nz_pot; // and split gate dimensions device_dimensions.Add("bottom_position", (double)input_dict["zmin"]); device_dimensions.Add("top_position", (double)input_dict["zmax"]); // check whether the bottom should be fixed if (input_dict.ContainsKey("bottom_V")) { fix_bottom_V = true; } // initialise the dictionary which contains the surface charges at each temperature surface_charge = new Dictionary <double, double>(); // double check whether you want to use FlexPDE if (input_dict.ContainsKey("use_FlexPDE")) { using_flexPDE = (bool)input_dict["use_FlexPDE"]; } // Initialise potential solver pois_solv = new OneD_PoissonSolver(this, using_flexPDE, input_dict); Initialise_DataClasses(input_dict); // if the input dictionary already has the dopent distribution, we don't need to recalculate it if (input_dict.ContainsKey("Dopent_Density")) { dopents_calculated = true; } // Get carrier type for DFT calculations (default is electron) if (input_dict.ContainsKey("carrier_type")) { carrier_type = (Carrier)Enum.Parse(typeof(Carrier), (string)input_dict["carrier_type"]); } Console.WriteLine("Experimental parameters initialised"); }
public virtual void Initialise(Dictionary <string, object> input_dict) { // solver inputs Get_From_Dictionary <double>(input_dict, "tolerance", ref tol); tol_anneal = tol; Get_From_Dictionary <double>(input_dict, "anneal_tolerance", ref tol_anneal, true); Get_From_Dictionary(input_dict, "max_iterations", ref max_iterations, true); Get_From_Dictionary <bool>(input_dict, "initial_run", ref initial_run, true); Get_From_Dictionary(input_dict, "initial_run_steps", ref initial_run_steps, true); // will not use FlexPDE unless told to if (input_dict.ContainsKey("use_FlexPDE")) { this.using_flexPDE = (bool)input_dict["use_FlexPDE"]; } else { using_flexPDE = false; } // and the same for dealii if (input_dict.ContainsKey("use_deal.II")) { this.using_dealii = (bool)input_dict["use_deal.II"]; } else { using_dealii = false; } // check to make sure that we haven't asked to use more than one external program to calculate the potential if (using_flexPDE == true && using_dealii == true) { throw new Exception("Error - Cannot use both FlexPDE and deal.II to calculate the potential!"); } // physical inputs Get_From_Dictionary <double>(input_dict, "init_T", ref initial_temperature, true); Get_From_Dictionary <double>(input_dict, "T", ref temperature); // get the band structure if (input_dict.ContainsKey("Layers")) { layers = (ILayer[])input_dict["Layers"]; } else { if (input_dict.ContainsKey("BandStructure_File")) { layers = Input_Band_Structure.Get_Layers((string)input_dict["BandStructure_File"]); input_dict.Add("Layers", layers); } else { throw new KeyNotFoundException("No band structure file found in input dictionary!"); } } // but try to get the specific values Get_From_Dictionary <double>(input_dict, "dx_dens", ref dx_dens, true); Get_From_Dictionary <double>(input_dict, "dy_dens", ref dy_dens, true); Get_From_Dictionary <double>(input_dict, "dz_dens", ref dz_dens, true); Get_From_Dictionary <double>(input_dict, "dx_pot", ref dx_pot, true); Get_From_Dictionary <double>(input_dict, "dy_pot", ref dy_pot, true); Get_From_Dictionary <double>(input_dict, "dz_pot", ref dz_pot, true); Get_From_Dictionary(input_dict, "nx_dens", ref nx_dens, true); Get_From_Dictionary(input_dict, "ny_dens", ref ny_dens, true); Get_From_Dictionary(input_dict, "nz_dens", ref nz_dens, true); Get_From_Dictionary(input_dict, "nx_pot", ref nx_pot, true); Get_From_Dictionary(input_dict, "ny_pot", ref ny_pot, true); Get_From_Dictionary(input_dict, "nz_pot", ref nz_pot, true); // and find the domain minimum coordinate values xmin_pot = Geom_Tool.Get_Xmin(layers); ymin_pot = Geom_Tool.Get_Ymin(layers); zmin_pot = Geom_Tool.Get_Zmin(layers); // but still try to get them from the dictionary if its there Get_From_Dictionary <double>(input_dict, "xmin_pot", ref xmin_pot, true); Get_From_Dictionary <double>(input_dict, "ymin_pot", ref ymin_pot, true); Get_From_Dictionary <double>(input_dict, "zmin_pot", ref zmin_pot, true); // and by default these are the same as for the density xmin_dens = xmin_pot; ymin_dens = ymin_pot; zmin_dens = zmin_pot; // and, once again, try to find something in the dictionary Get_From_Dictionary <double>(input_dict, "xmin_dens", ref xmin_dens, true); Get_From_Dictionary <double>(input_dict, "ymin_dens", ref ymin_dens, true); Get_From_Dictionary <double>(input_dict, "zmin_dens", ref zmin_dens, true); // and try and get as much information about the split gate dimensions as possible device_dimensions = new Dictionary <string, double>(); device_dimensions.Add("top_length", Get_From_Dictionary <double>(input_dict, "top_length", 0.0)); device_dimensions.Add("split_width", Get_From_Dictionary <double>(input_dict, "split_width", 0.0)); device_dimensions.Add("split_length", Get_From_Dictionary <double>(input_dict, "split_length", 0.0)); // as well as for the gate voltages boundary_conditions = new Dictionary <string, double>(); boundary_conditions.Add("top_V", Get_From_Dictionary <double>(input_dict, "top_V", 0.0)); boundary_conditions.Add("split_V1", Get_From_Dictionary <double>(input_dict, "split_V1", Get_From_Dictionary <double>(input_dict, "split_V", 0.0))); boundary_conditions.Add("split_V2", Get_From_Dictionary <double>(input_dict, "split_V2", Get_From_Dictionary <double>(input_dict, "split_V", 0.0))); boundary_conditions.Add("bottom_V", Get_From_Dictionary <double>(input_dict, "bottom_V", 0.0)); Inputs_to_Dictionary.Parse_Voltages(input_dict, boundary_conditions); // work out whether we are doing dft or not Get_From_Dictionary <bool>(input_dict, "no_dft", ref no_dft, true); if (input_dict.ContainsKey("dft")) { no_dft = !(bool)input_dict["dft"]; } // and whether to set the mixing parameter to something other than the default Get_From_Dictionary <double>(input_dict, "dft_mixing_parameter", ref dft_mixing_parameter, true); // get keys for any interesting start-up protocols if (input_dict.ContainsKey("hot_start")) { hot_start = (bool)input_dict["hot_start"]; } Get_From_Dictionary <bool>(input_dict, "initialise_with_1D_data", ref initialise_with_1D_data, true); if (File.Exists("restart.flag") && input_dict.ContainsKey("with_checkpointing")) { if (File.ReadAllLines("restart.flag")[0] == "true" && (bool)input_dict["with_checkpointing"]) { initialise_from_restart = true; } } // and create a restart flag file if necessary if (!initialise_from_restart) { StreamWriter sw_flag = new StreamWriter("restart.flag"); sw_flag.WriteLine("true"); sw_flag.Close(); } if (!Check_Boundary_Points(layers, Zmin_Dens, Zmin_Dens + Dz_Dens * Nz_Dens, Dz_Dens)) { throw new Exception("Error - there must be lattice points on all of the boundaries between zmin = " + Zmin_Dens.ToString() + " and zmax = " + (Zmin_Dens + Dz_Dens * Nz_Dens).ToString()); } // and load the output suffix for identification of output files Get_From_Dictionary <string>(input_dict, "output_suffix", ref output_suffix, true); }
public void Create_FlexPDE_File(double top_bc, double top_length, double split_bc1, double split_bc2, double split_width, double split_length, double surface, double bottom_bc, string output_file) { StreamWriter sw = new StreamWriter(output_file); // write out output file sw.WriteLine("TITLE \'Full Split Gate Geometry\'"); sw.WriteLine("COORDINATES cartesian3"); sw.WriteLine("VARIABLES"); sw.WriteLine("\tu"); sw.WriteLine("SELECT"); // gives the flexPDE tolerance for the finite element solve sw.WriteLine("\tERRLIM=" + pot_tol.ToString()); sw.WriteLine("\tGRIDLIMIT=20"); sw.WriteLine("DEFINITIONS"); sw.WriteLine("\tband_gap"); sw.WriteLine(); // and the tables for carrier and donor densities sw.WriteLine("\trho_carrier = TABLE(\'" + dens_filename + "\', x, y, z)"); sw.WriteLine("\trho_dopent = TABLE(\'" + densdopent_filename + "\', x, y, z)"); sw.WriteLine(); // simulation dimension sw.WriteLine("\tlx = " + (exp.Dx_Pot * exp.Nx_Pot).ToString()); sw.WriteLine("\tly = " + (exp.Dy_Pot * exp.Ny_Pot).ToString()); sw.WriteLine(); sw.WriteLine("\t! Scale factors"); sw.WriteLine("\ty_scaling = " + y_scaling.ToString()); sw.WriteLine("\tz_scaling = " + z_scaling.ToString()); sw.WriteLine(); sw.WriteLine("\tbottom_bc = " + bottom_bc.ToString()); sw.WriteLine("\ttop_bc = " + top_bc.ToString()); sw.WriteLine("\tsurface_bc = " + surface.ToString() + " * z_scaling"); sw.WriteLine(); sw.WriteLine("\t! GATE VOLTAGE INPUTS (in meV zC^-1)"); for (int i = 0; i < gate_bcs.Count; i++) { sw.WriteLine("\tV" + i.ToString() + " = " + gate_bcs[i].ToString()); } sw.WriteLine(); sw.WriteLine("\t! SPLIT GATE DIMENSIONS (in nm)"); sw.WriteLine("\tsplit_width = " + split_width.ToString() + ""); sw.WriteLine("\tsplit_length = " + split_length.ToString()); sw.WriteLine("\ttop_length = " + top_length.ToString()); sw.WriteLine("\tsplit_depth = 10! depth of the split gate metal material"); sw.WriteLine("\ttop_depth = 10! depth of the top gate metal material"); sw.WriteLine(); sw.WriteLine("\t! WELL DEPTH (in nm)"); sw.WriteLine("\twell_depth = " + z_2DEG.ToString()); sw.WriteLine(); sw.WriteLine("\t! Electrical permitivity"); sw.WriteLine("\teps"); sw.WriteLine(); // other physical parameters sw.WriteLine("\tq_e = " + Physics_Base.q_e.ToString() + "! charge of electron in zC"); sw.WriteLine(); sw.WriteLine("EQUATIONS"); // Poisson's equation sw.WriteLine("\tu: dx(eps * dx(u)) + y_scaling * dy(eps * y_scaling * dy(u)) + z_scaling * dz(eps * z_scaling * dz(u)) = - (rho_carrier + rho_dopent)\t! Poisson's equation"); sw.WriteLine(); // draw the domain Draw_Domain(sw); sw.WriteLine(); sw.WriteLine("\t\tFRONT(z - well_depth * z_scaling, 50 * z_scaling)"); sw.WriteLine("\t\tFRONT(z - well_depth, 50 * z_scaling)"); sw.WriteLine(); sw.WriteLine("!MONITORS"); sw.WriteLine("\t!CONTOUR(rho_carrier) ON z = well_depth * z_scaling"); sw.WriteLine("\t!CONTOUR(u) ON z = well_depth * z_scaling"); sw.WriteLine("\t!CONTOUR(u) ON x = 0"); sw.WriteLine("\t!CONTOUR(u) ON y = 0"); sw.WriteLine("PLOTS"); sw.WriteLine("\t!CONTOUR(rho_carrier + rho_dopent) ON x = 0"); sw.WriteLine("\t!CONTOUR(u) ON x = 0"); sw.WriteLine("\t!CONTOUR(u) ON y = 0"); sw.WriteLine("\t!CONTOUR(rho_carrier) ON z = well_depth * z_scaling"); sw.WriteLine("\t!CONTOUR(- q_e * u + 0.5 * band_gap) ON z = well_depth * z_scaling"); sw.WriteLine("\t!ELEVATION(rho_carrier + rho_dopent) FROM (0,0, " + Geom_Tool.Get_Zmin(exp.Layers).ToString() + " * z_scaling) TO (0, 0, " + exp.Layers[exp.Layers.Length - 1].Zmax.ToString() + " * z_scaling)"); sw.WriteLine("\t!ELEVATION(- q_e * u + 0.5 * band_gap) FROM (0, 0, " + Geom_Tool.Get_Zmin(exp.Layers).ToString() + " * z_scaling) TO (0, 0, " + exp.Layers[exp.Layers.Length - 1].Zmax.ToString() + " * z_scaling)"); sw.WriteLine("\t!ELEVATION(- q_e * u + 0.5 * band_gap) FROM (0, -ly / 2 * y_scaling, well_depth * z_scaling) TO (0, ly / 2 * y_scaling, well_depth * z_scaling)"); sw.WriteLine("\t!ELEVATION(- q_e * u + 0.5 * band_gap) FROM (-lx/2, 0, well_depth * z_scaling) TO (lx / 2, 0, well_depth * z_scaling)"); sw.WriteLine(); sw.WriteLine("\tTABLE(u) ZOOM (" + exp.Xmin_Dens.ToString() + ", " + (y_scaling * exp.Ymin_Dens).ToString() + ", " + (z_scaling * exp.Zmin_Dens).ToString() + ", " + ((exp.Nx_Dens - 1) * exp.Dx_Dens).ToString() + ", " + (y_scaling * (exp.Ny_Dens - 1) * exp.Dy_Dens).ToString() + ", " + (z_scaling * (exp.Nz_Dens - 1) * exp.Dz_Dens).ToString() + ") EXPORT FORMAT \"#1\" POINTS = (" + exp.Nx_Dens.ToString() + ", " + exp.Ny_Dens.ToString() + ", " + exp.Nz_Dens.ToString() + ") FILE = \"pot.dat\""); sw.WriteLine("\tTABLE(-1.0 * rho_carrier - rho_dopent) ZOOM (" + exp.Xmin_Dens.ToString() + ", " + (y_scaling * exp.Ymin_Dens).ToString() + ", " + (z_scaling * exp.Zmin_Dens).ToString() + ", " + ((exp.Nx_Dens - 1) * exp.Dx_Dens).ToString() + ", " + (y_scaling * (exp.Ny_Dens - 1) * exp.Dy_Dens).ToString() + ", " + (z_scaling * (exp.Nz_Dens - 1) * exp.Dz_Dens).ToString() + ") EXPORT FORMAT \"#1\" POINTS = (" + exp.Nx_Dens.ToString() + ", " + exp.Ny_Dens.ToString() + ", " + exp.Nz_Dens.ToString() + ") FILE = \"" + laplacian_file + "\""); sw.WriteLine("\tTRANSFER(u) FILE = \'" + pot_filename + "\'"); sw.WriteLine("\tTRANSFER(0.0 * u) FILE = \'" + new_pot_filename + "\' ! dummy file for smoother function"); sw.WriteLine(); sw.WriteLine("END"); sw.Close(); }