public override SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_density_deriv, SpinResolved_Data dopent_density_deriv, Band_Data chem_pot) { for (int i = 0; i < nz; i++) { double z = dz * i + zmin; // get the relevant layer and if it's frozen out, don't recalculate the dopent charge ILayer current_Layer = Solver_Bases.Geometry.Geom_Tool.GetLayer(layers, z); ZeroD_Density charge_calc = new ZeroD_Density(current_Layer, temperature); if (!current_Layer.Dopents_Frozen_Out(temperature)) { double local_dopent_density_deriv = charge_calc.Get_DopentDensityDeriv(chem_pot.vec[i]); dopent_density_deriv.Spin_Up.vec[i] = 0.5 * local_dopent_density_deriv; dopent_density_deriv.Spin_Down.vec[i] = 0.5 * local_dopent_density_deriv; } else { dopent_density_deriv.Spin_Up.vec[i] = 0.0; dopent_density_deriv.Spin_Down.vec[i] = 0.0; } carrier_density_deriv.Spin_Up.vec[i] = 0.5 * charge_calc.Get_CarrierDensityDeriv(chem_pot.vec[i]); carrier_density_deriv.Spin_Down.vec[i] = 0.5 * charge_calc.Get_CarrierDensityDeriv(chem_pot.vec[i]); } return carrier_density_deriv + dopent_density_deriv; }
void Print_VP(Band_Data band_energy, Band_Data x, SpinResolved_Data car_dens, SpinResolved_Data dop_dens, IPoisson_Solve pois_solv, IDensity_Solve dens_solv) { StreamWriter sw = new StreamWriter("vp"); int count_max = 100; double dt = 0.01; for (int i = 0; i < count_max; i++) { sw.WriteLine(calc_vp(i * dt, band_energy, x, car_dens, dop_dens, pois_solv, dens_solv).ToString()); } sw.Close(); }
public void Update_DFT_Potential(SpinResolved_Data car_dens) { if (this.dft_pot == null && alpha_dft != 0.0) { this.dft_pot = Get_XC_Potential(car_dens); } else if (alpha_dft == 0.0) { this.dft_pot = 0.0 * car_dens.Spin_Summed_Data.DeepenThisCopy(); } else { this.dft_pot = (1.0 - alpha_dft) * dft_pot + alpha_dft * Get_XC_Potential(car_dens); } }
protected virtual double calc_vp(double t, Band_Data phi, Band_Data x, SpinResolved_Data car_dens, SpinResolved_Data dop_dens, IPoisson_Solve pois_solv, IDensity_Solve dens_solv) { double vp; SpinResolved_Data tmp_dens = dens_solv.Get_ChargeDensity(layers, car_dens, dop_dens, Physics_Base.q_e * (phi + t * x)); Band_Data V_Prime = -1.0 * (phi.Laplacian + t * x.Laplacian) - tmp_dens.Spin_Summed_Data; vp = 0.0; for (int i = 0; i < x.Length; i++) { vp += V_Prime[i] * x[i]; } // multiply by volume element (this works in all dimensions as default dx, dy, dz are 1.0) return(vp * dx_dens * dy_dens * dz_dens); }
public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data density, Band_Data chem_pot) { // send data to client NetworkComms.SendObject("layers", clientIP, clientPort, layers); NetworkComms.SendObject("density", clientIP, clientPort, density); NetworkComms.SendObject("chem_pot", clientIP, clientPort, chem_pot); // Call the save_density routine //NetworkComms.AppendGlobalIncomingPacketHandler<SpinResolved_Data>("new_density", Save_Density); //Start listening for incoming connections TCPConnection.StartListening(true); //Print out the IPs and ports we are now listening on Console.WriteLine("Server listening for TCP connection on:"); foreach (System.Net.IPEndPoint localEndPoint in TCPConnection.ExistingLocalListenEndPoints()) Console.WriteLine("{0}:{1}", localEndPoint.Address, localEndPoint.Port); throw new NotImplementedException(); }
public static Band_Data Parse_Band_Data(string location, string[] input_data, int nz) { // and check that there is the right number of data points back if (input_data.Length != nz) { throw new Exception("Error - FlexPDE is outputting the wrong number of potential data points"); } // and parse these values into a DoubleVector Band_Data result = new Band_Data(new DoubleVector(nz)); for (int i = 0; i < nz; i++) { result.vec[i] = double.Parse(input_data[i]); } result.value_location = location; return(result); }
public void Output(SpinResolved_Data data, string filename, bool with_warnings) { StreamWriter sw = new StreamWriter(filename); if (with_warnings) { sw.WriteLine("Warning - The data has been written out serially and there is no information as to which order the dimensions come in."); sw.WriteLine("Warning - Ordering compared to Band_Data objects is not guaranteed!"); } // output the charge density Band_Data tot_charge = data.Spin_Summed_Data; for (int i = 0; i < tot_charge.Length; i++) { sw.WriteLine(tot_charge[i].ToString()); } sw.Close(); }
public double Renew_Mixing_Parameter(Band_Data band_energy, Band_Data new_band_energy, double alpha_min, double alpha) { double[] energy_diff = Get_Array_of_Absolute_Differences(band_energy, new_band_energy); // the new mixing factor is the maximum absolute change, multiplied by the original mixing factor double new_mixing_parameter = alpha_min / energy_diff.Max(); if (new_mixing_parameter > alpha_min && new_mixing_parameter < 0.01) { return(new_mixing_parameter); } else if (new_mixing_parameter > 0.01) { return(0.01); } else { return(alpha_min); } }
public Band_Data Get_XC_Potential_Deriv(SpinResolved_Data charge_density) { Band_Data result; Band_Data charge_dens_spin_summed = charge_density.Spin_Summed_Data; int dim = charge_dens_spin_summed.Dimension; if (dim == 1) { int nx = charge_dens_spin_summed.vec.Length; result = new Band_Data(new DoubleVector(nx)); for (int i = 0; i < nx; i++) { result.vec[i] = Get_XC_Potential_Deriv(charge_dens_spin_summed.vec[i]); } return(result); } else if (dim == 2) { int nx = charge_dens_spin_summed.mat.Rows; int ny = charge_dens_spin_summed.mat.Cols; result = new Band_Data(new DoubleMatrix(nx, ny)); for (int i = 0; i < nx; i++) { for (int j = 0; j < ny; j++) { result.mat[i, j] = Get_XC_Potential_Deriv(charge_dens_spin_summed.mat[i, j]); } } return(result); } else if (dim == 3) { throw new NotImplementedException(); } else { throw new NotImplementedException(); } }
void Print_Data(Band_Data x, Band_Data v) { StreamWriter swx = new StreamWriter("x_prt.dat"); StreamWriter swv = new StreamWriter("v_prt.dat"); for (int i = 0; i < v.mat.Rows; i++) { for (int j = 0; j < v.mat.Cols; j++) { swx.Write(x.mat[i, j].ToString() + '\t'); swv.Write(v.mat[i, j].ToString() + '\t'); if (j == v.mat.Cols - 1) { swv.WriteLine(); swx.WriteLine(); } } } swx.Close(); swv.Close(); }
public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot) { // convert the chemical potential into a quantum mechanical potential Band_Data dft_pot = chem_pot.DeepenThisCopy(); Get_Potential(ref dft_pot, layers); double[,] xy_energy = Solve_Eigenvector_Problem(dft_pot, ref charge_density); double beta = 1.0 / (Physics_Base.kB * temperature); // multiply the z-densities by the xy-density for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) for (int k = 0; k < nz; k++) { charge_density.Spin_Up.vol[k][i, j] *= g_2d * Math.Log(1.0 + Math.Exp(-1.0 * beta * xy_energy[i, j])) / beta; charge_density.Spin_Down.vol[k][i, j] *= g_2d * Math.Log(1.0 + Math.Exp(-1.0 * beta * xy_energy[i, j])) / beta; } // and multiply the density by -e to get the charge density (as these are electrons) charge_density = unit_charge * charge_density; }
public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data density, Band_Data chem_pot) { for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) for (int k = 0; k < nz; k++) { double x = dx * i + xmin; double y = dy * j + ymin; double z = dz * k + zmin; // get the relevant layer ILayer current_Layer = Solver_Bases.Geometry.Geom_Tool.GetLayer(layers, x, y, z); // calculate the density at the given point ZeroD_Density charge_calc = new ZeroD_Density(current_Layer, temperature); double local_charge_density = charge_calc.Get_CarrierDensity(chem_pot.vol[k][i, j]); // as there is no spin dependence in this problem yet, just divide the charge into spin-up and spin-down components equally density.Spin_Down.vol[k][i, j] = 0.5 * local_charge_density; density.Spin_Up.vol[k][i, j] = 0.5 * local_charge_density; } }
public static Band_Data operator -(Band_Data vec1, Band_Data vec2) { Band_Data result; // return null if both of the inputs are null if (vec1 == null || vec2 == null) { return(null); } if (vec1.Dimension != vec2.Dimension) { throw new RankException(); } if (vec1.Dimension == 1) { result = new Band_Data(vec1.vec - vec2.vec); } else if (vec1.Dimension == 2) { result = new Band_Data(vec1.mat - vec2.mat); } else if (vec1.Dimension == 3) { result = new Band_Data(new DoubleMatrix[vec1.vol.Length]); for (int i = 0; i < vec1.vol.Length; i++) { result.vol[i] = vec1.vol[i] - vec2.vol[i]; } } else { throw new NotImplementedException(); } result.Laplacian = vec1.Laplacian - vec2.Laplacian; return(result); }
public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data carrier_density, ref SpinResolved_Data dopent_density, Band_Data chem_pot) { Band_Data car_dens_spin_summed = carrier_density.Spin_Summed_Data; Band_Data dop_dens_spin_summed = dopent_density.Spin_Summed_Data; for (int i = 0; i < nz; i++) { double z = dz * i + zmin; double local_dopent_density; double local_carrier_density = car_dens_spin_summed.vec[i]; // get the relevant layer and if it's frozen out, don't recalculate the charge ILayer current_Layer = Solver_Bases.Geometry.Geom_Tool.GetLayer(layers, z); // calculate the density at the given point ZeroD_Density charge_calc = new ZeroD_Density(current_Layer, temperature); if (!current_Layer.Dopents_Frozen_Out(temperature)) { local_dopent_density = charge_calc.Get_DopentDensity(chem_pot.vec[i]); local_carrier_density = charge_calc.Get_CarrierDensity(chem_pot.vec[i]); } else { // if the density is frozen out, on the first step, this will add the carrier density to the dopent density // to give a total, frozen-out charge. After that, the local carrier density is set to zero and so this value // should not change local_dopent_density = dop_dens_spin_summed.vec[i]; local_carrier_density = charge_calc.Get_CarrierDensity(chem_pot.vec[i]); } // as there is no spin dependence in this problem yet, just divide the charge into spin-up and spin-down components equally dopent_density.Spin_Down.vec[i] = 0.5 * local_dopent_density; dopent_density.Spin_Up.vec[i] = 0.5 * local_dopent_density; carrier_density.Spin_Down.vec[i] = 0.5 * local_carrier_density; carrier_density.Spin_Up.vec[i] = 0.5 * local_carrier_density; } }
public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot) { // convert the chemical potential into a quantum mechanical potential Band_Data dft_pot = chem_pot.DeepenThisCopy(); Get_Potential(ref dft_pot, layers); DoubleHermitianEigDecomp eig_decomp = Solve_Eigenvector_Problem(dft_pot, ref charge_density); int max_wavefunction = (from val in eig_decomp.EigenValues where val < no_kb_T * Physics_Base.kB * temperature select val).ToArray().Length; double[] dens_x = new double[nx]; // and generate a density for the y-direction for (int i = 0; i < nx; i++) for (int k = 0; k < max_wavefunction; k++) dens_x[i] += DoubleComplex.Norm(eig_decomp.EigenVector(k)[i]) * DoubleComplex.Norm(eig_decomp.EigenVector(k)[i]) * Get_OneD_DoS(energies[k], no_kb_T); // multiply the z-densities by the y-density for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) { // do not add anything to the density if on the edge of the domain if (i == 0 || i == nx - 1 || j == 0 || j == ny - 1) { charge_density.Spin_Up.mat[i, j] *= 0.0; charge_density.Spin_Down.mat[i, j] *= 0.0; } charge_density.Spin_Up.mat[i, j] *= dens_x[i]; charge_density.Spin_Down.mat[i, j] *= dens_x[i]; } // and multiply the density by -e to get the charge density (as these are electrons) charge_density = unit_charge * charge_density; }
public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data density, Band_Data chem_pot) { for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) { // do not add anything to the density if on the edge of the domain if (i == 0 || i == nx - 1 || j == 0 || j == ny - 1) continue; double x = dx * i + xmin; double y = dy * j + ymin; // get the relevant layer ILayer current_Layer = Solver_Bases.Geometry.Geom_Tool.GetLayer(layers, plane, x, y, pos_z); // calculate the density at the given point ZeroD_Density charge_calc = new ZeroD_Density(current_Layer, temperature); double local_charge_density = charge_calc.Get_CarrierDensity(chem_pot.mat[i, j]); // as there is no spin dependence in this problem yet, just divide the charge into spin-up and spin-down components equally density.Spin_Down.mat[i, j] = 0.5 * local_charge_density; density.Spin_Up.mat[i, j] = 0.5 * local_charge_density; } }
protected override Band_Data Get_Pot_From_External(Band_Data density) { Save_Data(density, dens_filename); pot = Get_Data_From_External(initcalc_location, "-p " + initcalc_parameterfile, initcalc_result_filename); return pot; }
public override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi) { Save_Data(rho_prime.Spin_Summed_Data, densderiv_filename); Save_Data(gphi, gphi_filename); Band_Data x = Get_Data_From_External(newton_location, "-p " + newton_parameterfile, newton_result_filename); return x; }
/// <summary> /// Calculate the charge density for this potential /// NOTE!!! that the boundary potential is (essentially) set to infty by ringing the density with a set of zeros. /// this prevents potential solvers from extrapolating any residual density at the edge of the eigenstate /// solution out of the charge density calculation domain /// </summary> /// <param name="layers"></param> /// <param name="charge_density"></param> /// <param name="chem_pot"></param> public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot) { // convert the chemical potential into a quantum mechanical potential Band_Data dft_pot = chem_pot.DeepenThisCopy(); Get_Potential(ref dft_pot, layers); DoubleHermitianMatrix hamiltonian = Create_Hamiltonian(layers, dft_pot); DoubleHermitianEigDecompServer eig_server = new DoubleHermitianEigDecompServer(); eig_server.ComputeEigenValueRange(dft_pot.mat.Min(), no_kb_T * Physics_Base.kB * temperature); eig_server.ComputeVectors = true; DoubleHermitianEigDecomp eig_decomp = eig_server.Factor(hamiltonian); int max_wavefunction = 0; if (eig_decomp.EigenValues.Length != 0) { double min_eigval = eig_decomp.EigenValues.Min(); max_wavefunction = (from val in eig_decomp.EigenValues where val < no_kb_T * Physics_Base.kB * temperature select val).ToArray().Length; } for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) { double dens_val = 0.0; // do not add anything to the density if on the edge of the domain if (i == 0 || i == nx - 1 || j == 0 || j == ny - 1) { charge_density.Spin_Up.mat[i, j] = 0.0; charge_density.Spin_Down.mat[i, j] = 0.0; continue; } for (int k = 0; k < max_wavefunction; k++) { // and integrate the density of states at this position for this eigenvector from the minimum energy to // (by default) 50 * k_b * T above mu = 0 dens_val += DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * Get_OneD_DoS(eig_decomp.EigenValue(k), no_kb_T); } // just share the densities (there is no spin polarisation) charge_density.Spin_Up.mat[i, j] = 0.5 * dens_val; charge_density.Spin_Down.mat[i, j] = 0.5 * dens_val; } // and multiply the density by -e to get the charge density (as these are electrons) charge_density = unit_charge * charge_density; }
/// <summary> /// returns the eigen-energies for the given potential and charge density /// </summary> public override DoubleVector Get_EnergyLevels(ILayer[] layers, Band_Data pot) { // convert the chemical potential into a quantum mechanical potential Band_Data band_pot = pot.DeepenThisCopy(); Get_Potential(ref band_pot, layers); DoubleHermitianMatrix hamiltonian = Create_Hamiltonian(layers, band_pot); DoubleHermitianEigDecomp eig_decomp = new DoubleHermitianEigDecomp(hamiltonian); return eig_decomp.EigenValues; }
protected string Generate_Output_String(int count, Band_Data x, Band_Data dens_diff) { string output_string = "Iter = " + count.ToString() + "\tDens = " + dens_diff.Max().ToString("F4") + "\tPot = " + (Physics_Base.q_e * x.InfinityNorm()).ToString("F6") + "\tt = " + t.ToString("F6"); return(output_string); }
public static Band_Data operator *(double scalar, Band_Data data) { Band_Data result; // return null if the inputs is null if (data == null) return null; if (data.Dimension == 1) result = new Band_Data(scalar * data.vec); else if (data.Dimension == 2) result = new Band_Data(scalar * data.mat); else if (data.Dimension == 3) { result = new Band_Data(new DoubleMatrix[data.vol.Length]); for (int i = 0; i < data.vol.Length; i++) result.vol[i] = scalar * data.vol[i]; } else throw new NotImplementedException(); result.Laplacian = scalar * data.Laplacian; return result; }
protected abstract Band_Data Get_Pot_From_External(Band_Data density);
public override SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_charge_density, SpinResolved_Data dopent_charge_density, Band_Data chem_pot) { throw new NotImplementedException(); }
public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data density, Band_Data chem_pot) { // send data to client NetworkComms.SendObject("layers", clientIP, clientPort, layers); NetworkComms.SendObject("density", clientIP, clientPort, density); NetworkComms.SendObject("chem_pot", clientIP, clientPort, chem_pot); // Call the save_density routine //NetworkComms.AppendGlobalIncomingPacketHandler<SpinResolved_Data>("new_density", Save_Density); //Start listening for incoming connections TCPConnection.StartListening(true); //Print out the IPs and ports we are now listening on Console.WriteLine("Server listening for TCP connection on:"); foreach (System.Net.IPEndPoint localEndPoint in TCPConnection.ExistingLocalListenEndPoints()) { Console.WriteLine("{0}:{1}", localEndPoint.Address, localEndPoint.Port); } throw new NotImplementedException(); }
public override DoubleVector Get_EnergyLevels(ILayer[] layers, Band_Data chem_pot) { throw new NotImplementedException(); }
public SpinResolved_Data(Band_Data spin_up, Band_Data spin_down) { spin_data = new Band_Data[2]; spin_data[0] = spin_up; spin_data[1] = spin_down; }
public SpinResolved_Data(int nx) { spin_data = new Band_Data[2]; spin_data[0] = new Band_Data(nx, 0.0); spin_data[1] = new Band_Data(nx, 0.0); }
protected override void Save_Data(Band_Data density, string input_file_name) { density.Save_Data(input_file_name); }
public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot) { throw new NotImplementedException(); }
public abstract void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot);
public override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi, SpinResolved_Data car_dens, Band_Data dft_pot, Band_Data dft_calc) { Save_Data(car_dens.Spin_Summed_Data, dens_filename); Save_Data(dft_pot, xc_pot_filename); Save_Data(dft_calc, "xc_pot_calc.dat"); return(Calculate_Newton_Step(rho_prime, gphi)); }
public abstract Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi);
protected override Band_Data Get_Pot_On_Regular_Grid(Band_Data density) { throw new NotImplementedException(); }
public static Band_Data Parse_Band_Data(string location, string[] input_data, int ny, int nz) { // and check that there is the right number of data points back if (input_data.Length != ny * nz) throw new Exception("Error - FlexPDE is outputting the wrong number of potential data points"); // and parse these values into a DoubleVector Band_Data result = new Band_Data(new DoubleMatrix(ny, nz)); for (int i = 0; i < ny; i++) { for (int j = 0; j < nz; j++) result.mat[i, j] = double.Parse(input_data[j * ny + i]); } result.value_location = location; return result; }
/// <summary> /// Calculate the charge density for this potential /// NOTE!!! that the boundary potential is (essentially) set to infty by ringing the density with a set of zeros. /// this prevents potential solvers from extrapolating any residual density at the edge of the eigenstate /// solution out of the charge density calculation domain /// </summary> /// <param name="layers"></param> /// <param name="charge_density_deriv"></param> /// <param name="chem_pot"></param> public override void Get_ChargeDensity_Deriv(ILayer[] layers, ref SpinResolved_Data charge_density_deriv, Band_Data chem_pot) { // convert the chemical potential into a quantum mechanical potential Band_Data dft_pot = chem_pot.DeepenThisCopy(); Get_Potential(ref dft_pot, layers); DoubleHermitianMatrix hamiltonian = Create_Hamiltonian(layers, dft_pot); DoubleHermitianEigDecomp eig_decomp = new DoubleHermitianEigDecomp(hamiltonian); double min_eigval = eig_decomp.EigenValues.Min(); int max_wavefunction = (from val in eig_decomp.EigenValues where val < no_kb_T * Physics_Base.kB * temperature select val).ToArray().Length; for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) { double dens_val_deriv = 0.0; // do not add anything to the density if on the edge of the domain if (i == 0 || i == nx - 1 || j == 0 || j == ny - 1) { charge_density_deriv.Spin_Up.mat[i, j] = 0.0; charge_density_deriv.Spin_Down.mat[i, j] = 0.0; continue; } for (int k = 0; k < max_wavefunction; k++) { // and integrate the density of states at this position for this eigenvector from the minimum energy to // (by default) 50 * k_b * T above mu = 0 dens_val_deriv += DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * Get_OneD_DoS_Deriv(eig_decomp.EigenValue(k), no_kb_T); } // just share the densities (there is no spin polarisation) charge_density_deriv.Spin_Up.mat[i, j] = 0.5 * dens_val_deriv; charge_density_deriv.Spin_Down.mat[i, j] = 0.5 * dens_val_deriv; } // and multiply the density derivative by e to get the charge density and by e to convert it to d/dphi (as increasing phi decreases the charge: dn/dphi*-e^2 ) charge_density_deriv = unit_charge * unit_charge * charge_density_deriv; }
public void Reset_DFT_Potential() { this.dft_pot = null; }
DoubleHermitianMatrix Create_Hamiltonian(ILayer[] layers, Band_Data pot) { DoubleHermitianMatrix result = new DoubleHermitianMatrix(nx * ny); // set off diagonal elements for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) { // coupling sites in the transverse direction if (i != 0) result[i * ny + j, i * ny + j - ny] = tx; if (i != nx - 1) result[i * ny + j, i * ny + j + ny] = tx; // coupling sites in the growth direction if (j != 0) result[i * ny + j, i * ny + j - 1] = ty; if (j != ny - 1) result[i * ny + j, i * ny + j + 1] = ty; } double[,] potential = new double[nx, ny]; // set diagonal elements for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) result[i * ny + j, i * ny + j] = -2.0 * tx + -2.0 * ty + pot.mat[i, j]; return result; }
/// <summary> /// Initiates a laplacian for this Band_Data class of the correct size /// </summary> public void Initiate_Laplacian() { this.laplacian_band_data = 0.0 * this; }
public abstract SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_charge_density, SpinResolved_Data dopent_charge_density, Band_Data chem_pot);
public Band_Data DeepenThisCopy() { Band_Data tmp_result = null; if (dim == 1) { DoubleVector result = new DoubleVector(Length); for (int i = 0; i < Length; i++) result[i] = this[i]; tmp_result = new Band_Data(result); } else if (dim == 2) { DoubleMatrix result = new DoubleMatrix(mat.Rows, mat.Cols); for (int i = 0; i < mat.Rows; i++) for (int j = 0; j < mat.Cols; j++) result[i, j] = mat[i, j]; tmp_result = new Band_Data(result); } else if (dim == 3) { int nx = vol[0].Rows; int ny = vol[0].Cols; int nz = vol.Length; Band_Data result = new Band_Data(nx, ny, nz, 0.0); for (int k = 0; k < nz; k++) for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) result.vol[k][i, j] = this.vol[k][i, j]; tmp_result = result; } else throw new NotImplementedException(); if (this.Laplacian != null) tmp_result.Laplacian = this.Laplacian.DeepenThisCopy(); return tmp_result; }
public override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi, SpinResolved_Data car_dens, Band_Data dft_pot, Band_Data dft_calc) { Save_Data(car_dens.Spin_Summed_Data, dens_filename); Save_Data(dft_pot, xc_pot_filename); Save_Data(dft_calc, "xc_pot_calc.dat"); return Calculate_Newton_Step(rho_prime, gphi); }
public abstract DoubleVector Get_EnergyLevels(ILayer[] layers, Band_Data chem_pot);
// protected override Band_Data Get_ChemPot_From_External(Band_Data density) // { // Save_Data(density, dens_filename); // // return Get_Data_From_External(flexpde_script, initcalc_result_filename); // } /// <summary> /// Calculates the Laplacian for the given band structure of the input potential /// ie. returns d(eps * d(input)) /// NOTE: the input should be a potential so make sure you divide all band energies by q_e /// </summary> public Band_Data Calculate_Phi_Laplacian(Band_Data input) { DoubleTriDiagMatrix lap_mat = Generate_Laplacian(exp.Layers); return new Band_Data(MatrixFunctions.Product(lap_mat, input.vec)); }
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"); }
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; }
public abstract Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi, SpinResolved_Data carrier_density, Band_Data dft_pot, Band_Data dft_calc);
protected override Band_Data Get_Pot_From_External(Band_Data density) { throw new NotImplementedException(); }
protected abstract Band_Data Get_Pot_On_Regular_Grid(Band_Data density);
protected override Band_Data Get_Pot_On_Regular_Grid(Band_Data charge_density) { // set the top and bottom boundary conditions where [0] is the bottom of the device charge_density.vec[0] = bottom_bc * -1.0 * bottom_eps / (exp.Dz_Pot * exp.Dz_Pot); charge_density.vec[charge_density.Length - 1] = top_bc * -1.0 * top_eps / (exp.Dz_Pot * exp.Dz_Pot); // solve Poisson's equation Band_Data potential = new Band_Data(lu_fact.Solve(-1.0 * charge_density.vec)); // and save its laplacian potential.Laplacian = Calculate_Phi_Laplacian(potential); return potential; }
protected abstract void Save_Data(Band_Data density, string input_file_name);
protected override void Save_Data(Band_Data density, string input_file_name) { density.Save_1D_Data(input_file_name, exp.Dz_Pot, exp.Zmin_Pot); }
public static Band_Data operator -(Band_Data vec1, Band_Data vec2) { Band_Data result; // return null if both of the inputs are null if (vec1 == null || vec2 == null) return null; if (vec1.Dimension != vec2.Dimension) throw new RankException(); if (vec1.Dimension == 1) result = new Band_Data(vec1.vec - vec2.vec); else if (vec1.Dimension == 2) result = new Band_Data(vec1.mat - vec2.mat); else if (vec1.Dimension == 3) { result = new Band_Data(new DoubleMatrix[vec1.vol.Length]); for (int i = 0; i < vec1.vol.Length; i++) result.vol[i] = vec1.vol[i] - vec2.vol[i]; } else throw new NotImplementedException(); result.Laplacian = vec1.Laplacian - vec2.Laplacian; return result; }
public override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data g_phi) { DoubleTriDiagMatrix lap_mat = -1.0 * Generate_Laplacian(exp.Layers); Band_Data rho_prime_spin_summed = rho_prime.Spin_Summed_Data; // check that lap_mat and rho_prime have the same dimension if (rho_prime_spin_summed.Length != lap_mat.Rows) throw new Exception("Error - the Laplacian generated by pois_solv has a different order to rho_prime!"); for (int i = 0; i < rho_prime_spin_summed.Length; i++) lap_mat[i, i] -= rho_prime_spin_summed.vec[i]; DoubleTriDiagFact lu_newt_step = new DoubleTriDiagFact(lap_mat); // calculate newton step and its laplacian Band_Data result = new Band_Data(lu_newt_step.Solve(-1.0 * g_phi.vec)); result.Laplacian = Calculate_Phi_Laplacian(result); return result; }
public static Band_Data Parse_Band_Data(string location, string[] input_data, int nx, int ny, int nz) { // and check that there is the right number of data points back if (input_data.Length != nx * ny * nz) throw new Exception("Error - FlexPDE is outputting the wrong number of potential data points"); // and parse these values into a DoubleVector Band_Data result = new Band_Data(nx, ny, nz, 0.0); for (int k = 0; k < nz; k++) for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) result.vol[k][i, j] = double.Parse(input_data[k * nx * ny + j * nx + i]); result.value_location = location; return result; }
public SpinResolved_Data(int nx, int ny, int nz) { spin_data = new Band_Data[2]; spin_data[0] = new Band_Data(nx, ny, nz, 0.0); spin_data[1] = new Band_Data(nx, ny, nz, 0.0); }
public override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi, SpinResolved_Data carrier_density, Band_Data dft_pot, Band_Data dft_calc) { throw new NotImplementedException(); }