Beispiel #1
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);
        }
Beispiel #2
0
        /// <summary>
        /// initiates the poisson solver by writing the input file for the parameter handlers of the initcalc and newton methods
        /// </summary>
        public override void Initiate_Poisson_Solver(Dictionary <string, double> device_dimensions, Dictionary <string, double> boundary_conditions)
        {
            // get split gate specific device dimensions
            device_dimensions["zmin_pot"]        = exp.Layers[1].Zmin;
            device_dimensions["pmma_depth"]      = exp.Layers[exp.Layers.Length - 1].Zmax;
            device_dimensions["cap_depth"]       = Geom_Tool.Find_Layer_Below_Surface(exp.Layers).Zmin;
            device_dimensions["interface_depth"] = exp.Layers[1].Zmax;
            device_dimensions["buffer_depth"]    = exp.Layers[2].Zmax;

            // write the parameter details for the initial potential calculation
            StreamWriter sw_initcalc = new StreamWriter(initcalc_parameterfile);

            // check if the top layer is air... if so, we need to use natural boundary conditions on the upper surface
            bool natural_top_bc = (exp.Layers[exp.Layers.Length - 1].Material == Material.Air);

            if (natural_top_bc)
            {
                device_dimensions["top_V"] = 0.0;
            }

            sw_initcalc.WriteLine("subsection System Geometry");
            sw_initcalc.WriteLine("\tset zmin_pot = " + device_dimensions["zmin_pot"].ToString());
            sw_initcalc.WriteLine("\tset split_width = " + device_dimensions["split_width"].ToString());
            sw_initcalc.WriteLine("\tset pmma_depth = " + device_dimensions["pmma_depth"].ToString());
            sw_initcalc.WriteLine("\tset cap_depth = " + device_dimensions["cap_depth"].ToString());
            sw_initcalc.WriteLine("\tset interface_depth = " + device_dimensions["interface_depth"].ToString());
            sw_initcalc.WriteLine("\tset buffer_depth = " + device_dimensions["buffer_depth"].ToString());
            sw_initcalc.WriteLine("end");

            sw_initcalc.WriteLine("subsection Boundary Conditions");
            sw_initcalc.WriteLine("\tset top_bc = " + (boundary_conditions["top_V"] * Physics_Base.energy_V_to_meVpzC).ToString());
            sw_initcalc.WriteLine("\tset bottom_bc = " + (boundary_conditions["bottom_V"] * Physics_Base.energy_V_to_meVpzC).ToString());
            sw_initcalc.WriteLine("\tset split_bc1 = " + (boundary_conditions["V0"] * Physics_Base.energy_V_to_meVpzC).ToString());
            sw_initcalc.WriteLine("\tset split_bc2 = " + (boundary_conditions["V1"] * Physics_Base.energy_V_to_meVpzC).ToString());
            sw_initcalc.WriteLine("\tset surface_bc = " + (0.5 * boundary_conditions["surface"]).ToString());                                   // note that the surface "kink" is halved...
            // not sure why, but this is deal.II specific
            sw_initcalc.WriteLine("end");

            sw_initcalc.WriteLine("subsection Carrier Density Parameters");
            sw_initcalc.WriteLine("\tset ny_dens = " + exp.Ny_Dens.ToString());
            sw_initcalc.WriteLine("\tset nz_dens = " + exp.Nz_Dens.ToString());
            sw_initcalc.WriteLine("\tset ymin_dens = " + exp.Ymin_Dens.ToString());
            sw_initcalc.WriteLine("\tset ymax_dens = " + (exp.Ymin_Dens + exp.Dy_Dens * (exp.Ny_Dens - 1)).ToString());
            sw_initcalc.WriteLine("\tset zmin_dens = " + exp.Zmin_Dens.ToString());
            sw_initcalc.WriteLine("\tset zmax_dens = " + (exp.Zmin_Dens + exp.Dz_Dens * (exp.Nz_Dens - 1)).ToString());
            sw_initcalc.WriteLine("end");

            sw_initcalc.WriteLine("subsection Donor Density Parameters");
            sw_initcalc.WriteLine("\tset nz_donor = " + nz_donor);
            sw_initcalc.WriteLine("\tset zmin_donor = " + zmin_donor);
            sw_initcalc.WriteLine("\tset zmax_donor = " + zmax_donor);
            sw_initcalc.WriteLine("end");

            sw_initcalc.WriteLine("set natural top_bc = " + natural_top_bc.ToString().ToLower());

            sw_initcalc.Close();

            // and write the parameter details needed for the newton step
            StreamWriter sw_newton = new StreamWriter(newton_parameterfile);

            sw_newton.WriteLine("subsection System Geometry");
            sw_newton.WriteLine("\tset zmin_pot = " + device_dimensions["zmin_pot"].ToString());
            sw_newton.WriteLine("\tset split_width = " + device_dimensions["split_width"].ToString());
            sw_newton.WriteLine("\tset pmma_depth = " + device_dimensions["pmma_depth"].ToString());
            sw_newton.WriteLine("\tset cap_depth = " + device_dimensions["cap_depth"].ToString());
            sw_newton.WriteLine("\tset interface_depth = " + device_dimensions["interface_depth"].ToString());
            sw_newton.WriteLine("\tset buffer_depth = " + device_dimensions["buffer_depth"].ToString());
            sw_newton.WriteLine("end");

            sw_newton.WriteLine("subsection Carrier Density Parameters");
            sw_newton.WriteLine("\tset ny_dens = " + exp.Ny_Dens.ToString());
            sw_newton.WriteLine("\tset nz_dens = " + exp.Nz_Dens.ToString());
            sw_newton.WriteLine("\tset ymin_dens = " + exp.Ymin_Dens.ToString());
            sw_newton.WriteLine("\tset ymax_dens = " + (exp.Ymin_Dens + exp.Dy_Dens * (exp.Ny_Dens - 1)).ToString());
            sw_newton.WriteLine("\tset zmin_dens = " + exp.Zmin_Dens.ToString());
            sw_newton.WriteLine("\tset zmax_dens = " + (exp.Zmin_Dens + exp.Dz_Dens * (exp.Nz_Dens - 1)).ToString());
            sw_newton.WriteLine("end");

            sw_newton.WriteLine("set natural top_bc = " + natural_top_bc.ToString().ToLower());

            sw_newton.Close();
        }
