/// <summary> /// Generates a laplacian matrix in one-dimension on a regular grid with Dirichlet BCs wot varying permitivity /// </summary> DoubleTriDiagMatrix Generate_Laplacian(ILayer[] layers) { DoubleTriDiagMatrix result = new DoubleTriDiagMatrix(exp.Nz_Pot, exp.Nz_Pot); double factor_plus, factor_minus; // cycle through the structure and fill in the Laplacian with the correct permittivities for (int i = 1; i < exp.Nz_Pot - 1; i++) { double eps_plus = Geom_Tool.GetLayer(layers, i * exp.Dz_Pot + 0.5 * exp.Dz_Pot + exp.Zmin_Pot).Permitivity; double eps_minus = Geom_Tool.GetLayer(layers, i * exp.Dz_Pot - 0.5 * exp.Dz_Pot + exp.Zmin_Pot).Permitivity; // the factor which multiplies the Laplace equation factor_plus = eps_plus / (exp.Dz_Pot * exp.Dz_Pot); factor_minus = eps_minus / (exp.Dz_Pot * exp.Dz_Pot); // on-diagonal term result[i, i] = -1.0 * factor_minus + -1.0 * factor_plus; // off-diagonal result[i, i - 1] = 1.0 * factor_minus; result[i, i + 1] = 1.0 * factor_plus; } // and fix boundary conditions double factor = Geom_Tool.GetLayer(layers, exp.Zmin_Pot).Permitivity / (exp.Dz_Pot * exp.Dz_Pot); result[0, 0] = 1.0 * factor; result[0, 1] = 0.0; factor = Geom_Tool.GetLayer(layers, (exp.Nz_Pot - 1) * exp.Dz_Pot + exp.Zmin_Pot).Permitivity / (exp.Dz_Pot * exp.Dz_Pot); result[exp.Nz_Pot - 1, exp.Nz_Pot - 1] = 1.0 * factor; result[exp.Nz_Pot - 1, exp.Nz_Pot - 2] = 0.0; 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 OneD_PoissonSolver(Experiment exp, bool using_external_code, Dictionary<string, object> input) : base(using_external_code) { this.exp = exp; // generate Laplacian matrix (spin-resolved) if (!using_external_code) { laplacian = Generate_Laplacian(exp.Layers); lu_fact = new DoubleTriDiagFact(laplacian); } }
public OneD_PoissonSolver(Experiment exp, bool using_external_code, Dictionary <string, object> input) : base(using_external_code) { this.exp = exp; // generate Laplacian matrix (spin-resolved) if (!using_external_code) { laplacian = Generate_Laplacian(exp.Layers); lu_fact = new DoubleTriDiagFact(laplacian); } }
/// <summary> /// Generates a laplacian matrix in one-dimension on a regular grid with Dirichlet BCs wot varying permitivity /// </summary> DoubleTriDiagMatrix Generate_Laplacian(ILayer[] layers) { DoubleTriDiagMatrix result = new DoubleTriDiagMatrix(exp.Nz_Pot, exp.Nz_Pot); double factor_plus, factor_minus; // cycle through the structure and fill in the Laplacian with the correct permittivities for (int i = 1; i < exp.Nz_Pot - 1; i++) { double eps_plus = Geom_Tool.GetLayer(layers, i * exp.Dz_Pot + 0.5 * exp.Dz_Pot + exp.Zmin_Pot).Permitivity; double eps_minus = Geom_Tool.GetLayer(layers, i * exp.Dz_Pot - 0.5 * exp.Dz_Pot + exp.Zmin_Pot).Permitivity; // the factor which multiplies the Laplace equation factor_plus = eps_plus / (exp.Dz_Pot * exp.Dz_Pot); factor_minus = eps_minus / (exp.Dz_Pot * exp.Dz_Pot); // on-diagonal term result[i, i] = -1.0 * factor_minus + -1.0 * factor_plus; // off-diagonal result[i, i - 1] = 1.0 * factor_minus; result[i, i + 1] = 1.0 * factor_plus; } // and fix boundary conditions double factor = Geom_Tool.GetLayer(layers, exp.Zmin_Pot).Permitivity / (exp.Dz_Pot * exp.Dz_Pot); result[0, 0] = 1.0 * factor; result[0, 1] = 0.0; factor = Geom_Tool.GetLayer(layers, (exp.Nz_Pot - 1) * exp.Dz_Pot + exp.Zmin_Pot).Permitivity / (exp.Dz_Pot * exp.Dz_Pot); result[exp.Nz_Pot - 1, exp.Nz_Pot - 1] = 1.0 * factor; result[exp.Nz_Pot - 1, exp.Nz_Pot - 2] = 0.0; return result; }
// 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))); }