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; }
public Band_Data Get_XC_Potential(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(nx, 0.0); for (int i = 0; i < nx; i++) { result.vec[i] = Get_XC_Potential(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(nx, ny, 0.0); for (int i = 0; i < nx; i++) { for (int j = 0; j < ny; j++) { result.mat[i, j] = Get_XC_Potential(charge_dens_spin_summed.mat[i, j]); } } return(result); } else if (dim == 3) { int nx = charge_dens_spin_summed.vol[0].Rows; int ny = charge_dens_spin_summed.vol[0].Cols; int nz = charge_dens_spin_summed.vol.Length; 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] = Get_XC_Potential(charge_dens_spin_summed.vol[k][i, j]); } } } return(result); } else { throw new NotImplementedException(); } }
public Band_Data DFT_diff(SpinResolved_Data car_dens) { if (alpha_dft == 0.0) { return(0.0 * dft_pot); } else { return(dft_pot - Get_XC_Potential(car_dens)); } }
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 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 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(); } }
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 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 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 void Initialise_DataClasses(Dictionary<string, object> input_dict) { if (initialise_from_restart) { // initialise data classes for the density and chemical potential this.carrier_charge_density = new SpinResolved_Data(nz_dens); this.dopent_charge_density = new SpinResolved_Data(nz_dens); this.chem_pot = new Band_Data(nz_dens, 0.0); Initialise_from_Restart(input_dict); // and instantiate their derivatives carrier_charge_density_deriv = new SpinResolved_Data(nz_dens); dopent_charge_density_deriv = new SpinResolved_Data(nz_dens); chem_pot.Laplacian = pois_solv.Calculate_Phi_Laplacian(chem_pot); return; } else if (hot_start) { Initialise_from_Hot_Start(input_dict); } // try to get and the carrier and dopent density from the dictionary... they probably won't be there and if not... make them if (input_dict.ContainsKey("Carrier_Density")) this.carrier_charge_density = (SpinResolved_Data)input_dict["Carrier_Density"]; else this.carrier_charge_density = new SpinResolved_Data(nz_pot); if (input_dict.ContainsKey("Dopent_Density")) this.dopent_charge_density = (SpinResolved_Data)input_dict["Dopent_Density"]; else this.dopent_charge_density = new SpinResolved_Data(nz_pot); // and instantiate their derivatives carrier_charge_density_deriv = new SpinResolved_Data(nz_pot); dopent_charge_density_deriv = new SpinResolved_Data(nz_pot); // and finally, try to get the chemical potential from the dictionary... if (input_dict.ContainsKey("Chemical_Potential")) this.chem_pot = (Band_Data)input_dict["Chemical_Potential"]; }
public void Write_Out_Density(SpinResolved_Data h, string outfile) { Band_Data h_spin_summed = h.Spin_Summed_Data; System.IO.StreamWriter sw = new System.IO.StreamWriter(outfile); for (int i = 0; i < h_spin_summed.mat.Cols; i++) for (int j = 0; j < h_spin_summed.mat.Rows; j++) { sw.Write(h_spin_summed.mat[j, i].ToString() + '\t'); if (j == h_spin_summed.mat.Rows - 1) sw.WriteLine(); } sw.Close(); }
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 override Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi) { Save_Data(gphi, gphi_filename); Save_Data(rho_prime.Spin_Summed_Data, densderiv_filename); Create_NewtonStep_File(top_length, split_width, split_length, flexpde_script, T); return Get_Data_From_External(newton_location, flexpde_options, newton_result_filename); }
public void Update_DFT_Potential(SpinResolved_Data car_dens) { // set the dft potential for the electrons and holes separately // NOTE!!!!! V_xc is set using the total carrier density so its value includes the density due to electrons // this is a bug, but shouldn't be a problem as there should be no chance of getting holes where there are electrons and vice versa electron_dens_calc.Update_DFT_Potential(car_dens); hole_dens_calc.Update_DFT_Potential(car_dens); }
public void Output(SpinResolved_Data data, string filename) { throw new NotImplementedException(); }
/// <summary> /// calculates an optimal t based on bisection /// </summary> /// <param name="t"></param> /// <param name="phi"></param> /// <param name="x"></param> /// <param name="car_dens"></param> /// <param name="dop_dens"></param> /// <param name="pois_solv"></param> /// <param name="dens_solv"></param> /// <returns></returns> protected double Calculate_optimal_t(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 minval) { double maxval = 3.0; SpinResolved_Data car_dens_copy = car_dens.DeepenThisCopy(); SpinResolved_Data dop_dens_copy = dop_dens.DeepenThisCopy(); double vpa = calc_vp(t, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv); double vpb = calc_vp(div_fact * t, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv); double t_orig = t; // work out whether this is going in the right direction (assuming vp is monotonic) if (Math.Abs(vpb) < Math.Abs(vpa)) { // if 0.5 * t was going downhill, first, halve t seeing as you've already done this step t = div_fact * t; // then halve the damping parameter and check whether you've found a root yet while (Math.Sign(vpb) == Math.Sign(vpa)) { t = div_fact * t; if (t < minval) { if (Math.Sign(calc_vp(1.0, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv)) == Math.Sign(vpb)) { return(0.5); } //return 1.0 / div_fact; else { return(Calculate_optimal_t(1.0, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv, minval)); } } vpa = vpb; vpb = calc_vp(t, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv); } //return 0.5 * (1.0 + (1.0 / div_fact)) * t; return(t - t * (1.0 - 1.0 / div_fact) * vpb / (vpa - vpb)); } else { // if 0.5 * t was going uphill, then we need to be doubling t and looking for the root while (Math.Sign(vpb) == Math.Sign(vpa)) { t = (1.0 / div_fact) * t; if (t > maxval) { return(maxval); } vpa = vpb; vpb = calc_vp(t, phi, x, car_dens_copy, dop_dens_copy, pois_solv, dens_solv); } //return 0.5 * (1.0 + div_fact) * t; return(t - t * (1.0 - div_fact) * vpb / (vpb - vpa)); } }
/// <summary> /// returns an eigenvector decomposition for the xy-plane after having calculated the density in the /// z-direction and storing it in "charge_density" /// </summary> private double[,] Solve_Eigenvector_Problem(Band_Data dft_pot, ref SpinResolved_Data charge_density) { DoubleHermitianEigDecomp eig_decomp; double[,] xy_energy = new double[nx, ny]; Band_Data dens_up = new Band_Data(nx, ny, nz, 0.0); Band_Data dens_down = new Band_Data(nx, ny, nz, 0.0); // cycle over xy-plane calculating the ground state energy and eigenstate in the growth direction for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) { // pull out the chemical potential for this slice double[] z_dft_pot = new double[nz]; for (int k = 0; k < nz; k++) z_dft_pot[k] = dft_pot.vol[k][i, j]; // calculate its eigendecomposition DoubleHermitianMatrix h_z = Create_Hamiltonian(z_dft_pot, tz, nz); eig_decomp = new DoubleHermitianEigDecomp(h_z); // insert the eigenstate into density and record the local confinement energy xy_energy[i, j] = eig_decomp.EigenValue(0); for (int k = 0; k < nz; k++) { double dens_tot = DoubleComplex.Norm(eig_decomp.EigenVector(0)[k]) * DoubleComplex.Norm(eig_decomp.EigenVector(0)[k]); dens_up.vol[k][i, j] = 0.5 * dens_tot; dens_down.vol[k][i, j] = 0.5 * dens_tot; } } // put the calculated densities into charge_density charge_density = new SpinResolved_Data(dens_up, dens_down); return xy_energy; }
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 = new double[nx, ny]; xy_energy = 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_xy = new double[nx, ny]; // and generate a density for the y-direction for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) for (int k = 0; k < max_wavefunction; k++) dens_xy[i, j] += DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * DoubleComplex.Norm(eig_decomp.EigenVector(k)[i * ny + j]) * Get_Fermi_Function(energies[k]); */ IExperiment exp_green; exp_green = new Iterative_Greens_Function_Test.Experiment(); Iterative_Greens_Function_Test.Iterative_Greens_Function iter = new Iterative_Greens_Function_Test.Iterative_Greens_Function(exp_green, xy_energy); double[,] dens_xy = new double[nx, ny]; double max_energy = Physics_Base.kB * temperature * no_kb_T; DoubleMatrix xy_energy_mat = new DoubleMatrix(xy_energy); double min_energy = xy_energy_mat.Min(); double dE = 0.1; //double min_energy = -1.0 * max_energy; int n_slices = (int)((max_energy - min_energy) / dE); for (int n = 1; n < n_slices-1; n++) { double energy = min_energy + n * dE; double[,] dens_per_E = iter.GetDoS(energy); double fermi_func = Get_Fermi_Function(energy); for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) { dens_xy[i, j] += dens_per_E[i,j] * fermi_func; } } //double fermi_fact_max = Math.Exp(max_energy / (Physics_Base.kB * temperature)) + 1; //double fermi_fact_min = 2.0; double[,] dens_per_E_max = iter.GetDoS(max_energy); double[,] dens_per_E_min = iter.GetDoS(min_energy); double fermi_func_max = Get_Fermi_Function(max_energy); double fermi_func_min = Get_Fermi_Function(min_energy); for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) { dens_xy[i, j] += 0.5*(dens_per_E_max[i, j] * fermi_func_max + dens_per_E_min[i,j] * fermi_func_min); } // 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] *= dens_xy[i, j]; charge_density.Spin_Down.vol[k][i, j] *= dens_xy[i, j]; } // and multiply the density by -e to get the charge density (as these are electrons) charge_density = unit_charge * charge_density; }
public abstract SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_charge_density, SpinResolved_Data dopent_charge_density, Band_Data chem_pot);
public void Print_DFT_diff(SpinResolved_Data car_dens) { Console.WriteLine("Maximum absolute difference in DFT potentials = " + DFT_diff(car_dens).InfinityNorm().ToString("F6")); }
public override void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot) { throw new NotImplementedException(); }
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; }
public abstract void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot);
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);
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); double[,] xy_energy = Solve_Eigenvector_Problem(dft_pot, ref charge_density_deriv); 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_deriv.Spin_Up.vol[k][i, j] *= g_2d * Get_Fermi_Function(xy_energy[i, j]); charge_density_deriv.Spin_Down.vol[k][i, j] *= g_2d * Get_Fermi_Function(xy_energy[i, j]); } // 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 Band_Data Get_XC_Potential_Deriv(SpinResolved_Data charge_density) { throw new NotImplementedException(); }
/// <summary> /// for this method, it is assumed that the dopent density is frozen out (and therefore not altered) unless overriden /// </summary> public virtual void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data carrier_charge_density, ref SpinResolved_Data dopent_charge_density, Band_Data chem_pot) { Get_ChargeDensity(layers, ref carrier_charge_density, chem_pot); }
public void Print_DFT_diff(SpinResolved_Data car_dens) { }
public override void Get_ChargeDensity_Deriv(ILayer[] layers, ref SpinResolved_Data charge_density_deriv, Band_Data chem_pot) { Get_SOI_parameters(chem_pot); // if (dV_x == null) // throw new Exception("Error - Band structure derivatives are null! Have you initiated this type properly by calling Get_SOI_parameters(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); // reset charge density charge_density_deriv = 0.0 * charge_density_deriv; // integrate up density from k = 0 to k = k_F int count = 0; double k = 0; // create initial hamiltonian and eigendecomposition int max_wavefunction_old_p, max_wavefunction_old_m; DoubleHermitianMatrix hamiltonian_p = Create_H_Using_SOIP(dft_pot, k); DoubleHermitianEigDecomp eig_decomp_old_p = Diagonalise_Hamiltonian(hamiltonian_p, out max_wavefunction_old_p); DoubleHermitianEigDecomp eig_decomp_old_m = Diagonalise_Hamiltonian(hamiltonian_p, out max_wavefunction_old_m); while (k < kmax) { // increment the wavevector k += delta_k; count += 1; // create new decompositions for forwards and backwards analysis int max_wavefunction_p, max_wavefunction_m; DoubleHermitianEigDecomp eig_decomp_p = Diagonalise_Hamiltonian(Create_H_Using_SOIP(dft_pot, k), out max_wavefunction_p); DoubleHermitianEigDecomp eig_decomp_m = Diagonalise_Hamiltonian(Create_H_Using_SOIP(dft_pot, -1.0 * k), out max_wavefunction_m); SpinResolved_Data new_charge_deriv = new SpinResolved_Data(nx, ny); // cycle over each of the positive bands for (int i = 0; i < max_wavefunction_p; i++) new_charge_deriv += Calculate_Density_Derivative(eig_decomp_old_p, eig_decomp_p, i); // and negative bands for (int i = 0; i < max_wavefunction_m; i++) new_charge_deriv += Calculate_Density_Derivative(eig_decomp_old_m, eig_decomp_m, i); // set new eigenvalue decompositions and max_wavefunctions to the old ones eig_decomp_old_m = eig_decomp_m; eig_decomp_old_p = eig_decomp_p; max_wavefunction_old_m = max_wavefunction_m; max_wavefunction_old_p = max_wavefunction_p; // and finally, add the charge density calculated charge_density_deriv += new_charge_deriv; } }
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)); }
bool Check_Integration_Convergence(SpinResolved_Data density_k, double eps) { // checks whether the maximum (negative) density is less than eps double max_dens = 0.0; for (int i = 0; i < nx; i++) for (int j = 0; j < ny; j++) if (density_k.Spin_Up.mat[i, j] + density_k.Spin_Down.mat[i, j] < max_dens) max_dens = density_k.Spin_Up.mat[i, j] + density_k.Spin_Down.mat[i, j]; return eps > -1.0 * max_dens; }
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(); }
public Band_Data DFT_diff(SpinResolved_Data car_dens) { throw new NotImplementedException(); }
/// <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 Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data charge_density, Band_Data chem_pot) { SpinResolved_Data electron_density = charge_density.DeepenThisCopy(); SpinResolved_Data hole_density = charge_density.DeepenThisCopy(); // remove the electron density from the hole density SpinResolved_Data and vice versa for (int i = 0; i < electron_density.Spin_Summed_Data.Length; i++ ) { if (electron_density.Spin_Summed_Data.vec[i] > 0.0) { electron_density.Spin_Up[i] = 0.0; electron_density.Spin_Down[i] = 0.0; } if (hole_density.Spin_Summed_Data.vec[i] < 0.0) { hole_density.Spin_Up[i] = 0.0; hole_density.Spin_Down[i] = 0.0; } } electron_dens_calc.Get_ChargeDensity(layers, ref electron_density, chem_pot); hole_dens_calc.Get_ChargeDensity(layers, ref hole_density, chem_pot); charge_density = electron_density + hole_density; }
/// <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; }
public SpinResolved_Data Get_ChargeDensity(ILayer[] layers, SpinResolved_Data carrier_charge_density, SpinResolved_Data dopent_charge_density, Band_Data chem_pot) { SpinResolved_Data electron_density = carrier_charge_density.DeepenThisCopy(); SpinResolved_Data hole_density = carrier_charge_density.DeepenThisCopy(); // remove the electron density from the hole density SpinResolved_Data and vice versa for (int i = 0; i < electron_density.Spin_Summed_Data.Length; i++) { if (electron_density.Spin_Summed_Data.vec[i] > 0.0) { electron_density.Spin_Up[i] = 0.0; electron_density.Spin_Down[i] = 0.0; } if (hole_density.Spin_Summed_Data.vec[i] < 0.0) { hole_density.Spin_Up[i] = 0.0; hole_density.Spin_Down[i] = 0.0; } } // must remove one lot of dopents due to double counting return electron_dens_calc.Get_ChargeDensity(layers, electron_density, dopent_charge_density, chem_pot) + hole_dens_calc.Get_ChargeDensity(layers, hole_density, dopent_charge_density, chem_pot) - dopent_charge_density; }
public void Output(SpinResolved_Data data, string filename) { Output(data, filename, true); }
/// <summary> /// for this method, it is assumed that the dopent density is frozen out (and therefore not altered) unless overriden /// </summary> public void Get_ChargeDensity(ILayer[] layers, ref SpinResolved_Data carrier_charge_density, ref SpinResolved_Data dopent_charge_density, Band_Data chem_pot) { Get_ChargeDensity(layers, ref carrier_charge_density, 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 SpinResolved_Data Get_ChargeDensity_Deriv(ILayer[] layers, SpinResolved_Data carrier_density_deriv, SpinResolved_Data dopent_density_deriv, Band_Data chem_pot) { SpinResolved_Data electron_density_deriv = carrier_density_deriv.DeepenThisCopy(); SpinResolved_Data hole_density_deriv = carrier_density_deriv.DeepenThisCopy(); // remove the electron density from the hole density SpinResolved_Data and vice versa for (int i = 0; i < electron_density_deriv.Spin_Summed_Data.Length; i++) { if (electron_density_deriv.Spin_Summed_Data.vec[i] > 0.0) { electron_density_deriv.Spin_Up[i] = 0.0; electron_density_deriv.Spin_Down[i] = 0.0; } if (hole_density_deriv.Spin_Summed_Data.vec[i] < 0.0) { hole_density_deriv.Spin_Up[i] = 0.0; hole_density_deriv.Spin_Down[i] = 0.0; } } return electron_dens_calc.Get_ChargeDensity_Deriv(layers, electron_density_deriv, dopent_density_deriv, chem_pot) + hole_dens_calc.Get_ChargeDensity_Deriv(layers, hole_density_deriv, dopent_density_deriv, chem_pot); }
public abstract Band_Data Calculate_Newton_Step(SpinResolved_Data rho_prime, Band_Data gphi);
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(); }