Beispiel #3
0
        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");
        }
        private void Draw_Domain(StreamWriter sw)
        {
            sw.WriteLine("EXTRUSION");
            sw.WriteLine("\tSURFACE \"Substrate\"\tz = " + exp.Layers[0].Zmax.ToString() + " * z_scaling");
            for (int i = 1; i < exp.Layers.Length; i++)
            {
                sw.WriteLine("\t\tLAYER \"" + i.ToString() + "\"");
                sw.WriteLine("\tSURFACE	\"" + i.ToString() + "\"\tz = " + exp.Layers[i].Zmax.ToString() + " * z_scaling");
            }
            sw.WriteLine();
            sw.WriteLine("BOUNDARIES");
            sw.WriteLine("\tSURFACE \"Substrate\"	VALUE(u) = bottom_bc");
            sw.WriteLine("\tSURFACE \"" + (Geom_Tool.Find_Layer_Below_Surface(exp.Layers).Layer_No - 1).ToString() + "\" NATURAL(u) = surface_bc");
            //sw.WriteLine("\tSURFACE \"" + (exp.Layers.Length - 1).ToString() + "\" NATURAL(u) = 0");
            sw.WriteLine("\tSURFACE \"" + (exp.Layers.Length - 1).ToString() + "\" VALUE(u) = top_bc");
            sw.WriteLine();
            sw.WriteLine("\tREGION 1");
            for (int i = 1; i < exp.Layers.Length; i++)
            {
                sw.WriteLine("\t\tLAYER \"" + i.ToString() + "\"");

                sw.WriteLine("\t\teps = " + exp.Layers[i].Permitivity.ToString());
                sw.WriteLine("\t\tband_gap = " + exp.Layers[i].Band_Gap.ToString());
                sw.WriteLine();
            }
            sw.WriteLine("\t\tSTART(-lx / 2, -ly / 2 * y_scaling)");
            sw.WriteLine("\t\tLINE TO (-lx / 2, ly / 2 * y_scaling)");
            sw.WriteLine("\t\tLINE TO (lx / 2, ly / 2 * y_scaling)");
            sw.WriteLine("\t\tLINE TO (lx / 2, -ly / 2 * y_scaling)");
            sw.WriteLine("\t\tLINE TO CLOSE");
            sw.WriteLine();

            int count         = 2;
            int voltage_count = 0;

            for (int i = 0; i < exp.Layers.Length; i++)
            {
                if (exp.Layers[i].No_Components > 1)
                {
                    for (int j = 1; j < exp.Layers[i].No_Components; j++)
                    {
                        ILayer current_layer = exp.Layers[i].Get_Component(j);
                        if (current_layer.Geometry == Geometry_Type.triangle_slab)
                        {
                            throw new NotImplementedException("Triangles are not currently implemented...  Sorry");
                        }

                        string xmin = "-1.0 * split_length / 2";
                        string xmax = "split_length / 2";
                        string ymin = "-ly / 2";
                        string ymax = "ly / 2";
                        if (current_layer.Xmin != double.MinValue)
                        {
                            xmin = current_layer.Xmin.ToString();
                        }
                        if (current_layer.Xmax != double.MaxValue)
                        {
                            xmax = current_layer.Xmax.ToString();
                        }
                        if (current_layer.Ymin != double.MinValue)
                        {
                            ymin = current_layer.Ymin.ToString();
                        }
                        if (current_layer.Ymax != double.MaxValue)
                        {
                            ymax = current_layer.Ymax.ToString();
                        }

                        sw.WriteLine("\tLIMITED REGION " + count.ToString());
                        sw.WriteLine("\t\tSURFACE \"" + (i - 1).ToString() + "\" VALUE(u) = V" + voltage_count.ToString());
                        sw.WriteLine("\t\tSURFACE \"" + i.ToString() + "\" VALUE(u) = V" + voltage_count.ToString());
                        sw.WriteLine("\t\tLAYER \"" + i.ToString() + "\" VOID");
                        sw.WriteLine("\t\tSTART (" + xmin + ", " + ymax + " * y_scaling)");
                        sw.WriteLine("\t\tLAYER \"" + i.ToString() + "\"");
                        sw.WriteLine("\t\tVALUE(u) = V" + voltage_count.ToString());
                        sw.WriteLine("\t\tmesh_spacing = 100");
                        sw.WriteLine("\t\tLINE TO (" + xmax + ", " + ymax + " * y_scaling)");
                        sw.WriteLine("\t\tLINE TO (" + xmax + ", " + ymin + " * y_scaling) TO (" + xmin + ", " + ymin + " * y_scaling) TO CLOSE");
                        sw.WriteLine();

                        count++;
                        voltage_count++;
                    }
                }
            }

            if (voltage_count != gate_bcs.Count)
            {
                sw.Close();
                throw new Exception("Error - not enough voltages for the number of gates... see FlexPDE file...");
            }
        }