private void Bind_Slice(int slice_no, DoubleComplexMatrix slice_to_bind) { DoubleComplexMatrix new_hopping = Generate_Hopping_Hamiltonian(); DoubleComplexMatrix new_hopping_trans = Generate_Hopping_Hamiltonian().Transpose(); DoubleComplexMatrix temp_matrix = new DoubleComplexMatrix(slice_to_bind - Product(Product(new_hopping, onsite_G[slice_no - 1]), new_hopping_trans)); // factorise the matrix DoubleComplexLUFact factorisation = new DoubleComplexLUFact(temp_matrix); // the inverse of this matrix is the onsite Green's function for the new slice onsite_G[slice_no] = factorisation.Inverse(); // the first hop from n to n + 1 uses the onsite Green's function as G_(i,n+1) = G_(i,n) H' G(n+1,n+1) and when i = n, G_(i,n) = G(i,i) // must do this here before updating the onsite Green's functions hopping_G[slice_no - 1] = onsite_G[slice_no - 1]; // update the old onsite Green's functions (not including the boundary slice) for (int i = 0; i < slice_no; i++) { onsite_G[i] = onsite_G[i] + Product(Product(Product(Product(hopping_G[i], new_hopping), onsite_G[slice_no]), new_hopping_trans), hopping_G[i].Transpose()); } // calculate the new hopping Green's functions for (int i = 0; i < slice_no; i++) { hopping_G[i] = Product(Product(hopping_G[i], new_hopping), onsite_G[slice_no]); } }
private DoubleComplexMatrix Create_New_Slice(double energy, int slice_no) { // work out where this slice is double x = (slice_no - (nx - 1) / 2) * dx; // generate the matrices for this slice DoubleComplexMatrix new_slice = Generate_Slice_Hamiltonian(x); return((energy * DoubleMatrix.Identity(ny)) - new_slice); }
DoubleComplexMatrix Generate_Hopping_Hamiltonian() { DoubleComplexMatrix result = new DoubleComplexMatrix(ny, ny); for (int i = 0; i < ny; i++) { result[i, i] = alphax; } return(result); }
void Save_BC_Eigvecs(DoubleComplexMatrix eig_mat) { StreamWriter sw = new StreamWriter("vecs.dat"); for (int i = 0; i < eig_mat.Rows; i++) { for (int j = 0; j < eig_mat.Cols; j++) { sw.Write(eig_mat[i, j].Real.ToString() + '\t'); } sw.WriteLine(); } sw.Close(); }
void Initiate_Greens_Function(double energy) { onsite_G = new DoubleComplexMatrix[nx]; hopping_G = new DoubleComplexMatrix[nx]; for (int i = 1; i < nx - 1; i++) { onsite_G[i] = new DoubleComplexMatrix(ny, ny); hopping_G[i] = new DoubleComplexMatrix(ny, ny); } onsite_G[0] = Calculate_Boundary_Conditions(Boundary.left, energy); onsite_G[nx - 1] = Calculate_Boundary_Conditions(Boundary.right, energy); LHSboundary = onsite_G[0]; RHSboundary = onsite_G[nx - 1]; }
DoubleComplexMatrix Generate_Slice_Hamiltonian(double x) { DoubleComplexMatrix result = new DoubleComplexMatrix(ny, ny); for (int i = 0; i < ny - 1; i++) { double y = (i - (ny - 1) / 2) * dy; result[i, i] = -2.0 * alphay - 2.0 * alphax + Get_Potential(x, y); result[i, i + 1] = 1.0 * alphay; result[i + 1, i] = 1.0 * alphay; } // the alphax term is necessary here as we are doing this in 2D result[ny - 1, ny - 1] = -2.0 * alphax - 2.0 * alphay + Get_Potential(x, (ny - 1) / 2 * dy); return(result); }
void Get_Greens_Functions(double energy) { Initiate_Greens_Function(energy); for (int i = 1; i < nx - 1; i++) { Add_Slice(energy, i); } // factorise and invert the right hand lead Green's function DoubleComplexLUFact factorisation = new DoubleComplexLUFact(onsite_G[nx - 1]); DoubleComplexMatrix rhs_inverted_G = factorisation.Inverse(); Bind_Slice(nx - 1, rhs_inverted_G); //Output_DoS(); for (int i = 0; i < ny; i++) { for (int j = 0; j < nx; j++) { DensityoS[j, i] = (-1.0 * onsite_G[j][i, i].Imag / (Math.PI * alphax_prime)); } } }
DoubleComplexMatrix Generate_Hopping_Hamiltonian() { DoubleComplexMatrix result = new DoubleComplexMatrix(ny,ny); for (int i = 0; i < ny; i++) result[i, i] = alphax; return result; }
private DoubleComplexMatrix Calculate_Boundary_Conditions(Boundary boundary, double energy) { DoubleComplexMatrix bc_matrix = new DoubleComplexMatrix(2 * ny, 2 * ny); // generate Hamiltonians for the boundaries DoubleComplexMatrix tmp_slice; if (boundary == Boundary.left) { tmp_slice = Generate_Slice_Hamiltonian(-0.5 * (nx - 1) * dx); } else if (boundary == Boundary.right) { tmp_slice = Generate_Slice_Hamiltonian(0.5 * (nx - 1) * dx); } else { throw new NotImplementedException(); } DoubleComplexMatrix tmp_hopping_trans = Generate_Hopping_Hamiltonian().Transpose(); // create temporary matrix for top-left of BC matrix DoubleComplexMatrix tmp_matrix = Product(tmp_hopping_trans, (new DoubleComplexMatrix(energy * DoubleMatrix.Identity(ny)) - tmp_slice)); // fill with transfer matrix for (int i = 0; i < ny; i++) { for (int j = 0; j < ny; j++) { bc_matrix[i, j] = tmp_matrix[i, j]; bc_matrix[i + ny, j] = tmp_hopping_trans[i, j]; bc_matrix[i, j + ny] = -1.0 * tmp_hopping_trans[i, j]; } } // solve eigen-problem for transfer matrix DoubleComplexEigDecomp eig_decomp = new DoubleComplexEigDecomp(bc_matrix); DoubleComplexEigDecompServer server = new DoubleComplexEigDecompServer(); eig_decomp = server.Factor(bc_matrix); // fill the eigenvalue matrix, excluding unphysical solutions which blow-up in the wire DoubleComplexMatrix eig_vals = new DoubleComplexMatrix(ny, ny); DoubleComplexMatrix eig_vecs = new DoubleComplexMatrix(ny, ny); int count = 0; for (int i = 0; i < 2 * ny; i++) { if (Add_BC_EigenSolution(i, eig_decomp, boundary)) { // invert eigenvalues if calculating for the right lead if (boundary == Boundary.left) { eig_vals[count, count] = eig_decomp.EigenValue(i); } else if (boundary == Boundary.right) { eig_vals[count, count] = 1.0 / eig_decomp.EigenValue(i); } else { throw new NotImplementedException(); } // insert corresponding (normalised) eigenvector into the matrix double norm = 0.0; for (int j = 0; j < ny; j++) { norm += DoubleComplex.Norm(eig_decomp.RightEigenVector(i)[j]) * DoubleComplex.Norm(eig_decomp.RightEigenVector(i)[j]); } double inv_norm = 1.0 / Math.Sqrt(norm); for (int j = 0; j < ny; j++) { eig_vecs[j, count] = inv_norm * eig_decomp.RightEigenVector(i)[j]; } count++; } } // calculate coefficient matrix A and output Green's function DoubleComplexMatrix coefficient_matrix = new DoubleComplexMatrix(ny, ny); coefficient_matrix = Product(Product(tmp_hopping_trans.Transpose(), eig_vecs), eig_vals); DoubleComplexLUFact lu_fact = new DoubleComplexLUFact(coefficient_matrix); return(new DoubleComplexMatrix(Product(eig_vecs, lu_fact.Inverse()))); /* // allocate for evanescent modes * if (boundary == Boundary.left && DoubleComplex.Norm(eig_decomp.EigenValue(i)) < 1.0 - propagating_mode_error) * eig_vals[i, i] = eig_decomp.EigenValue(i); * else if (boundary == Boundary.right && DoubleComplex.Norm(eig_decomp.EigenValue(i)) > 1.0 + propagating_mode_error) * eig_vals[i, i] = 1.0 / eig_decomp.EigenValue(i); * // and for propagating modes * else if (Math.Abs(DoubleComplex.Norm(eig_decomp.EigenValue(i)) - 1.0) < propagating_mode_error) * eig_vals[i, i] * else * throw new InvalidArgumentException("Error - Cannot have eigenvalue of transfer matrix with value " + eig_decomp.EigenValue(i).ToString() + "!"); * * // fill the eigenvector matrix with only the top half of the eigenvector * DoubleComplexMatrix eig_vecs = new DoubleComplexMatrix(ny, ny); * DoubleComplexMatrix inv_eigvec = new DoubleComplexMatrix(ny, ny); * for (int i = 0; i < ny; i++) * { * DoubleComplexVector tmpvec_right = eig_decomp.RightEigenVector(i); * DoubleComplexVector tmpvec_left = eig_decomp.LeftEigenVector(i); * * // normalise the top of half of the eigenvector * double norm2_right = 0.0; * double norm2_left = 0.0; * for (int j = 0; j < ny; j++) * { * norm2_right += NMathFunctions.Abs(tmpvec_right[i]) * NMathFunctions.Abs(tmpvec_right[i]); * norm2_left += NMathFunctions.Abs(tmpvec_left[i]) * NMathFunctions.Abs(tmpvec_left[i]); * } * double norm_left = Math.Sqrt(norm2_left); * double norm_right = Math.Sqrt(norm2_right); * * // and insert it into the matrix * for (int j = 0; j < ny; j++) * { * eig_vecs[j, i] = tmpvec_right[j] / norm_right; * inv_eigvec[i, j] = tmpvec_left[j] / norm_left; * } * } * * // get the inverse of the eigenvector matrix * // DoubleComplexMatrix tmp_eigvec = new DoubleComplexMatrix(eig_vecs); * // DoubleComplexMatrix inv_eigvec = NMathFunctions.PseudoInverse(tmp_eigvec); * //DoubleComplexLUFact eigvec_fact = new DoubleComplexLUFact(tmp_eigvec); * //DoubleComplexMatrix inv_eigvec = eigvec_fact.Inverse(); * * // Calculate the on-site Greens function of the end of the wire and return it * if (boundary == Boundary.left) * return Product(Product(Product(eig_vecs, eig_vals), inv_eigvec), tmp_hopping_trans); * else if (boundary == Boundary.right) * return Product(Product(Product(eig_vecs, eig_vals), inv_eigvec), tmp_hopping); * else * throw new NotImplementedException(); */ }
DoubleComplexMatrix Generate_Slice_Hamiltonian(double x) { DoubleComplexMatrix result = new DoubleComplexMatrix(ny,ny); for (int i = 0; i < ny - 1; i++) { double y = (i - (ny - 1) / 2) * dy; result[i, i] = -2.0 * alphay - 2.0 * alphax + Get_Potential(x, y); result[i, i + 1] = 1.0 * alphay; result[i + 1, i] = 1.0 * alphay; } // the alphax term is necessary here as we are doing this in 2D result[ny - 1, ny - 1] = -2.0 * alphax - 2.0 * alphay + Get_Potential(x, (ny - 1) / 2 * dy); return result; }
DoubleComplexMatrix Product(DoubleHermitianMatrix A, DoubleComplexMatrix B) { return new DoubleComplexMatrix(NMathFunctions.Product(MatrixFunctions.ToGeneralMatrix(A), B)); }
void Initiate_Greens_Function(double energy) { onsite_G = new DoubleComplexMatrix[nx]; hopping_G = new DoubleComplexMatrix[nx]; for (int i = 1; i < nx - 1; i++) { onsite_G[i] = new DoubleComplexMatrix(ny,ny); hopping_G[i] = new DoubleComplexMatrix(ny,ny); } onsite_G[0] = Calculate_Boundary_Conditions(Boundary.left, energy); onsite_G[nx - 1] = Calculate_Boundary_Conditions(Boundary.right, energy); LHSboundary = onsite_G[0]; RHSboundary = onsite_G[nx - 1]; }
void Add_Slice(double energy, int slice_no) { DoubleComplexMatrix new_slice = Create_New_Slice(energy, slice_no); Bind_Slice(slice_no, new_slice); }
private DoubleComplexMatrix Calculate_Boundary_Conditions(Boundary boundary, double energy) { DoubleComplexMatrix bc_matrix = new DoubleComplexMatrix(2 * ny, 2 * ny); // generate Hamiltonians for the boundaries DoubleComplexMatrix tmp_slice; if (boundary == Boundary.left) tmp_slice = Generate_Slice_Hamiltonian(-0.5 * (nx - 1) * dx); else if (boundary == Boundary.right) tmp_slice = Generate_Slice_Hamiltonian(0.5 * (nx - 1) * dx); else throw new NotImplementedException(); DoubleComplexMatrix tmp_hopping_trans = Generate_Hopping_Hamiltonian().Transpose(); // create temporary matrix for top-left of BC matrix DoubleComplexMatrix tmp_matrix = Product(tmp_hopping_trans, (new DoubleComplexMatrix(energy * DoubleMatrix.Identity(ny)) - tmp_slice)); // fill with transfer matrix for (int i = 0; i < ny; i++) for (int j = 0; j < ny; j++) { bc_matrix[i, j] = tmp_matrix[i, j]; bc_matrix[i + ny, j] = tmp_hopping_trans[i, j]; bc_matrix[i, j + ny] = -1.0 * tmp_hopping_trans[i, j]; } // solve eigen-problem for transfer matrix DoubleComplexEigDecomp eig_decomp = new DoubleComplexEigDecomp(bc_matrix); DoubleComplexEigDecompServer server = new DoubleComplexEigDecompServer(); eig_decomp = server.Factor(bc_matrix); // fill the eigenvalue matrix, excluding unphysical solutions which blow-up in the wire DoubleComplexMatrix eig_vals = new DoubleComplexMatrix(ny, ny); DoubleComplexMatrix eig_vecs = new DoubleComplexMatrix(ny, ny); int count = 0; for (int i = 0; i < 2 * ny; i++) if (Add_BC_EigenSolution(i, eig_decomp, boundary)) { // invert eigenvalues if calculating for the right lead if (boundary == Boundary.left) eig_vals[count, count] = eig_decomp.EigenValue(i); else if (boundary == Boundary.right) eig_vals[count, count] = 1.0 / eig_decomp.EigenValue(i); else throw new NotImplementedException(); // insert corresponding (normalised) eigenvector into the matrix double norm = 0.0; for (int j = 0; j < ny; j++) norm += DoubleComplex.Norm(eig_decomp.RightEigenVector(i)[j]) * DoubleComplex.Norm(eig_decomp.RightEigenVector(i)[j]); double inv_norm = 1.0 / Math.Sqrt(norm); for (int j = 0; j < ny; j++) eig_vecs[j, count] = inv_norm * eig_decomp.RightEigenVector(i)[j]; count++; } // calculate coefficient matrix A and output Green's function DoubleComplexMatrix coefficient_matrix = new DoubleComplexMatrix(ny, ny); coefficient_matrix = Product(Product(tmp_hopping_trans.Transpose(), eig_vecs), eig_vals); DoubleComplexLUFact lu_fact = new DoubleComplexLUFact(coefficient_matrix); return new DoubleComplexMatrix(Product(eig_vecs, lu_fact.Inverse())); /* // allocate for evanescent modes if (boundary == Boundary.left && DoubleComplex.Norm(eig_decomp.EigenValue(i)) < 1.0 - propagating_mode_error) eig_vals[i, i] = eig_decomp.EigenValue(i); else if (boundary == Boundary.right && DoubleComplex.Norm(eig_decomp.EigenValue(i)) > 1.0 + propagating_mode_error) eig_vals[i, i] = 1.0 / eig_decomp.EigenValue(i); // and for propagating modes else if (Math.Abs(DoubleComplex.Norm(eig_decomp.EigenValue(i)) - 1.0) < propagating_mode_error) eig_vals[i, i] else throw new InvalidArgumentException("Error - Cannot have eigenvalue of transfer matrix with value " + eig_decomp.EigenValue(i).ToString() + "!"); // fill the eigenvector matrix with only the top half of the eigenvector DoubleComplexMatrix eig_vecs = new DoubleComplexMatrix(ny, ny); DoubleComplexMatrix inv_eigvec = new DoubleComplexMatrix(ny, ny); for (int i = 0; i < ny; i++) { DoubleComplexVector tmpvec_right = eig_decomp.RightEigenVector(i); DoubleComplexVector tmpvec_left = eig_decomp.LeftEigenVector(i); // normalise the top of half of the eigenvector double norm2_right = 0.0; double norm2_left = 0.0; for (int j = 0; j < ny; j++) { norm2_right += NMathFunctions.Abs(tmpvec_right[i]) * NMathFunctions.Abs(tmpvec_right[i]); norm2_left += NMathFunctions.Abs(tmpvec_left[i]) * NMathFunctions.Abs(tmpvec_left[i]); } double norm_left = Math.Sqrt(norm2_left); double norm_right = Math.Sqrt(norm2_right); // and insert it into the matrix for (int j = 0; j < ny; j++) { eig_vecs[j, i] = tmpvec_right[j] / norm_right; inv_eigvec[i, j] = tmpvec_left[j] / norm_left; } } // get the inverse of the eigenvector matrix // DoubleComplexMatrix tmp_eigvec = new DoubleComplexMatrix(eig_vecs); // DoubleComplexMatrix inv_eigvec = NMathFunctions.PseudoInverse(tmp_eigvec); //DoubleComplexLUFact eigvec_fact = new DoubleComplexLUFact(tmp_eigvec); //DoubleComplexMatrix inv_eigvec = eigvec_fact.Inverse(); // Calculate the on-site Greens function of the end of the wire and return it if (boundary == Boundary.left) return Product(Product(Product(eig_vecs, eig_vals), inv_eigvec), tmp_hopping_trans); else if (boundary == Boundary.right) return Product(Product(Product(eig_vecs, eig_vals), inv_eigvec), tmp_hopping); else throw new NotImplementedException(); */ }
DoubleComplexMatrix Product(DoubleHermitianMatrix A, DoubleComplexMatrix B) { return(new DoubleComplexMatrix(NMathFunctions.Product(MatrixFunctions.ToGeneralMatrix(A), B))); }
void Save_BC_Eigvecs(DoubleComplexMatrix eig_mat) { StreamWriter sw = new StreamWriter("vecs.dat"); for (int i = 0; i < eig_mat.Rows; i++) { for (int j = 0; j < eig_mat.Cols; j++) sw.Write(eig_mat[i, j].Real.ToString() + '\t'); sw.WriteLine(); } sw.Close(); }
DoubleComplexMatrix Product(DoubleComplexMatrix A, DoubleComplexMatrix B) { return NMathFunctions.Product(A, B); }
DoubleComplexMatrix Product(DoubleComplexMatrix A, DoubleComplexMatrix B) { return(NMathFunctions.Product(A, B)); }
private void Bind_Slice(int slice_no, DoubleComplexMatrix slice_to_bind) { DoubleComplexMatrix new_hopping = Generate_Hopping_Hamiltonian(); DoubleComplexMatrix new_hopping_trans = Generate_Hopping_Hamiltonian().Transpose(); DoubleComplexMatrix temp_matrix = new DoubleComplexMatrix(slice_to_bind - Product(Product(new_hopping, onsite_G[slice_no - 1]), new_hopping_trans)); // factorise the matrix DoubleComplexLUFact factorisation = new DoubleComplexLUFact(temp_matrix); // the inverse of this matrix is the onsite Green's function for the new slice onsite_G[slice_no] = factorisation.Inverse(); // the first hop from n to n + 1 uses the onsite Green's function as G_(i,n+1) = G_(i,n) H' G(n+1,n+1) and when i = n, G_(i,n) = G(i,i) // must do this here before updating the onsite Green's functions hopping_G[slice_no - 1] = onsite_G[slice_no - 1]; // update the old onsite Green's functions (not including the boundary slice) for (int i = 0; i < slice_no; i++) onsite_G[i] = onsite_G[i] + Product(Product(Product(Product(hopping_G[i], new_hopping), onsite_G[slice_no]), new_hopping_trans), hopping_G[i].Transpose()); // calculate the new hopping Green's functions for (int i = 0; i < slice_no; i++) hopping_G[i] = Product(Product(hopping_G[i], new_hopping), onsite_G[slice_no]); }