Exemple #1
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")

}
Exemple #2
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])
	}
}