func testRightSplit(n int) { fmt.Println("Initializing Sparse matrix structure\n") tmp := cmplxSparse.New() matrixSize := int(2 * (n + n + 4)) fmt.Println("Making sparse ", matrixSize, "x", matrixSize, " Hamiltonian tridiagonal matrix for band split test (right)\n") cmplxSparse.MakeHamTriDiag(n+n+4, tmp) fmt.Println("Adding splitting of 1.25 along +z direction\n") tmp2 := cmplxSparse.AddBandSplitRightFM(0, 0, 0.1, 1.25, n, tmp) fmt.Println("Accessing matrix elements (m,n):") for idx0 := 0; idx0 < matrixSize; idx0++ { for idx1 := 0; idx1 < matrixSize; idx1++ { test := cmplxSparse.AccessMatrix(idx0, idx1, tmp2) fmt.Printf("%f ", test) } fmt.Printf("\n") } fmt.Println("\n") fmt.Println("Adding splitting of 0.75 along (1,1,1) direction\n") tmp2 = cmplxSparse.AddBandSplitRightFM(1.0, 1.0, 1.0, 0.75, n, tmp) fmt.Println("Accessing matrix elements (m,n):") for idx0 := 0; idx0 < matrixSize; idx0++ { for idx1 := 0; idx1 < matrixSize; idx1++ { test := cmplxSparse.AccessMatrix(idx0, idx1, tmp2) fmt.Printf("%f ", test) } fmt.Printf("\n") } fmt.Println("\n") }
func testScaleMatrix(n int) { fmt.Println("Initializing Sparse matrix structure\n") tmp := cmplxSparse.New() matrixSize := int(2 * n) fmt.Println("Making sparse ", matrixSize, "x", matrixSize, " Hamiltonian tridiagonal matrix\n") cmplxSparse.MakeHamTriDiag(n, tmp) fmt.Println("Scaling matrix by factor of 5+1*im\n") cmplxSparse.ScaleSparseMatrix(complex(5, 1), tmp) fmt.Println("Accessing matrix elements (m,n):") for idx0 := 0; idx0 < matrixSize; idx0++ { for idx1 := 0; idx1 < matrixSize; idx1++ { test := cmplxSparse.AccessMatrix(idx0, idx1, tmp) fmt.Printf("%f ", test) } fmt.Printf("\n") } fmt.Printf("\n") fmt.Println("Scaling matrix by factor of 1/5\n") cmplxSparse.ScaleSparseMatrix(complex128(0.2), tmp) for idx0 := 0; idx0 < matrixSize; idx0++ { for idx1 := 0; idx1 < matrixSize; idx1++ { test := cmplxSparse.AccessMatrix(idx0, idx1, tmp) fmt.Printf("%f ", test) } fmt.Printf("\n") } fmt.Println("\n") }
func testDiagSolver(n int) { fmt.Println("Initializing Sparse matrix structure\n") tmp := cmplxSparse.New() matrixSize := int(2 * n) fmt.Println("Making sparse ", matrixSize, "x", matrixSize, " Hamiltonian tridiagonal matrix\n") cmplxSparse.MakeHamTriDiag(n, tmp) for idx0 := 0; idx0 < matrixSize; idx0++ { tmp.Data[idx0][2] -= complex(0.0, 5.0) } fmt.Println("Accessing matrix elements of Hamiltonian (m,n):") for idx0 := 0; idx0 < matrixSize; idx0++ { for idx1 := 0; idx1 < matrixSize; idx1++ { test := cmplxSparse.AccessMatrix(idx0, idx1, tmp) fmt.Printf("%f ", test) } fmt.Printf("\n") } fmt.Printf("\n") tmp0 := cmplxSparse.SparseCopy(tmp) cmplxSparse.SparseDiagLU(tmp0) fmt.Println("Accessing matrix elements of LU (m,n):") for idx0 := 0; idx0 < matrixSize; idx0++ { for idx1 := 0; idx1 < matrixSize; idx1++ { test := cmplxSparse.AccessMatrix(idx0, idx1, tmp0) fmt.Printf("%f ", test) } fmt.Printf("\n") } fmt.Printf("\n") InvBuffer := make([][]complex128, matrixSize) for idx0 := range InvBuffer { InvBuffer[idx0] = make([]complex128, matrixSize) for idx1 := range InvBuffer[idx0] { InvBuffer[idx0][idx1] = 0.0 + 0.0i } } for idx0 := range InvBuffer { InvBuffer[idx0][idx0] = 1.0 + 0.0i BufferMatrix := cmplxSparse.SparseDiagLinearSolver(tmp0, InvBuffer[idx0]) InvBuffer[idx0] = BufferMatrix } fmt.Println("Accessing matrix elements of inverse (m,n):") for idx0 := range InvBuffer { for idx1 := range InvBuffer[idx0] { fmt.Printf("%.15g ", InvBuffer[idx0][idx1]) } fmt.Printf("\n") } }
func testAddModeProfile(E_mode float64, N_fmL int, m_fmL float64, N_ox int, m_ox float64, N_fmR int, m_fmR float64) { fmt.Println("Initializing Sparse matrix structure\n") tmp := cmplxSparse.New() matrixSize := int(2 * (N_fmL + N_ox + N_fmR + 2)) fmt.Println("Making sparse ", matrixSize, "x", matrixSize, " Hamiltonian tridiagonal matrix for mode energy test\n") cmplxSparse.MakeHamTriDiag(matrixSize/2, tmp) fmt.Println("Printing sparse ", matrixSize, "x", matrixSize, " Hamiltonian tridiagonal matrix before action\n") cmplxSparse.PrintSparseMatrix(tmp) cmplxSparse.AddModeEnergy(E_mode, N_fmL, m_fmL, N_ox, m_ox, N_fmR, m_fmR, tmp) fmt.Println("Printing sparse ", matrixSize, "x", matrixSize, " Hamiltonian tridiagonal matrix after action\n") cmplxSparse.PrintSparseMatrix(tmp) }
func testHamTri(n int) { fmt.Println("Initializing Sparse matrix structure\n") tmp := cmplxSparse.New() matrixSize := int(2 * n) fmt.Println("Making sparse ", matrixSize, "x", matrixSize, " Hamiltonian tridiagonal matrix\n") cmplxSparse.MakeHamTriDiag(n, tmp) fmt.Println("Accessing matrix elements (m,n):") for idx0 := 0; idx0 < matrixSize; idx0++ { for idx1 := 0; idx1 < matrixSize; idx1++ { test := cmplxSparse.AccessMatrix(idx0, idx1, tmp) fmt.Printf("%f ", test) } fmt.Printf("\n") } fmt.Println("\n") }
func testIdentity() { fmt.Println("Initializing Sparse matrix structure\n") tmp := cmplxSparse.New() fmt.Println("Making sparse 5x5 identity matrix\n") matrixSize := int(5) cmplxSparse.MakeIdentity(matrixSize, tmp) fmt.Println("Accessing matrix elements (m,n):") for idx0 := 0; idx0 < matrixSize; idx0++ { for idx1 := 0; idx1 < matrixSize; idx1++ { test := cmplxSparse.AccessMatrix(idx0, idx1, tmp) fmt.Printf("%f ", test) } fmt.Printf("\n") } fmt.Println("\n") }
func testRangeScale(A complex128, startIdx, endIdx, diagIdx, n int) { fmt.Println("Initializing Sparse matrix structure\n") tmp := cmplxSparse.New() matrixSize := int(2 * n) fmt.Println("Making sparse ", matrixSize, "x", matrixSize, " Hamiltonian tridiagonal matrix for range scale test\n") cmplxSparse.MakeHamTriDiag(n, tmp) fmt.Println("Scaling index ", startIdx, " to ", endIdx, " on the ", diagIdx, " diagonal of matrix by ", A) cmplxSparse.ScaleRangeSparseMatrix(startIdx, endIdx, diagIdx, A, tmp) fmt.Println("Accessing matrix elements (m,n):") for idx0 := 0; idx0 < matrixSize; idx0++ { for idx1 := 0; idx1 < matrixSize; idx1++ { test := cmplxSparse.AccessMatrix(idx0, idx1, tmp) fmt.Printf("%f ", test) } fmt.Printf("\n") } fmt.Println("\n") }
func testVoltage(n int) { fmt.Println("Initializing Sparse matrix structure\n") tmp := cmplxSparse.New() matrixSize := int(2 * n) fmt.Println("Making sparse ", matrixSize, "x", matrixSize, " Hamiltonian tridiagonal matrix for voltage profile test\n") cmplxSparse.MakeHamTriDiag(n, tmp) fmt.Println("Adding applied potential profile of 0.3 \n") tmp2 := cmplxSparse.AddVoltagePotential(1, n-4, 0.30, tmp) fmt.Println("Accessing matrix elements (m,n):") for idx0 := 0; idx0 < matrixSize; idx0++ { for idx1 := 0; idx1 < matrixSize; idx1++ { test := cmplxSparse.AccessMatrix(idx0, idx1, tmp2) fmt.Printf("%f ", test) } fmt.Printf("\n") } fmt.Println("\n") }
func testLU(n int) { fmt.Println("Initializing Sparse matrix structure\n") tmp := cmplxSparse.New() matrixSize := int(2 * n) fmt.Println("Making sparse ", matrixSize, "x", matrixSize, " Hamiltonian tridiagonal matrix\n") cmplxSparse.MakeHamTriDiag(n, tmp) for idx0 := 0; idx0 < matrixSize; idx0++ { tmp.Data[idx0][2] -= complex(0.0, 5.0) } LU_mat := cmplxSparse.SparseCopy(tmp) cmplxSparse.SparseDiagLU(LU_mat) fmt.Println("Accessing matrix elements (m,n):") for idx0 := 0; idx0 < matrixSize; idx0++ { for idx1 := 0; idx1 < matrixSize; idx1++ { test := cmplxSparse.AccessMatrix(idx0, idx1, LU_mat) fmt.Printf("%f ", test) } fmt.Printf("\n") } fmt.Println("\n") }
func main() { fmt.Println("Pi =", utils.Pi) fmt.Println("Planck constant =", utils.Hplanck) fmt.Println("Reduced Planck constant =", utils.Hbar) fmt.Println("Elementary charge =", utils.Echarge) fmt.Println("Permeability of free space =", utils.Mu0) fmt.Println("Bohr magneton =", utils.MuB) fmt.Println("Small imaginary number =", utils.Zplus) fmt.Println("Free electron mass =", utils.M0) // Set material parameters m_ox = float64(0.315) m_fm_L = float64(0.72) m_fm_R = m_fm_L Ub = 0.93 E_split_L = 0.9 E_split_R = E_split_L E_Fermi = 2.25 fmt.Println("----------------------------------------") fmt.Printf("Ub = %.15g, E_Fermi = %.15g, E_split_L = %.15g, E_split_R = %.15g\n", Ub, E_Fermi, E_split_L, E_split_R) // Configuration parameters th_F, ph_F = utils.Pi/1.0, 0.0 th_H, ph_H = 0.0, 0.0 Vmtj, Temperature = 0.20, 300.0 fmt.Println("----------------------------------------") fmt.Println("Left FM:") fmt.Printf("th = %.15g, ph = %.15g\n", th_F, ph_F) fmt.Println("----------------------------------------") fmt.Println("Right FM:") fmt.Printf("th = %.15g, ph = %.15g\n", th_H, ph_H) fmt.Println("----------------------------------------") // aSpace := float64(2.5e-11) d_ox := float64(1.25e-9) d_fm_L := 2.0 * aSpace d_fm_R := 2.0 * aSpace /* aSpace := float64(0.25e-9); d_ox := float64(1.0e-9); d_fm_L := float64(0.5e-9); d_fm_R := float64(0.5e-9); */ N_fm_L := int(d_fm_L / aSpace) N_fm_R := int(d_fm_R / aSpace) N_ox := int(d_ox/aSpace) - 1 fmt.Printf("Grid spacing = %.15g, N_ox = %d, N_fm_L = %d, N_fm_R = %d\n", aSpace, N_ox, N_fm_L, N_fm_R) fmt.Println("----------------------------------------") t_base := utils.Hbar * utils.Hbar / 2 / utils.Echarge / utils.M0 / aSpace / aSpace t_fm_L := t_base / m_fm_L t_fm_R := t_base / m_fm_R t_ox := t_base / m_ox fmt.Printf("m_fm_L = %.15g, m_ox = %.15g, m_fm_R = %.15g\n", m_fm_L, m_ox, m_fm_R) fmt.Println("----------------------------------------") fmt.Printf("t_fm_L = %.15g, t_ox = %.15g, t_fm_R = %.15g\n", t_fm_L, t_ox, t_fm_R) fmt.Printf("2t_fm_L = %.15g, 2t_ox = %.15g, 2t_fm_R = %.15g\n", 2*t_fm_L, 2*t_ox, 2*t_fm_R) fmt.Println("----------------------------------------") // Create data structure for use with integration functions. ProblemSet := vecQuad.CreateIntegStruct() // Initialize a base matrix template HamBuffer := cmplxSparse.New() cmplxSparse.MakeHamTriDiag(N_fm_L+N_fm_R+N_ox+2, HamBuffer) // Build the main diagonal first cmplxSparse.ScaleRangeSparseMatrix(0, 2*N_fm_L-1, 0, complex(t_fm_L, 0.0), HamBuffer) // Left FM contact cmplxSparse.ScaleRangeSparseMatrix(2*N_fm_L, 2*N_fm_L+1, 0, complex(0.5*(t_fm_L+t_ox), 0.0), HamBuffer) // Interface of left FM contact with barrier cmplxSparse.ScaleRangeSparseMatrix(2*(N_fm_L+1), 2*(N_fm_L+N_ox)+1, 0, complex(t_ox, 0.0), HamBuffer) // Barrier cmplxSparse.ScaleRangeSparseMatrix(2*(N_fm_L+N_ox+1), 2*(N_fm_L+N_ox)+3, 0, complex(0.5*(t_ox+t_fm_R), 0.0), HamBuffer) // Interface of right FM contact with barrier cmplxSparse.ScaleRangeSparseMatrix(2*(N_fm_L+N_ox)+4, 2*(N_fm_L+N_ox+N_fm_R)+3, 0, complex(t_fm_R, 0.0), HamBuffer) // Right FM contact // Build the upper diagonal cmplxSparse.ScaleRangeSparseMatrix(0, 2*N_fm_L-1, 2, complex(t_fm_L, 0.0), HamBuffer) cmplxSparse.ScaleRangeSparseMatrix(2*N_fm_L, 2*(N_fm_L+N_ox)+1, 2, complex(t_ox, 0.0), HamBuffer) cmplxSparse.ScaleRangeSparseMatrix(2*(N_fm_L+N_ox+1), 2*(N_fm_L+N_ox+N_fm_R)+1, 2, complex(t_fm_R, 0.0), HamBuffer) // Build the lower diagonal cmplxSparse.ScaleRangeSparseMatrix(2, 2*N_fm_L+1, -2, complex(t_fm_L, 0.0), HamBuffer) cmplxSparse.ScaleRangeSparseMatrix(2*(N_fm_L+1), 2*(N_fm_L+N_ox)+3, -2, complex(t_ox, 0.0), HamBuffer) cmplxSparse.ScaleRangeSparseMatrix(2*(N_fm_L+N_ox+2), 2*(N_fm_L+N_ox+N_fm_R)+3, -2, complex(t_fm_R, 0.0), HamBuffer) // Include barrier cmplxSparse.AddBarrierProfile(N_fm_L, N_ox, -1.0*(Ub+E_Fermi), HamBuffer) // Include band splitting to left FM contact mx_, my_, mz_ := math.Sin(th_F)*math.Cos(ph_F), math.Sin(th_F)*math.Sin(ph_F), math.Cos(th_F) HamBuffer = cmplxSparse.AddBandSplitLeftFM(mx_, my_, mz_, -1.0*E_split_L, N_fm_L, HamBuffer) // Include band splitting to right FM contact mx_, my_, mz_ = math.Sin(th_H)*math.Cos(ph_H), math.Sin(th_H)*math.Sin(ph_H), math.Cos(th_H) HamBuffer = cmplxSparse.AddBandSplitRightFM(mx_, my_, mz_, -1.0*E_split_R, N_fm_L, HamBuffer) // Calculate matrices for basis transformation. Done here since it is only needed once. ProblemSet.SetHamiltonian(HamBuffer) ProblemSet.SetParams(Vmtj, E_Fermi, Temperature, E_split_L, E_split_R, m_fm_L, m_ox, m_fm_R, complex(t_fm_L, 0.0), complex(t_fm_R, 0.0), N_fm_L, N_ox, N_fm_R, cmplxSparse.BasisTransform(th_F, ph_F), cmplxSparse.BasisTransform(th_H, ph_H)) // Add applied voltage profile ProblemSet.SetHamiltonian(cmplxSparse.AddVoltagePotential(ProblemSet.N_fmL, ProblemSet.N_ox, ProblemSet.V_MTJ, ProblemSet.Hamiltonian)) ProblemSet.SetMu() // cmplxSparse.PrintSparseMatrix(ProblemSet.ReturnHamiltonianPtr()); // TODO: integrate over mode energies // i.e. We should integrate over the region E_mode = [0, +inf) currentsPtr := ProblemSet.NEGF_AutoModeInteg() currents := *currentsPtr for idx0 := 0; idx0 < len(currents); idx0++ { fmt.Println("currents[", idx0, "] =", currents[idx0]) } }