Пример #1
0
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")
}
Пример #2
0
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")

}
Пример #3
0
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")
	}
}
Пример #4
0
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)
}
Пример #5
0
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")
}
Пример #6
0
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")
}
Пример #7
0
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")
}
Пример #8
0
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")

}
Пример #9
0
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")
}
Пример #10
0
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])
	}
}