void OutputBands() { KptList ks = KMesh; using (StreamWriter w = new StreamWriter("eigenvalues.k")) { w.WriteLine("# Grid"); w.WriteLine("{0} {1} {2} {3} {4} {5}", ks.Mesh[0], ks.Mesh[1], ks.Mesh[2], ks.Shift[0], ks.Shift[1], ks.Shift[2]); w.WriteLine("# Eigenvalues"); for (int i = 0; i < ks.AllKpts.Count; i++) { KPoint kpt = ks.AllKpts[i]; w.Write("{0} {1} {2} ", kpt.Value.X, kpt.Value.Y, kpt.Value.Z); for (int j = 0; j < kpt.Wavefunctions.Count; j++) { w.Write("{0} ", kpt.Wavefunctions[j].Energy); } w.WriteLine(); } } }
BandTetrahedron GetTetrahedron(TightBinding tb, KPoint kpt, KptList kpts) { List <Pair <int, double> > lst = new List <Pair <int, double> >(); double[] weights = new double[kpts.Kpts.Count]; for (int j = 0; j < kpts.Kpts.Count; j++) { double distance = CalcDistance(tb, kpts.Kpts[j].Value, kpt.Value); weights[j] = 1 / (distance + 0.00001); } for (int j = 0; j < weights.Length; j++) { lst.Add(new Pair <int, double>(j, weights[j])); } lst.Sort((x, y) => { return(y.Second.CompareTo(x.Second)); }); lst.RemoveRange(4, lst.Count - 4); List <int> ilist = lst.Select(x => x.First).ToList(); BandTetrahedron retval = new BandTetrahedron(tb, kpt.Value, kpts, ilist); return(retval); }
void WriteBands(TightBinding tb, KptList kpts, StreamWriter w) { int bandCount = kpts.Kpts[0].Wavefunctions.Count; BandTetrahedron tet = null; for (int i = 0; i < tb.KPath.Kpts.Count; i++) { var kpt = tb.KPath.Kpts[i]; if (tet == null || tet.Contains(kpt) == false) { GetTetrahedron(tb, kpt, kpts); } w.Write(i); w.Write(" "); for (int band = 0; band < bandCount; band++) { double energy = tet.Interpolate(kpt); w.Write("{0} ", energy); } w.WriteLine(); } }
public KptList Clone() { KptList retval = new KptList(); retval.allKpts.AddRange(allKpts.Select(x => x.Clone())); retval.kpts.AddRange(kpts.Select(x => x.Clone())); if (mesh != null) { retval.mesh = (int[])mesh.Clone(); } if (shift != null) { retval.shift = (int[])shift.Clone(); } retval.gammaCentered = gammaCentered; foreach (KeyValuePair <int, int> var in Nvalues) { retval.Nvalues.Add(var.Key, var.Value); } foreach (KeyValuePair <int, int> var in AllNvalues) { retval.AllNvalues.Add(var.Key, var.Value); } retval.sdir = sdir; retval.tdir = tdir; retval.origin = origin; return(retval); }
private void RpaChi0Thread(object obj) { RpaThreadInfo info = (RpaThreadInfo)obj; System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); TightBinding tb = info.tb; List <RpaParams> rpa = info.RpaParams; KptList qpts = info.qpts; for (int i = 0; i < rpa.Count; i++) { SetTemperature(tb, rpa[i].Temperature, rpa[i].ChemicalPotential); rpa[i].X0 = CalcX0(tb, rpa[i].Frequency, qpts.Kpts[rpa[i].Qindex]); if (i == 0 && info.PrimaryThread) { long time = watch.ElapsedTicks * rpa.Count; TimeSpan s = new TimeSpan(time); Output.WriteLine("Estimated total time {0:+hh.mm}", s); } Complex val = rpa[i].X0.Trace(); Output.Write("q = {0}, T = {1:0.000}, mu = {2:0.000}, omega = {3:0.0000}", rpa[i].Qindex + 1, rpa[i].Temperature, rpa[i].ChemicalPotential, rpa[i].Frequency); Output.WriteLine(", Tr(X_0) = {0}", val.ToString("0.0000")); } }
void OutputBands(TightBinding tb, KptList ks, List <RpaParams> rpa, MatrixGetter g, string name) { using (StreamWriter w = new StreamWriter("eigenvalues." + name + ".q")) { w.WriteLine("# Grid"); w.WriteLine("{0} {1} {2} {3} {4} {5}", ks.Mesh[0], ks.Mesh[1], ks.Mesh[2], ks.Shift[0], ks.Shift[1], ks.Shift[2]); w.WriteLine("# Eigenvalues"); foreach (var rpa_i in rpa) { var qpt = rpa_i.QptValue; w.Write("{0} {1} {2} ", qpt.X, qpt.Y, qpt.Z); Matrix chi = g(rpa_i); Matrix evalues = chi.EigenValues(); for (int j = 0; j < evalues.Rows; j++) { w.Write("{0} ", evalues[j, 0].RealPart); } w.WriteLine(); } } }
public void WriteGraceHeader(KptList kpath) { file.WriteLine("@with g0"); var pairs = kpath.Kpts.Select( (kpt, index) => new Pair <int, KPoint>(index, kpt)).ToArray(); var pts = ( from val in pairs where string.IsNullOrEmpty(val.Second.Name) == false select val ).ToArray(); file.WriteLine("@ xaxis tick spec type both"); file.WriteLine("@ xaxis tick spec {0}", pts.Length); for (int i = 0; i < pts.Length; i++) { string label = pts[i].Second.Name; if (label.StartsWith("G")) { label = @"\xG\f{}" + label.Substring(1); } label = label.Replace("$_", @"\s"); label = label.Replace("$^", @"\S"); label = label.Replace("$.", @"\N"); file.WriteLine("@ xaxis tick major {0}, {1}", i, pts[i].First); file.WriteLine("@ xaxis ticklabel {0}, \"{1}\"", i, label); } }
void CreateBands(TightBinding tb, string name) { using (StreamReader r = new StreamReader(name)) { string line = r.ReadLine(); if (line != "# Grid") { Console.WriteLine("Not an eigenvalues file!"); System.Environment.Exit(3); } int[] grid = new int[3]; int[] shift = new int[3]; ParseGrid(grid, shift, line); if (line != "# Eigenvalues") { Console.WriteLine("Not an eigenvalues file!"); System.Environment.Exit(2); } KptList kpts = new KptList(); kpts.Mesh = grid; kpts.Shift = shift; while (r.EndOfStream == false) { line = r.ReadLine(); string[] elements = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); KPoint kpt = new KPoint(new Vector3(double.Parse(elements[0]), double.Parse(elements[1]), double.Parse(elements[2]))); for (int i = 3; i < elements.Length; i++) { Wavefunction wfk = new Wavefunction(0); wfk.Energy = double.Parse(elements[i]); kpt.Wavefunctions.Add(wfk); } kpts.Kpts.Add(kpt); } CreateTetrahedronMesh(kpts); string outputfile = name + ".bands"; using (StreamWriter w = new StreamWriter(outputfile)) { WriteBands(tb, kpts, w); } } }
void CreateBands(TightBinding tb, string name) { using (StreamReader r = new StreamReader(name)) { string line = r.ReadLine(); if (line != "# Grid") { Console.WriteLine("Not an eigenvalues file!"); System.Environment.Exit(3); } int[] grid = new int[3]; int[] shift = new int[3]; ParseGrid(grid, shift, line); if (line != "# Eigenvalues") { Console.WriteLine("Not an eigenvalues file!"); System.Environment.Exit(2); } KptList kpts = new KptList(); kpts.Mesh = grid; kpts.Shift = shift; while (r.EndOfStream == false) { line = r.ReadLine(); string[] elements = line.Split(new char[] { ' '}, StringSplitOptions.RemoveEmptyEntries ); KPoint kpt = new KPoint(new Vector3(double.Parse(elements[0]), double.Parse(elements[1]), double.Parse(elements[2]))); for (int i = 3; i < elements.Length; i++) { Wavefunction wfk = new Wavefunction(0); wfk.Energy = double.Parse(elements[i]); kpt.Wavefunctions.Add(wfk); } kpts.Kpts.Add(kpt); } CreateTetrahedronMesh(kpts); string outputfile = name + ".bands"; using (StreamWriter w = new StreamWriter(outputfile)) { WriteBands(tb, kpts, w); } } }
public static KptPlane GeneratePlane(Lattice lattice, Vector3[] points, KptList qmesh) { Vector3 diff_1 = points[1] - points[0]; Vector3 diff_2 = points[2] - points[0]; Vector3 norm = Vector3.CrossProduct(diff_1, diff_2); KptPlane retval = new KptPlane(); retval.SetLattice(lattice); retval.mesh = (int[])qmesh.Mesh.Clone(); retval.shift = new int[3]; retval.origin = points[0]; retval.sdir = diff_1; retval.tdir = diff_2; NormalizeST(lattice, retval); int zmax = qmesh.Mesh[2] * 2; int ymax = qmesh.Mesh[1] * 2; int xmax = qmesh.Mesh[0] * 2; List <KPoint> planePoints = new List <KPoint>(); for (int i = 0; i < qmesh.Kpts.Count; i++) { var qpt = qmesh.Kpts[i]; Vector3 diff = lattice.ReciprocalExpand(qpt.Value) - points[0]; double dot = Math.Abs(diff.DotProduct(norm)); if (dot < 1e-8) { double s, t; retval.GetPlaneST(qpt, out s, out t); retval.AddKpt(qpt); } } // now sort q-points to lay them in the s,t plane. retval.SortKpoints(); Vector3 sd = retval.sdir / SmallestNonzero(retval.sdir); Vector3 td = retval.tdir / SmallestNonzero(retval.tdir); Output.WriteLine("Plane horizontal direction: {0}", sd); Output.WriteLine("Plane vertical direction: {0}", td); Output.WriteLine("Plane horizontal vector: {0}", retval.sdir); Output.WriteLine("Plane vertical vector: {0}", retval.tdir); return(retval); }
public static KptPlane GeneratePlane(Lattice lattice, Vector3[] points, KptList qmesh) { Vector3 diff_1 = points[1] - points[0]; Vector3 diff_2 = points[2] - points[0]; Vector3 norm = Vector3.CrossProduct(diff_1, diff_2); KptPlane retval = new KptPlane(); retval.SetLattice(lattice); retval.mesh = (int[])qmesh.Mesh.Clone(); retval.shift = new int[3]; retval.origin = points[0]; retval.sdir = diff_1; retval.tdir = diff_2; NormalizeST(lattice, retval); int zmax = qmesh.Mesh[2] * 2; int ymax = qmesh.Mesh[1] * 2; int xmax = qmesh.Mesh[0] * 2; List<KPoint> planePoints = new List<KPoint>(); for (int i = 0; i < qmesh.Kpts.Count; i++) { var qpt = qmesh.Kpts[i]; Vector3 diff = lattice.ReciprocalExpand(qpt.Value) - points[0]; double dot = Math.Abs(diff.DotProduct(norm)); if (dot < 1e-8) { double s, t; retval.GetPlaneST(qpt, out s, out t); retval.AddKpt(qpt); } } // now sort q-points to lay them in the s,t plane. retval.SortKpoints(); Vector3 sd = retval.sdir / SmallestNonzero(retval.sdir); Vector3 td = retval.tdir / SmallestNonzero(retval.tdir); Output.WriteLine("Plane horizontal direction: {0}", sd); Output.WriteLine("Plane vertical direction: {0}", td); Output.WriteLine("Plane horizontal vector: {0}", retval.sdir); Output.WriteLine("Plane vertical vector: {0}", retval.tdir); return retval; }
void ReadKPathSection(string section, ref KptList path) { if (path != null) { ThrowEx(section + " found twice."); } Vector3 lastKpt = Vector3.Zero; char[] array = new char[] { ' ' }; const double ptScale = 400; int ptCount = 0; path = new KptList(); while (EOF == false && LineType != LineType.NewSection) { double dummy; string[] vals = Line.Split(array, StringSplitOptions.RemoveEmptyEntries); if (vals.Length != 3 && vals.Length != 4) { ThrowEx("Cannot understand path entry."); } string text = Line; string name = string.Empty; if (double.TryParse(vals[0], out dummy) == false) { text = text.Substring(text.IndexOf(' ')); name = vals[0]; } Vector3 vecval = Vector3.Parse(text); Vector3 kpt = vecval; double length = (kpt - lastKpt).Magnitude; if (ptCount == 0) { path.AddPts(kpt, kpt, 1); } else { path.AddPts(lastKpt, kpt, Math.Max((int)(ptScale * length), 1)); } path.Kpts[path.Kpts.Count - 1].Name = name; ptCount++; lastKpt = kpt; ReadNextLine(); } }
private static void NormalizeST(Lattice lattice, KptList retval) { retval.sdir /= retval.sdir.Magnitude; retval.tdir /= retval.tdir.Magnitude; retval.sdir /= GammaInDirection(lattice, retval.sdir).Magnitude; retval.tdir /= GammaInDirection(lattice, retval.tdir).Magnitude; // double them to make s and t 1 at the zone boundary, instead of 0.5. retval.sdir *= 2; retval.tdir *= 2; }
private void CalcNelec() { KptList ks = KMesh; Matrix[] eigenvals = new Matrix[ks.Kpts.Count]; for (int i = 0; i < KMesh.Kpts.Count; i++) { Matrix vals = new Matrix(Orbitals.Count, Orbitals.Count); for (int j = 0; j < Orbitals.Count; j++) { vals[j, 0] = ks.Kpts[i].Wavefunctions[j].Energy; } eigenvals[i] = vals; } double beta = 1 / TemperatureMesh[0]; double N = FindNelec(ks, eigenvals, MuMesh[0], beta); if (specifiedNelec) { MuMesh = new double[Nelec.Length]; for (int i = 0; i < MuMesh.Length; i++) { MuMesh[i] = FindMu(ks, eigenvals, Nelec[i], beta); } } else { Nelec = new double[MuMesh.Length]; for (int i = 0; i < MuMesh.Length; i++) { Nelec[i] = FindNelec(ks, eigenvals, MuMesh[i], beta); } } Output.WriteLine(" mu Nelec"); for (int i = 0; i < MuMesh.Length; i++) { MuMesh[i] = FindMu(ks, eigenvals, Nelec[i], beta); Output.WriteLine(" {0:0.000000} {1:0.000000}", MuMesh[i], Nelec[i]); } }
public static KptList DefaultPath(Lattice l) { const int pts = 40; KptList retval = new KptList(); retval.Kpts.Add(new KPoint(Vector3.Zero)); retval.AddPts(Vector3.Zero, l.G1 * Math.PI, pts); retval.AddPts(l.G1 * Math.PI, (l.G1 + l.G2) * Math.PI, pts); retval.AddPts((l.G1 + l.G2) * Math.PI, l.G2 * Math.PI, pts); retval.AddPts(l.G2 * Math.PI, l.G3 * Math.PI, pts); retval.AddPts(l.G3 * Math.PI, Vector3.Zero, pts); return retval; }
public static KptList DefaultPath(Lattice l) { const int pts = 40; KptList retval = new KptList(); retval.Kpts.Add(new KPoint(Vector3.Zero)); retval.AddPts(Vector3.Zero, l.G1 * Math.PI, pts); retval.AddPts(l.G1 * Math.PI, (l.G1 + l.G2) * Math.PI, pts); retval.AddPts((l.G1 + l.G2) * Math.PI, l.G2 * Math.PI, pts); retval.AddPts(l.G2 * Math.PI, l.G3 * Math.PI, pts); retval.AddPts(l.G3 * Math.PI, Vector3.Zero, pts); return(retval); }
private Matrix[] CalcGreenFunction(TightBindingSuite.TightBinding tb, RpaParams p, KptList kmesh) { int orbitalCount = tb.Orbitals.Count; Matrix[] retval = new Matrix[kmesh.Kpts.Count]; Complex denomFactor = new Complex(0, p.Temperature); for (int k = 0; k < kmesh.Kpts.Count; k++) { retval[k] = new Matrix(orbitalCount, orbitalCount); Matrix hamilt = tb.CalcHamiltonian(kmesh.Kpts[k].Value); Matrix vals, vecs; hamilt.EigenValsVecs(out vals, out vecs); for (int i = 0; i < orbitalCount; i++) { for (int j = 0; j < orbitalCount; j++) { for (int n = 0; n < orbitalCount; n++) { var wfk = new Wavefunction(orbitalCount); wfk.Energy = vals[n, 0].RealPart; for (int c = 0; c < vecs.Rows; c++) { wfk.Coeffs[c] = vecs[c, n]; } Complex coeff = wfk.Coeffs[i].Conjugate() * wfk.Coeffs[j]; Complex g = 1.0 / (p.Frequency + p.ChemicalPotential - wfk.Energy + denomFactor); retval[k][i, j] += g * coeff; } } } } return retval; }
private double FindNelec(KptList ks, Matrix[] eigenvals, double mu, double beta) { double N = 0; for (int i = 0; i < ks.Kpts.Count; i++) { double weight = ks.Kpts[i].Weight; for (int j = 0; j < eigenvals[i].Rows; j++) { double energy = eigenvals[i][j, 0].RealPart; double npt = 2 * FermiFunction(energy, mu, beta); N += npt * weight; } } return(N); }
private void GenerateKmesh() { tb.kmesh = KptList.GenerateMesh(tb.lattice, tb.kgrid, tb.kshift, tb.symmetries, false); Output.WriteLine("Applied {0} symmetries to get {1} irreducible kpoints from {2}.", tb.symmetries.Count, tb.kmesh.Kpts.Count, tb.kmesh.AllKpts.Count); using (StreamWriter writer = new StreamWriter("kpts")) { for (int i = 0; i < tb.kmesh.Kpts.Count; i++) { Vector3 red = tb.lattice.ReducedCoords(tb.kmesh.Kpts[i].Value); writer.WriteLine("{0} {1}", i, red); } } if (tb.UseQPlane == false) { tb.qmesh = KptList.GenerateMesh(tb.lattice, tb.qgrid, tb.qshift, tb.symmetries, false); Output.WriteLine("Found {0} qpoints in the zone.", tb.qmesh.Kpts.Count); } if (tb.setQplane) { tb.qplane = KptList.GeneratePlane(tb.lattice, tb.qplaneDef, tb.symmetries, tb.qgrid, null); Output.WriteLine("Found {0} irreducible qpoints in the plane of {1} qpoints.", tb.qplane.Kpts.Count, tb.qplane.AllKpts.Count); using (StreamWriter writer = new StreamWriter("qpts")) { for (int i = 0; i < tb.qplane.Kpts.Count; i++) { Vector3 red = tb.lattice.ReducedCoords(tb.qplane.Kpts[i].Value); writer.WriteLine("{0} {1}", i, red); } } } }
public BandTetrahedron(TightBinding tb, Vector3 anchor, KptList kpts, List<int> indices) { for (int i = 0; i < indices.Count; i++) { KPoint kpt = kpts.Kpts[indices[i]].Clone(); Vector3 delta = kpt.Value - anchor; ShiftDelta(ref delta, tb.Lattice.G1); ShiftDelta(ref delta, tb.Lattice.G2); ShiftDelta(ref delta, tb.Lattice.G3); kpt.Value = delta + anchor; this.kpts.Add(kpt); } CalculateVelocityMatrix(); }
public BandTetrahedron(TightBinding tb, Vector3 anchor, KptList kpts, List <int> indices) { for (int i = 0; i < indices.Count; i++) { KPoint kpt = kpts.Kpts[indices[i]].Clone(); Vector3 delta = kpt.Value - anchor; ShiftDelta(ref delta, tb.Lattice.G1); ShiftDelta(ref delta, tb.Lattice.G2); ShiftDelta(ref delta, tb.Lattice.G3); kpt.Value = delta + anchor; this.kpts.Add(kpt); } CalculateVelocityMatrix(); }
public void RunRpa(TightBinding tb, KptList qpts, bool plane) { List <KPoint> QMesh = qpts.Kpts; List <RpaParams> rpa = CreateRpaParameterList(tb, QMesh); Output.WriteLine("Calculating susceptibility for {0} q-points.", QMesh.Count); CalcSusceptibility(tb, qpts, rpa); if (plane) { SaveMatricesQPlane(tb, QMesh, rpa, x => x.X0, "chi_0"); SaveMatricesQPlane(tb, QMesh, rpa, x => x.Xs, "chi_s"); SaveMatricesQPlane(tb, QMesh, rpa, x => x.Xc, "chi_c"); } else { OutputBands(tb, qpts, rpa, CalcX0 => CalcX0.X0, "chi_0"); } }
public void RunRpa(TightBinding tb, KptList qpts, bool plane) { List<KPoint> QMesh = qpts.Kpts; List<RpaParams> rpa = CreateRpaParameterList(tb, QMesh); Output.WriteLine("Calculating susceptibility for {0} q-points.", QMesh.Count); CalcSusceptibility(tb, qpts, rpa); if (plane) { SaveMatricesQPlane(tb, QMesh, rpa, x => x.X0, "chi_0"); SaveMatricesQPlane(tb, QMesh, rpa, x => x.Xs, "chi_s"); SaveMatricesQPlane(tb, QMesh, rpa, x => x.Xc, "chi_c"); } else { OutputBands(tb, qpts, rpa, CalcX0 => CalcX0.X0, "chi_0"); } }
void Run(string inputfile) { using (StreamWriter w = new StreamWriter("gplot.out")) { Output.SetFile(w); TightBindingSuite.TightBinding tb = new TightBindingSuite.TightBinding(); tb.LoadTB(inputfile); RpaParams p = new RpaParams(0, Vector3.Zero, tb.TemperatureMesh[0], tb.FrequencyMesh[0], tb.MuMesh[0]); KptList kmesh = KptList.GenerateMesh( tb.Lattice, tb.KMesh.Mesh, null, tb.Symmetries, true); Matrix[] green = CalcGreenFunction(tb, p, kmesh); while (true) { WriteGreenFunction(tb, green, kmesh); }; } }
void ReadKPathSection(string section, ref KptList path) { if (path != null) ThrowEx(section + " found twice."); Vector3 lastKpt = Vector3.Zero; char[] array = new char[] { ' ' }; const double ptScale = 400; int ptCount = 0; path = new KptList(); while (EOF == false && LineType != LineType.NewSection) { double dummy; string[] vals = Line.Split(array, StringSplitOptions.RemoveEmptyEntries); if (vals.Length != 3 && vals.Length != 4) ThrowEx("Cannot understand path entry."); string text = Line; string name = string.Empty; if (double.TryParse(vals[0], out dummy) == false) { text = text.Substring(text.IndexOf(' ')); name = vals[0]; } Vector3 vecval = Vector3.Parse(text); Vector3 kpt = vecval; double length = (kpt - lastKpt).Magnitude; if (ptCount == 0) { path.AddPts(kpt, kpt, 1); } else { path.AddPts(lastKpt, kpt, Math.Max((int)(ptScale * length), 1)); } path.Kpts[path.Kpts.Count - 1].Name = name; ptCount++; lastKpt = kpt; ReadNextLine(); } }
public static KptList oldGenerateMesh(Lattice lattice, int[] kgrid, int[] shift, SymmetryList syms, bool includeEnds) { bool centerGamma = false; KptList retval = new KptList(); int zmax = kgrid[2] * 2; int ymax = kgrid[1] * 2; int xmax = kgrid[0] * 2; if (shift == null) shift = new int[3]; retval.mesh = (int[])kgrid.Clone(); retval.shift = (int[])shift.Clone(); retval.gammaCentered = centerGamma; int index = 0; Vector3 gridVector = new Vector3(kgrid[0], kgrid[1], kgrid[2]); SymmetryList compatSyms = new SymmetryList(); foreach (var symmetry in syms) { Vector3 grid2 = symmetry.Value * gridVector; for (int gi = 0; gi < 3; gi++) grid2[gi] = Math.Abs(grid2[gi]); if (grid2 == gridVector) { compatSyms.Add(symmetry); } } for (int k = 0; k <= zmax; k += 2) { for (int j = 0; j <= ymax; j += 2) { for (int i = 0; i <= xmax; i += 2) { if (includeEnds == false) { if (k == zmax) break; if (i == xmax) break; if (j == ymax) break; } int N = retval.KptToInteger(i, j, k); bool foundSym = false; double dx = (i + shift[0]) / (double)xmax; double dy = (j + shift[1]) / (double)ymax; double dz = (k + shift[2]) / (double)zmax; int symN = N; List<int> orbitals = null; if (centerGamma) { if (kgrid[0] > 1) dx -= 0.5; if (kgrid[1] > 1) dy -= 0.5; if (kgrid[2] > 1) dz -= 0.5; } Vector3 pt = CalcK(lattice, dx, dy, dz); #if DEBUG int testi, testj, testk; retval.ReduceKpt(lattice, new Vector3(pt), out testi, out testj, out testk); //System.Diagnostics.Debug.Assert(i == testi); //System.Diagnostics.Debug.Assert(j == testj); //System.Diagnostics.Debug.Assert(k == testk); #endif foreach (var symmetry in compatSyms) { Vector3 Tpt = symmetry.Value * pt; if (Tpt == pt) continue; Vector3 red = lattice.ReducedCoords(Tpt, true); int newi = (int)Math.Round(xmax * red.X - shift[0]); int newj = (int)Math.Round(ymax * red.Y - shift[1]); int newk = (int)Math.Round(zmax * red.Z - shift[2]); if (newi % 2 != 0 || newj % 2 != 0 || newk % 2 != 0) continue; symN = retval.KptToInteger(newi, newj, newk); if (symN < N) { foundSym = true; if (symmetry.OrbitalTransform.Count > 0) { orbitals = symmetry.OrbitalTransform; } } if (foundSym) break; } Vector3 kptValue = CalcK(lattice, dx, dy, dz); retval.allKpts.Add(new KPoint(kptValue)); if (retval.Nvalues.ContainsKey(N)) { } else if (foundSym == false) { retval.kpts.Add(new KPoint(kptValue)); retval.Nvalues.Add(N, index); index++; } else { int newIndex = retval.Nvalues[symN]; retval.kpts[newIndex].Weight++; retval.kpts[newIndex].AddOrbitalSymmetry(orbitals); retval.Nvalues.Add(N, newIndex); } } } } int count = kgrid[0] * kgrid[1] * kgrid[2]; for (int i = 0; i < retval.kpts.Count; i++) { retval.kpts[i].Weight /= count; retval.allKpts[i].Weight /= count; } if (includeEnds) { retval.allKpts.Sort((x, y) => x.Value.Z.CompareTo(y.Value.Z)); List<int> removeThese = new List<int>(); List<int> equivKpt = new List<int>(); // read this value first, because the size of the array will change. int kptCount = retval.AllKpts.Count; for (int kindex = 0; kindex < kptCount; kindex++) { if (removeThese.Contains(kindex)) continue; Vector3 kpt = retval.allKpts[kindex].Value; double dist = kpt.Magnitude; equivKpt.Clear(); for (int k = -1; k <= 1; k++) { for (int j = -1; j <= 1; j++) { for (int i = -1; i <= 1; i++) { if (i == 0 && j == 0 && k == 0) continue; Vector3 pt = kpt + i * lattice.G1 + j * lattice.G2 + k * lattice.G3; double newDist = pt.Magnitude; if (newDist < dist - 1e-6) { foreach (var value in equivKpt) { if (removeThese.Contains(value) == false) removeThese.Add(value); } equivKpt.Clear(); int search = retval.AllKpts.FindIndex(x => (x.Value - pt).Magnitude < 1e-6); if (search != -1) { if (removeThese.Contains(kindex) == false) removeThese.Add(kindex); // break out of the loop k = 1; j = 1; i = 2; } else { retval.allKpts[kindex].Value = pt; kpt = pt; dist = newDist; // reset variables since we updated this kpoint value. k = -1; j = -1; i = -2; } } else if (Math.Abs(dist - newDist) < 1e-6) { int search = retval.AllKpts.FindIndex(x => (x.Value - pt).Magnitude < 1e-6); if (search != -1) { if (removeThese.Contains(search)) { k = 1; j = 1; i = 2; removeThese.Add(kindex); break; } equivKpt.Add(search); continue; } equivKpt.Add(retval.allKpts.Count); retval.allKpts.Add(new KPoint(pt)); } } } } } // sort in reverse order removeThese.Sort((x, y) => -x.CompareTo(y)); for (int i = 0; i < removeThese.Count; i++) { retval.allKpts.RemoveAt(removeThese[i]); } retval.allKpts.Sort((x, y) => x.Value.Z.CompareTo(y.Value.Z)); } #if DEBUG if (!includeEnds) { double check = 0; for (int i = 0; i < retval.kpts.Count; i++) check += retval.kpts[i].Weight; System.Diagnostics.Debug.Assert(Math.Abs(check - 1) < 1e-8); } #endif return retval; }
void CreateTetrahedronMesh(KptList kpts) { }
private double FindMu(KptList ks, Matrix[] eigenvals, double Ntarget, double beta) { double N; double mu_lower, mu_upper; double N_lower, N_upper; double mu; mu_lower = mu_upper = mu = 0; // first bracket N = FindNelec(ks, eigenvals, mu, beta); if (N > Ntarget) { mu_upper = mu; while (mu_lower >= mu_upper) { mu -= 1; N = FindNelec(ks, eigenvals, mu, beta); if (N > Ntarget) mu_upper = mu; else mu_lower = mu; } } else { mu_lower = mu; while (mu_lower >= mu_upper) { mu += 1; N = FindNelec(ks, eigenvals, mu, beta); if (N > Ntarget) mu_upper = mu; else mu_lower = mu; } } mu = 0.5 * (mu_upper + mu_lower); N_lower = FindNelec(ks, eigenvals, mu_lower, beta); N_upper = FindNelec(ks, eigenvals, mu_upper, beta); // do linear extrapolation int iter = 0; while (Math.Abs(N - Ntarget) > 1e-11 && iter < 300) { double slope = (N_upper - N_lower) / (mu_upper - mu_lower); if ((iter / 3) % 5 < 2) { // bisection in case system is gapped at target number mu = 0.5 * (mu_upper + mu_lower); } else { // linear extrapoliation mu = (Ntarget - N_lower) / slope + mu_lower; } N = FindNelec(ks, eigenvals, mu, beta); if (N < Ntarget) { mu_lower = mu; N_lower = N; } else if (N > Ntarget) { mu_upper = mu; N_upper = N; } iter++; } if (iter >= 300) { Output.WriteLine("Failed to find chemical potential. Check the number of electrons."); throw new Exception("Failed to find chemical potential."); } return mu; }
BandTetrahedron GetTetrahedron(TightBinding tb, KPoint kpt, KptList kpts) { List<Pair<int, double>> lst = new List<Pair<int, double>>(); double[] weights = new double[kpts.Kpts.Count]; for (int j = 0; j < kpts.Kpts.Count; j++) { double distance = CalcDistance(tb, kpts.Kpts[j].Value, kpt.Value); weights[j] = 1 / (distance + 0.00001); } for (int j = 0; j < weights.Length; j++) { lst.Add(new Pair<int, double>(j, weights[j])); } lst.Sort((x,y) => { return y.Second.CompareTo(x.Second); }); lst.RemoveRange(4, lst.Count - 4); List<int> ilist = lst.Select(x => x.First).ToList(); BandTetrahedron retval = new BandTetrahedron(tb, kpt.Value, kpts, ilist); return retval; }
void DoBandStructure() { KptList kpath = KPath; Output.WriteLine("Computing band structure with {0} k-points.", kpath.Kpts.Count); List <Matrix> eigenvals = new List <Matrix>(); List <Matrix> eigenvecs = new List <Matrix>(); for (int i = 0; i < kpath.Kpts.Count; i++) { Matrix m = CalcHamiltonian(kpath.Kpts[i]); Matrix vals, vecs; m.EigenValsVecs(out vals, out vecs); eigenvals.Add(vals); eigenvecs.Add(vecs); for (int j = 0; j < vals.Rows; j++) { if (double.IsNaN(vals[j, 0].RealPart)) { throw new Exception("NaN found while diagonalizing tight binding at kpt " + i.ToString() + "."); } } } int datasets = eigenvals[0].Rows; using (AgrWriter writer = new AgrWriter(outputfile + ".band.agr")) { int[] colors = new int[datasets]; for (int i = 0; i < colors.Length; i++) { colors[i] = 1; } writer.WriteGraceHeader(kpath); writer.WriteGraceSetLineStyle(0, 2); writer.WriteGraceSetLineColor(0); writer.WriteGraceSetLineColor(1, colors); writer.WriteGraceBaseline(kpath.Kpts.Count); for (int i = 0; i < datasets; i++) { writer.WriteGraceDataset(kpath.Kpts.Count, x => new Pair <double, double>(x, eigenvals[x][i, 0].RealPart - MuMesh[0])); } } // Do fat bands plot using (AgrWriter writer = new AgrWriter(outputfile + ".bweights.agr")) { // set all band lines to black int[] colors = new int[datasets]; for (int i = 0; i < colors.Length; i++) { colors[i] = 1; } writer.WriteGraceHeader(kpath); writer.WriteGraceSetLineStyle(0, 2); writer.WriteGraceSetLineColor(0); writer.WriteGraceSetLineColor(1, colors); int set = datasets + 1; for (int j = 0; j < Orbitals.Count; j++) { int color = j + 1; if (color > 15) { color -= 15; } writer.WriteGraceSetLineColor(set, color); writer.WriteGraceSetSymbol(set, 1); writer.WriteGraceSetSymbolColor(set, color); writer.WriteGraceSetSymbolFill(set, 1); set++; } set = datasets + 1; for (int j = 0; j < Orbitals.Count; j++) { writer.WriteGraceLegend(set, Orbitals[j].Name); set += 1; } writer.WriteGraceBaseline(kpath.Kpts.Count); for (int i = 0; i < datasets * Orbitals.Count; i++) { writer.WriteGraceSetLineStyle(i + datasets + 1, 0); } for (int i = 0; i < datasets; i++) { writer.WriteGraceDataset(kpath.Kpts.Count, x => new Pair <double, double>(x, eigenvals[x][i, 0].RealPart - MuMesh[0])); } for (int j = 0; j < Orbitals.Count; j++) { writer.WriteGraceDataset("xysize", kpath.Kpts.Count * datasets, x => { int k = x % kpath.Kpts.Count; int i = x / kpath.Kpts.Count; double mag = eigenvecs[k][j, i].MagnitudeSquared; if (mag < 0.0001) { return(null); } return(new Triplet <double, double, double>( k, eigenvals[k][i, 0].RealPart - MuMesh[0], mag)); }); } } }
public static KptList oldGenerateMesh(Lattice lattice, int[] kgrid, int[] shift, SymmetryList syms, bool includeEnds) { bool centerGamma = false; KptList retval = new KptList(); int zmax = kgrid[2] * 2; int ymax = kgrid[1] * 2; int xmax = kgrid[0] * 2; if (shift == null) { shift = new int[3]; } retval.mesh = (int[])kgrid.Clone(); retval.shift = (int[])shift.Clone(); retval.gammaCentered = centerGamma; int index = 0; Vector3 gridVector = new Vector3(kgrid[0], kgrid[1], kgrid[2]); SymmetryList compatSyms = new SymmetryList(); foreach (var symmetry in syms) { Vector3 grid2 = symmetry.Value * gridVector; for (int gi = 0; gi < 3; gi++) { grid2[gi] = Math.Abs(grid2[gi]); } if (grid2 == gridVector) { compatSyms.Add(symmetry); } } for (int k = 0; k <= zmax; k += 2) { for (int j = 0; j <= ymax; j += 2) { for (int i = 0; i <= xmax; i += 2) { if (includeEnds == false) { if (k == zmax) { break; } if (i == xmax) { break; } if (j == ymax) { break; } } int N = retval.KptToInteger(i, j, k); bool foundSym = false; double dx = (i + shift[0]) / (double)xmax; double dy = (j + shift[1]) / (double)ymax; double dz = (k + shift[2]) / (double)zmax; int symN = N; List <int> orbitals = null; if (centerGamma) { if (kgrid[0] > 1) { dx -= 0.5; } if (kgrid[1] > 1) { dy -= 0.5; } if (kgrid[2] > 1) { dz -= 0.5; } } Vector3 pt = CalcK(lattice, dx, dy, dz); #if DEBUG int testi, testj, testk; retval.ReduceKpt(lattice, new Vector3(pt), out testi, out testj, out testk); //System.Diagnostics.Debug.Assert(i == testi); //System.Diagnostics.Debug.Assert(j == testj); //System.Diagnostics.Debug.Assert(k == testk); #endif foreach (var symmetry in compatSyms) { Vector3 Tpt = symmetry.Value * pt; if (Tpt == pt) { continue; } Vector3 red = lattice.ReducedCoords(Tpt, true); int newi = (int)Math.Round(xmax * red.X - shift[0]); int newj = (int)Math.Round(ymax * red.Y - shift[1]); int newk = (int)Math.Round(zmax * red.Z - shift[2]); if (newi % 2 != 0 || newj % 2 != 0 || newk % 2 != 0) { continue; } symN = retval.KptToInteger(newi, newj, newk); if (symN < N) { foundSym = true; if (symmetry.OrbitalTransform.Count > 0) { orbitals = symmetry.OrbitalTransform; } } if (foundSym) { break; } } Vector3 kptValue = CalcK(lattice, dx, dy, dz); retval.allKpts.Add(new KPoint(kptValue)); if (retval.Nvalues.ContainsKey(N)) { } else if (foundSym == false) { retval.kpts.Add(new KPoint(kptValue)); retval.Nvalues.Add(N, index); index++; } else { int newIndex = retval.Nvalues[symN]; retval.kpts[newIndex].Weight++; retval.kpts[newIndex].AddOrbitalSymmetry(orbitals); retval.Nvalues.Add(N, newIndex); } } } } int count = kgrid[0] * kgrid[1] * kgrid[2]; for (int i = 0; i < retval.kpts.Count; i++) { retval.kpts[i].Weight /= count; retval.allKpts[i].Weight /= count; } if (includeEnds) { retval.allKpts.Sort((x, y) => x.Value.Z.CompareTo(y.Value.Z)); List <int> removeThese = new List <int>(); List <int> equivKpt = new List <int>(); // read this value first, because the size of the array will change. int kptCount = retval.AllKpts.Count; for (int kindex = 0; kindex < kptCount; kindex++) { if (removeThese.Contains(kindex)) { continue; } Vector3 kpt = retval.allKpts[kindex].Value; double dist = kpt.Magnitude; equivKpt.Clear(); for (int k = -1; k <= 1; k++) { for (int j = -1; j <= 1; j++) { for (int i = -1; i <= 1; i++) { if (i == 0 && j == 0 && k == 0) { continue; } Vector3 pt = kpt + i * lattice.G1 + j * lattice.G2 + k * lattice.G3; double newDist = pt.Magnitude; if (newDist < dist - 1e-6) { foreach (var value in equivKpt) { if (removeThese.Contains(value) == false) { removeThese.Add(value); } } equivKpt.Clear(); int search = retval.AllKpts.FindIndex(x => (x.Value - pt).Magnitude < 1e-6); if (search != -1) { if (removeThese.Contains(kindex) == false) { removeThese.Add(kindex); } // break out of the loop k = 1; j = 1; i = 2; } else { retval.allKpts[kindex].Value = pt; kpt = pt; dist = newDist; // reset variables since we updated this kpoint value. k = -1; j = -1; i = -2; } } else if (Math.Abs(dist - newDist) < 1e-6) { int search = retval.AllKpts.FindIndex(x => (x.Value - pt).Magnitude < 1e-6); if (search != -1) { if (removeThese.Contains(search)) { k = 1; j = 1; i = 2; removeThese.Add(kindex); break; } equivKpt.Add(search); continue; } equivKpt.Add(retval.allKpts.Count); retval.allKpts.Add(new KPoint(pt)); } } } } } // sort in reverse order removeThese.Sort((x, y) => - x.CompareTo(y)); for (int i = 0; i < removeThese.Count; i++) { retval.allKpts.RemoveAt(removeThese[i]); } retval.allKpts.Sort((x, y) => x.Value.Z.CompareTo(y.Value.Z)); } #if DEBUG if (!includeEnds) { double check = 0; for (int i = 0; i < retval.kpts.Count; i++) { check += retval.kpts[i].Weight; } System.Diagnostics.Debug.Assert(Math.Abs(check - 1) < 1e-8); } #endif return(retval); }
public static KptList GenerateMesh(Lattice lattice, int[] kgrid, int[] shift, SymmetryList syms, bool includeEnds) { KptList retval = new KptList(); if (shift == null) shift = new int[3]; for (int i = 0; i < 3; i++) if (kgrid[i] == 1) shift[i] = 1; retval.mesh = (int[])kgrid.Clone(); retval.shift = (int[])shift.Clone(); retval.gammaCentered = true; SymmetryList compatSyms = FindCompatibleSymmetries(kgrid, syms); int index = 0; for (int k = -kgrid[2] + shift[2]; k <= kgrid[2]; k += 2) { for (int j = -kgrid[1] + shift[1]; j <= kgrid[1]; j += 2) { for (int i = -kgrid[0] + shift[0]; i <= kgrid[0]; i += 2) { if (includeEnds == false) { if (k == kgrid[2]) break; if (j == kgrid[1]) break; if (i == kgrid[0]) break; } double dx = i * 0.5 / kgrid[0]; double dy = j * 0.5 / kgrid[1]; double dz = k * 0.5 / kgrid[2]; Vector3 kptValue = CalcK(lattice, dx, dy, dz); int N = retval.KptToInteger(i, j, k); int symN = N; System.Diagnostics.Debug.Assert(!(retval.Nvalues.ContainsKey(N) && includeEnds == false)); List<int> orbitals = null; bool foundSym = false; foreach (var symmetry in compatSyms) { Vector3 Tpt = symmetry.Value * kptValue; if (Tpt == kptValue) continue; int newi, newj, newk; retval.ReduceKpt(lattice, Tpt, out newi, out newj, out newk); if (Math.Abs(newi) % 2 != shift[0] || Math.Abs(newj) % 2 != shift[1] || Math.Abs(newk) % 2 != shift[2]) continue; symN = retval.KptToInteger(newi, newj, newk); if (symN < N) { foundSym = true; if (symmetry.OrbitalTransform.Count > 0) { orbitals = symmetry.OrbitalTransform; } break; } } if (includeEnds) { if (retval.AllNvalues.ContainsKey(N)) { retval.allKpts.Add(new KPoint(kptValue)); continue; } } retval.AllNvalues.Add(N, retval.allKpts.Count); retval.allKpts.Add(new KPoint(kptValue)); if (foundSym == false) { retval.kpts.Add(new KPoint(kptValue)); retval.Nvalues.Add(N, index); index++; } else { int newIndex = retval.Nvalues[symN]; retval.kpts[newIndex].Weight++; retval.kpts[newIndex].AddOrbitalSymmetry(orbitals); retval.Nvalues.Add(N, newIndex); } } } } int count = kgrid[0] * kgrid[1] * kgrid[2]; for (int i = 0; i < retval.kpts.Count; i++) { retval.kpts[i].Weight /= count; } for (int i = 0; i < retval.allKpts.Count; i++) { retval.allKpts[i].Weight /= count; } return retval; }
private static bool CenterOnGamma(Lattice lattice, ref KPoint qpt, KptList list) { double dist = qpt.Value.Magnitude; double olddist = dist; Vector3 newPt = qpt.Value; bool retval = true; double bs, bt; list.GetPlaneST(qpt, out bs, out bt); for (int k = -1; k <= 1; k++) { for (int j = -1; j <= 1; j++) { for (int i = -1; i <= 1; i++) { if (i == 0 && j == 0 && k == 0) continue; Vector3 pt = qpt.Value + i * lattice.G1 + j * lattice.G2 + k * lattice.G3; double s, t; bool valid = list.GetPlaneST(new KPoint(pt), out s, out t); if (!valid) continue; if (pt.Magnitude < dist - 1e-6) { if (list.allKpts.Any(x => Math.Abs((x.Value - pt).Magnitude) > 1e-6)) { retval = false; continue; } dist = pt.Magnitude; newPt = pt; } } } } if (olddist != dist) retval = true; if (retval == false) return false; qpt.Value = newPt; return true; }
private void WriteGreenFunction(TightBindingSuite.TightBinding tb, Matrix[] green, KptList kmesh) { WriteGreenFunctionPlane(tb, green, kmesh); }
private void WriteGreenFunctionPlane(TightBindingSuite.TightBinding tb, Matrix[] green, KptList kmesh) { Console.WriteLine("Output as a plane."); Console.WriteLine(); Console.WriteLine("Enter vectors as a series of three numbers, like: 1 1 0"); Console.WriteLine("Only integer values need be used."); Console.WriteLine(); Console.Write("Enter first vector: "); string first = Console.ReadLine(); if (string.IsNullOrEmpty(first)) return; Console.Write("Enter second vector: "); string second = Console.ReadLine(); Vector3 sdir = Vector3.Parse(first); Vector3 tdir = Vector3.Parse(second); Vector3 udir = Vector3.CrossProduct(sdir, tdir); Console.Write("Enter origin point: "); string origin = Console.ReadLine(); Vector3 orig = Vector3.Parse(origin); Vector3 closestKpt = Vector3.Zero; double closestDistance = 999999999; foreach (var kpt in kmesh.AllKpts) { double distance = (kpt.Value - orig).MagnitudeSquared; if (distance < closestDistance) { closestKpt = kpt.Value; closestDistance = distance; } } if (closestDistance > 1e-6) { Console.WriteLine("Using closest k-point to specified origin: {0}.", closestKpt); orig = closestKpt; sdir += closestKpt; tdir += closestKpt; } KptList plane = KptList.GeneratePlane( tb.Lattice, new Vector3[] { orig, sdir, tdir }, tb.Symmetries, kmesh); string tr_filename = string.Format("green.tr.pln"); StreamWriter tr = new StreamWriter(tr_filename); double lastt = double.MinValue; for (int k = 0; k < plane.AllKpts.Count; k++) { Complex trValue = new Complex(); for (int i = 0; i < green[k].Rows; i++) { trValue += green[k][i, i]; } Vector3 kpt = plane.AllKpts[k].Value; List<int> orbitalMap; double s, t; plane.GetPlaneST(plane.AllKpts[k], out s, out t); int kindex = kmesh.IrreducibleIndex(kpt, tb.Lattice, tb.Symmetries, out orbitalMap); if (Math.Abs(t - lastt) > 1e-6) { tr.WriteLine(); lastt = t; } tr.WriteLine("{0}\t{1}\t{2}", s, t, -trValue.ImagPart); } tr.Close(); for (int i = 0; i < green[0].Rows; i++) { for (int j = 0; j < green[0].Columns; j++) { string re_filename = string.Format("green.re.{0}.{1}.pln", i,j); string im_filename = string.Format("green.im.{0}.{1}.pln", i, j); string mag_filename = string.Format("green.mag.{0}.{1}.pln", i, j); StreamWriter rew = new StreamWriter(re_filename); StreamWriter imw = new StreamWriter(im_filename); StreamWriter mag = new StreamWriter(mag_filename); try { lastt = double.MaxValue; for (int k = 0; k < plane.AllKpts.Count; k++) { Vector3 kpt = plane.AllKpts[k].Value; List<int> orbitalMap; double s, t; plane.GetPlaneST(plane.AllKpts[k], out s, out t); int kindex = kmesh.IrreducibleIndex(kpt, tb.Lattice, tb.Symmetries, out orbitalMap); if (Math.Abs(t - lastt) > 1e-6) { rew.WriteLine(); imw.WriteLine(); mag.WriteLine(); lastt = t; } rew.WriteLine("{0}\t{1}\t{2}", s, t, green[kindex][i, j].RealPart); imw.WriteLine("{0}\t{1}\t{2}", s, t, -green[kindex][i, j].ImagPart); mag.WriteLine("{0}\t{1}\t{2}", s, t, green[kindex][i, j].Magnitude); } } finally { rew.Dispose(); imw.Dispose(); mag.Dispose(); } } } }
void OutputBands(TightBinding tb, KptList ks, List<RpaParams> rpa, MatrixGetter g, string name) { using (StreamWriter w = new StreamWriter("eigenvalues." + name + ".q")) { w.WriteLine("# Grid"); w.WriteLine("{0} {1} {2} {3} {4} {5}", ks.Mesh[0], ks.Mesh[1], ks.Mesh[2], ks.Shift[0], ks.Shift[1], ks.Shift[2]); w.WriteLine("# Eigenvalues"); foreach(var rpa_i in rpa) { var qpt = rpa_i.QptValue; w.Write("{0} {1} {2} ", qpt.X, qpt.Y, qpt.Z); Matrix chi = g(rpa_i); Matrix evalues = chi.EigenValues(); for (int j = 0; j < evalues.Rows; j++) { w.Write("{0} ", evalues[j, 0].RealPart); } w.WriteLine(); } } }
private void CalcSusceptibility(TightBinding tb, KptList qpts, List <RpaParams> rpa) { Matrix ident = Matrix.Identity(tb.Orbitals.Count * tb.Orbitals.Count); Matrix[] S, C; CalcSpinChargeMatrices(tb, rpa, out S, out C); Output.WriteLine("Calculating X0..."); RpaThreadInfo[] threadInfos = CreateThreadInfos(tb, rpa, qpts); Output.WriteLine("Using {0} threads.", threads); for (int i = 0; i < threadInfos.Length; i++) { RunRpaThread(threadInfos[i]); if (i == 0) { Thread.Sleep(20); } } bool threadsRunning; do { threadsRunning = false; for (int i = 0; i < threadInfos.Length; i++) { if (threadInfos[i].Thread.ThreadState == ThreadState.Running) { threadsRunning = true; } } Thread.Sleep(10); } while (threadsRunning); Output.WriteLine(); Output.WriteLine("Bare susceptibility calculation completed."); Output.WriteLine(); double factor = InteractionAdjustment(rpa, S, C, tb); if (tb.Interactions.AdjustInteractions) { Output.WriteLine("Multiplying interactions by {0}.", factor); for (int i = 0; i < rpa.Count; i++) { S[i] *= factor; C[i] *= factor; } } else if (factor < 1) { Output.WriteLine("WARNING: There will be divergent geometric series."); Output.WriteLine(" Interpret results with care!"); } Output.WriteLine(); Output.WriteLine("Calculating dressed susceptibilities."); Output.WriteLine(); RpaParams largestParams = null; double largest = 0; string indices = ""; bool charge = false; for (int i = 0; i < rpa.Count; i++) { Matrix s_denom = (ident - S[i] * rpa[i].X0); Matrix c_denom = (ident + C[i] * rpa[i].X0); Matrix s_inv = s_denom.Invert(); Matrix c_inv = c_denom.Invert(); System.Diagnostics.Debug.Assert((s_denom * s_inv).IsIdentity); rpa[i].Xs = rpa[i].X0 * s_inv; rpa[i].Xc = rpa[i].X0 * c_inv; for (int l1 = 0; l1 < tb.Orbitals.Count; l1++) { for (int l2 = 0; l2 < tb.Orbitals.Count; l2++) { for (int l3 = 0; l3 < tb.Orbitals.Count; l3++) { for (int l4 = 0; l4 < tb.Orbitals.Count; l4++) { int a = GetIndex(tb, l1, l2); int b = GetIndex(tb, l3, l4); bool found = false; if (rpa[i].Xs[a, b].MagnitudeSquared > largest) { largest = rpa[i].Xs[a, b].MagnitudeSquared; charge = false; found = true; } if (rpa[i].Xc[a, b].MagnitudeSquared > largest) { largest = rpa[i].Xc[a, b].MagnitudeSquared; charge = true; found = true; } if (found == false) { continue; } indices = string.Format("{0}{1}{2}{3}", l1, l2, l3, l4); largestParams = rpa[i]; } } } } } Output.WriteLine("Largest susceptibility found at:"); Output.WriteLine(" {0} susceptibility: {1}", charge ? "Charge" : "Spin", Math.Sqrt(largest)); Output.WriteLine(" Indices: {0}", indices); Output.WriteLine(" Temperature: {0}", largestParams.Temperature); Output.WriteLine(" Frequency: {0}", largestParams.Frequency); Output.WriteLine(" Chemical Potential: {0}", largestParams.ChemicalPotential); Output.WriteLine(" Q: {0}", largestParams.QptValue); }
private static bool CenterOnGamma(Lattice lattice, ref KPoint qpt, KptList list) { double dist = qpt.Value.Magnitude; double olddist = dist; Vector3 newPt = qpt.Value; bool retval = true; double bs, bt; list.GetPlaneST(qpt, out bs, out bt); for (int k = -1; k <= 1; k++) { for (int j = -1; j <= 1; j++) { for (int i = -1; i <= 1; i++) { if (i == 0 && j == 0 && k == 0) { continue; } Vector3 pt = qpt.Value + i * lattice.G1 + j * lattice.G2 + k * lattice.G3; double s, t; bool valid = list.GetPlaneST(new KPoint(pt), out s, out t); if (!valid) { continue; } if (pt.Magnitude < dist - 1e-6) { if (list.allKpts.Any(x => Math.Abs((x.Value - pt).Magnitude) > 1e-6)) { retval = false; continue; } dist = pt.Magnitude; newPt = pt; } } } } if (olddist != dist) { retval = true; } if (retval == false) { return(false); } qpt.Value = newPt; return(true); }
public static KptList GenerateMesh(Lattice lattice, int[] kgrid, int[] shift, SymmetryList syms, bool includeEnds) { KptList retval = new KptList(); if (shift == null) { shift = new int[3]; } for (int i = 0; i < 3; i++) { if (kgrid[i] == 1) { shift[i] = 1; } } retval.mesh = (int[])kgrid.Clone(); retval.shift = (int[])shift.Clone(); retval.gammaCentered = true; SymmetryList compatSyms = FindCompatibleSymmetries(kgrid, syms); int index = 0; for (int k = -kgrid[2] + shift[2]; k <= kgrid[2]; k += 2) { for (int j = -kgrid[1] + shift[1]; j <= kgrid[1]; j += 2) { for (int i = -kgrid[0] + shift[0]; i <= kgrid[0]; i += 2) { if (includeEnds == false) { if (k == kgrid[2]) { break; } if (j == kgrid[1]) { break; } if (i == kgrid[0]) { break; } } double dx = i * 0.5 / kgrid[0]; double dy = j * 0.5 / kgrid[1]; double dz = k * 0.5 / kgrid[2]; Vector3 kptValue = CalcK(lattice, dx, dy, dz); int N = retval.KptToInteger(i, j, k); int symN = N; System.Diagnostics.Debug.Assert(!(retval.Nvalues.ContainsKey(N) && includeEnds == false)); List <int> orbitals = null; bool foundSym = false; foreach (var symmetry in compatSyms) { Vector3 Tpt = symmetry.Value * kptValue; if (Tpt == kptValue) { continue; } int newi, newj, newk; retval.ReduceKpt(lattice, Tpt, out newi, out newj, out newk); if (Math.Abs(newi) % 2 != shift[0] || Math.Abs(newj) % 2 != shift[1] || Math.Abs(newk) % 2 != shift[2]) { continue; } symN = retval.KptToInteger(newi, newj, newk); if (symN < N) { foundSym = true; if (symmetry.OrbitalTransform.Count > 0) { orbitals = symmetry.OrbitalTransform; } break; } } if (includeEnds) { if (retval.AllNvalues.ContainsKey(N)) { retval.allKpts.Add(new KPoint(kptValue)); continue; } } retval.AllNvalues.Add(N, retval.allKpts.Count); retval.allKpts.Add(new KPoint(kptValue)); if (foundSym == false) { retval.kpts.Add(new KPoint(kptValue)); retval.Nvalues.Add(N, index); index++; } else { int newIndex = retval.Nvalues[symN]; retval.kpts[newIndex].Weight++; retval.kpts[newIndex].AddOrbitalSymmetry(orbitals); retval.Nvalues.Add(N, newIndex); } } } } int count = kgrid[0] * kgrid[1] * kgrid[2]; for (int i = 0; i < retval.kpts.Count; i++) { retval.kpts[i].Weight /= count; } for (int i = 0; i < retval.allKpts.Count; i++) { retval.allKpts[i].Weight /= count; } return(retval); }
private double FindMu(KptList ks, Matrix[] eigenvals, double Ntarget, double beta) { double N; double mu_lower, mu_upper; double N_lower, N_upper; double mu; mu_lower = mu_upper = mu = 0; // first bracket N = FindNelec(ks, eigenvals, mu, beta); if (N > Ntarget) { mu_upper = mu; while (mu_lower >= mu_upper) { mu -= 1; N = FindNelec(ks, eigenvals, mu, beta); if (N > Ntarget) { mu_upper = mu; } else { mu_lower = mu; } } } else { mu_lower = mu; while (mu_lower >= mu_upper) { mu += 1; N = FindNelec(ks, eigenvals, mu, beta); if (N > Ntarget) { mu_upper = mu; } else { mu_lower = mu; } } } mu = 0.5 * (mu_upper + mu_lower); N_lower = FindNelec(ks, eigenvals, mu_lower, beta); N_upper = FindNelec(ks, eigenvals, mu_upper, beta); // do linear extrapolation int iter = 0; while (Math.Abs(N - Ntarget) > 1e-11 && iter < 300) { double slope = (N_upper - N_lower) / (mu_upper - mu_lower); if ((iter / 3) % 5 < 2) { // bisection in case system is gapped at target number mu = 0.5 * (mu_upper + mu_lower); } else { // linear extrapoliation mu = (Ntarget - N_lower) / slope + mu_lower; } N = FindNelec(ks, eigenvals, mu, beta); if (N < Ntarget) { mu_lower = mu; N_lower = N; } else if (N > Ntarget) { mu_upper = mu; N_upper = N; } iter++; } if (iter >= 300) { Output.WriteLine("Failed to find chemical potential. Check the number of electrons."); throw new Exception("Failed to find chemical potential."); } return(mu); }
private RpaThreadInfo[] CreateThreadInfos(TightBinding tb, List <RpaParams> rpa, KptList qpts) { RpaThreadInfo[] infos = new RpaThreadInfo[threads]; for (int i = 0; i < infos.Length; i++) { infos[i] = new RpaThreadInfo(); infos[i].tb = tb.Clone(); infos[i].qpts = qpts; } infos[0].PrimaryThread = true; for (int i = 0; i < rpa.Count; i++) { infos[i % threads].RpaParams.Add(rpa[i]); } return(infos); }
void DoDensityOfStates() { KptList ks = KMesh; using (StreamWriter outf = new StreamWriter(outputfile + ".dos")) { double smearing = TemperatureMesh[0]; double effBeta = 1 / smearing; double emin = double.MaxValue, emax = double.MinValue; for (int i = 0; i < ks.Kpts.Count; i++) { KPoint kpt = ks.Kpts[i]; emin = Math.Min(emin, kpt.Wavefunctions.Min(x => x.Energy)); emax = Math.Max(emax, kpt.Wavefunctions.Max(x => x.Energy)); } emin -= smearing * 10; emax += smearing * 10; emin -= MuMesh[0]; emax -= MuMesh[0]; int epts = 3000; double[] energyGrid = new double[epts]; double[,] dos = new double[epts, Orbitals.Count + 1]; int zeroIndex = 0; Output.WriteLine( "Calculating DOS from {0} to {1} with finite temperature smearing {2}.", emin, emax, smearing); Output.WriteLine("Using {0} kpts.", ks.Kpts.Count); for (int i = 0; i < epts; i++) { energyGrid[i] = emin + (emax - emin) * i / (double)(epts - 1); if (energyGrid[i] < 0) { zeroIndex = i; } } for (int i = 0; i < ks.Kpts.Count; i++) { KPoint kpt = ks.Kpts[i]; for (int j = 0; j < kpt.Wavefunctions.Count; j++) { Wavefunction wfk = kpt.Wavefunctions[j]; double energy = wfk.Energy - MuMesh[0]; int startIndex = FindIndex(energyGrid, energy - smearing * 10); int endIndex = FindIndex(energyGrid, energy + smearing * 10); for (int k = startIndex; k <= endIndex; k++) { double ferm = FermiFunction(energyGrid[k], energy, effBeta); double smearWeight = ferm * (1 - ferm) * effBeta; smearWeight *= ks.Kpts[i].Weight; double weight = 0; for (int l = 0; l < wfk.Coeffs.Length; l++) { if (PoleStates.Contains(l)) { continue; } double stateval = wfk.Coeffs[l].MagnitudeSquared; weight += stateval; } if (PoleStates.Count == 0 && Math.Abs(weight - 1) > 1e-8) { throw new Exception("Eigenvector not normalized!"); } dos[k, 0] += smearWeight * weight; for (int state = 0; state < wfk.Coeffs.Length; state++) { if (PoleStates.Contains(state)) { continue; } double wtk = wfk.Coeffs[state].MagnitudeSquared; dos[k, state + 1] += smearWeight * wtk; } } } } // symmetrize DOS for equivalent orbitals. for (int k = 0; k < epts; k++) { for (int i = 0; i < Orbitals.Count; i++) { double wtk = dos[k, i + 1]; int count = 1; foreach (int equiv in Orbitals[i].Equivalent) { wtk += dos[k, equiv + 1]; count++; } dos[k, i + 1] = wtk / count; foreach (int equiv in Orbitals[i].Equivalent) { dos[k, equiv + 1] = wtk / count; } } } if (emin < 0 && emax > 0) { if (zeroIndex + 1 >= energyGrid.Length) { zeroIndex = energyGrid.Length - 2; } double slope = (dos[zeroIndex, 0] - dos[zeroIndex + 1, 0]) / (energyGrid[zeroIndex] - energyGrid[zeroIndex + 1]); double dosEF = slope * (-energyGrid[zeroIndex]) + dos[zeroIndex, 0]; Output.WriteLine("Density of states at chemical potential: {0}", dosEF); for (int i = 0; i < epts; i++) { outf.Write("{0} ", energyGrid[i]); for (int j = 0; j < Orbitals.Count + 1; j++) { outf.Write("{0} ", dos[i, j]); } outf.WriteLine(); } } } }
public static KptList GeneratePlane(Lattice lattice, Vector3[] points, SymmetryList syms, KptList qmesh) { Vector3 diff_1 = points[1] - points[0]; Vector3 diff_2 = points[2] - points[0]; Vector3 norm = Vector3.CrossProduct(diff_1, diff_2); KptList retval = new KptList(); retval.mesh = (int[])qmesh.mesh.Clone(); retval.shift = new int[3]; retval.gammaCentered = true; retval.origin = points[0]; retval.sdir = diff_1; retval.tdir = Vector3.CrossProduct(norm, diff_1); NormalizeST(lattice, retval); int zmax = qmesh.mesh[2] * 2; int ymax = qmesh.mesh[1] * 2; int xmax = qmesh.mesh[0] * 2; int index = 0; List <KPoint> planePoints = new List <KPoint>(); for (int i = 0; i < qmesh.AllKpts.Count; i++) { var qpt = qmesh.AllKpts[i]; Vector3 diff = qpt.Value - points[0]; double dot = Math.Abs(diff.DotProduct(norm)); if (dot < 1e-8) { double s, t; retval.GetPlaneST(qpt, out s, out t); planePoints.Add(qpt); } } SortByDistanceFromGamma(planePoints); for (int i = 0; i < planePoints.Count; i++) { var qpt = planePoints[i]; double s, t; retval.GetPlaneST(qpt, out s, out t); //if (CenterOnGamma(lattice, ref qpt, retval) == false) // continue; //retval.GetPlaneST(qpt, out news, out newt); retval.allKpts.Add(qpt); } // now sort q-points to lay them in the s,t plane. Comparison <KPoint> sorter = (x, y) => { double s_x, s_y, t_x, t_y; retval.GetPlaneST(x, out s_x, out t_x); retval.GetPlaneST(y, out s_y, out t_y); if (Math.Abs(t_x - t_y) > 1e-6) { return(t_x.CompareTo(t_y)); } else { return(s_x.CompareTo(s_y)); } }; retval.allKpts.Sort(sorter); // now reduce points by symmetry. for (int i = 0; i < retval.allKpts.Count; i++) { var qpt = retval.AllKpts[i]; int N = retval.KptToInteger(lattice, qpt); int symN = N; bool foundSym = false; List <int> orbitals = null; Vector3 pt = qpt.Value; foreach (var symmetry in syms) { Vector3 Tpt = symmetry.Value * pt; int newi, newj, newk; retval.ReduceKpt(lattice, Tpt, out newi, out newj, out newk); if (newi % 2 != 0 || newj % 2 != 0 || newk % 2 != 0) { continue; } symN = retval.KptToInteger(newi, newj, newk); if (retval.Nvalues.ContainsKey(symN)) { foundSym = true; if (symmetry.OrbitalTransform.Count > 0) { orbitals = symmetry.OrbitalTransform; } } if (foundSym) { break; } } if (foundSym == false && retval.Nvalues.ContainsKey(N) == false) { retval.kpts.Add(qpt); retval.Nvalues.Add(N, index); index++; } else if (retval.Nvalues.ContainsKey(N) == false) { int newIndex = retval.Nvalues[symN]; retval.kpts[newIndex].AddOrbitalSymmetry(orbitals); retval.Nvalues.Add(N, newIndex); } else { } // skip points which are already in there. This should only happen for zone edge points } retval.kpts.Sort(sorter); Vector3 sd = retval.sdir / SmallestNonzero(retval.sdir); Vector3 td = retval.tdir / SmallestNonzero(retval.tdir); Output.WriteLine("Plane horizontal direction: {0}", sd); Output.WriteLine("Plane vertical direction: {0}", td); Output.WriteLine("Plane horizontal vector: {0}", retval.sdir); Output.WriteLine("Plane vertical vector: {0}", retval.tdir); return(retval); }
/// <summary> /// This function does not work with symmetries, so it is unused. /// </summary> /// <param name="inp"></param> /// <param name="outputfile"></param> void tet_DoDensityOfStates(TightBinding.TbInputFileReader inp) { KptList ks = KMesh; StreamWriter outf = new StreamWriter(outputfile + ".dos"); double smearing = TemperatureMesh[0]; double smearNorm = 1 / smearing * Math.Pow(Math.PI, -0.5); double oneOverSmearSquared = Math.Pow(smearing, -2); double emin, emax; Hoppings.EnergyScale(out emin, out emax); emin -= smearing * 5; emax += smearing * 5; int epts = 2000; double[] energyGrid = new double[epts]; double[,] dos = new double[epts, Orbitals.Count + 1]; smearNorm /= ks.Kpts.Count; for (int i = 0; i < epts; i++) { energyGrid[i] = emin + (emax - emin) * i / (double)(epts - 1); } Output.WriteLine("Calculating DOS from {0} to {1} with tetrahedron method.", emin, emax, smearing); Output.WriteLine("Using {0} tetrahedrons.", ks.Tetrahedrons.Count); for (int tetindex = 0; tetindex < ks.Tetrahedrons.Count; tetindex++) { Tetrahedron tet = ks.Tetrahedrons[tetindex]; if (tetindex % (ks.Tetrahedrons.Count / 10) == 0 && tetindex > 0) { Output.WriteLine("At {0}...", tetindex); } Matrix[] eigenvals = new Matrix[4]; for (int i = 0; i < 4; i++) { Matrix m = CalcHamiltonian(tet.Corners[i]); Matrix vals, vecs; m.EigenValsVecs(out vals, out vecs); eigenvals[i] = vals; } for (int nband = 0; nband < eigenvals[0].Rows; nband++) { for (int i = 0; i < 4; i++) { tet.Values[i] = eigenvals[i][nband, 0].RealPart; } tet.SortCorners(); int estart = FindIndex(energyGrid, tet.Values[0]); int eend = FindIndex(energyGrid, tet.Values[3]); for (int ei = estart; ei < eend; ei++) { dos[ei, 0] += tet.IntegrateArea(energyGrid[ei]); } } } for (int i = 0; i < epts; i++) { dos[i, 0] /= ks.Tetrahedrons.Count; } for (int i = 0; i < epts; i++) { outf.Write("{0} ", energyGrid[i]); for (int j = 0; j < Orbitals.Count + 1; j++) { outf.Write("{0} ", dos[i, j]); } outf.WriteLine(); } outf.Close(); Output.WriteLine("Creating +coeff file."); outf = new StreamWriter(Path.Combine(Path.GetDirectoryName(outputfile), "+coeff")); outf.WriteLine("#\t1\t0\t" + ks.Kpts.Count.ToString()); outf.Write("# band index\te(k,n)\t"); for (int i = 0; i < Orbitals.Count; i++) { if (string.IsNullOrEmpty(Orbitals[i].Name)) { outf.Write("TB{0}\t", i); } else { outf.Write("{0}\t", Orbitals[i].Name); } } outf.WriteLine(); for (int kindex = 0; kindex < ks.Kpts.Count; kindex++) { Matrix m = CalcHamiltonian(ks.Kpts[kindex]); Matrix vals, vecs; m.EigenValsVecs(out vals, out vecs); outf.WriteLine("# spin= 1 k={0}", ks.Kpts[kindex].Value); for (int i = 0; i < vals.Rows; i++) { outf.Write("{0} {1} ", i + 1, vals[i, 0].RealPart); for (int j = 0; j < vecs.Columns; j++) { outf.Write("{0} {1} ", vecs[i, j].RealPart, vecs[i, j].ImagPart); } outf.WriteLine(); } } }
private void CalcSusceptibility(TightBinding tb, KptList qpts, List<RpaParams> rpa) { Matrix ident = Matrix.Identity(tb.Orbitals.Count * tb.Orbitals.Count); Matrix[] S, C; CalcSpinChargeMatrices(tb, rpa, out S, out C); Output.WriteLine("Calculating X0..."); RpaThreadInfo[] threadInfos = CreateThreadInfos(tb, rpa, qpts); Output.WriteLine("Using {0} threads.", threads); for (int i = 0; i < threadInfos.Length; i++) { RunRpaThread(threadInfos[i]); if (i == 0) Thread.Sleep(20); } bool threadsRunning; do { threadsRunning = false; for (int i = 0; i < threadInfos.Length; i++) { if (threadInfos[i].Thread.ThreadState == ThreadState.Running) threadsRunning = true; } Thread.Sleep(10); } while (threadsRunning); Output.WriteLine(); Output.WriteLine("Bare susceptibility calculation completed."); Output.WriteLine(); double factor = InteractionAdjustment(rpa, S, C, tb); if (tb.Interactions.AdjustInteractions) { Output.WriteLine("Multiplying interactions by {0}.", factor); for (int i = 0; i < rpa.Count; i++) { S[i] *= factor; C[i] *= factor; } } else if (factor < 1) { Output.WriteLine("WARNING: There will be divergent geometric series."); Output.WriteLine(" Interpret results with care!"); } Output.WriteLine(); Output.WriteLine("Calculating dressed susceptibilities."); Output.WriteLine(); RpaParams largestParams = null; double largest = 0; string indices = ""; bool charge = false; for (int i = 0; i < rpa.Count; i++) { Matrix s_denom = (ident - S[i] * rpa[i].X0); Matrix c_denom = (ident + C[i] * rpa[i].X0); Matrix s_inv = s_denom.Invert(); Matrix c_inv = c_denom.Invert(); System.Diagnostics.Debug.Assert((s_denom * s_inv).IsIdentity); rpa[i].Xs = rpa[i].X0 * s_inv; rpa[i].Xc = rpa[i].X0 * c_inv; for (int l1 = 0; l1 < tb.Orbitals.Count; l1++) { for (int l2 = 0; l2 < tb.Orbitals.Count; l2++) { for (int l3 = 0; l3 < tb.Orbitals.Count; l3++) { for (int l4 = 0; l4 < tb.Orbitals.Count; l4++) { int a = GetIndex(tb, l1, l2); int b = GetIndex(tb, l3, l4); bool found = false; if (rpa[i].Xs[a,b].MagnitudeSquared > largest) { largest = rpa[i].Xs[a,b].MagnitudeSquared; charge = false; found = true; } if (rpa[i].Xc[a, b].MagnitudeSquared > largest) { largest = rpa[i].Xc[a, b].MagnitudeSquared; charge = true; found = true; } if (found == false) continue; indices = string.Format("{0}{1}{2}{3}", l1, l2, l3, l4); largestParams = rpa[i]; } } } } } Output.WriteLine("Largest susceptibility found at:"); Output.WriteLine(" {0} susceptibility: {1}", charge ? "Charge" : "Spin", Math.Sqrt(largest)); Output.WriteLine(" Indices: {0}", indices); Output.WriteLine(" Temperature: {0}", largestParams.Temperature); Output.WriteLine(" Frequency: {0}", largestParams.Frequency); Output.WriteLine(" Chemical Potential: {0}", largestParams.ChemicalPotential); Output.WriteLine(" Q: {0}", largestParams.QptValue); }
private double FindNelec(KptList ks, Matrix[] eigenvals, double mu, double beta) { double N = 0; for (int i = 0; i < ks.Kpts.Count; i++) { double weight = ks.Kpts[i].Weight; for (int j = 0; j < eigenvals[i].Rows; j++) { double energy = eigenvals[i][j, 0].RealPart; double npt = 2 * FermiFunction(energy, mu, beta); N += npt * weight; } } return N; }
private RpaThreadInfo[] CreateThreadInfos(TightBinding tb, List<RpaParams> rpa, KptList qpts) { RpaThreadInfo[] infos = new RpaThreadInfo[threads]; for (int i = 0; i < infos.Length; i++) { infos[i] = new RpaThreadInfo(); infos[i].tb = tb.Clone(); infos[i].qpts = qpts; } infos[0].PrimaryThread = true; for (int i = 0; i < rpa.Count; i++) { infos[i % threads].RpaParams.Add(rpa[i]); } return infos; }
protected override void Validate() { if (tb.lattice == null) { ThrowEx(@"""Lattice"" section missing."); } if (tb.sites == null) { ThrowEx(@"""Sites"" section missing."); } if (tb.hoppings == null) { ThrowEx(@"""Hoppings"" section missing."); } if (tb.kpath == null) { tb.kpath = KptList.DefaultPath(tb.lattice); } if (tb.kgrid == null || tb.kgrid[0] == 0 || tb.kgrid[1] == 0 || tb.kgrid[2] == 0) { ThrowEx(@"KMesh was not defined properly."); } if (tb.sites.Count == 0) { ThrowEx(@"There are no sites."); } if (tb.hoppings.Count == 0) { ThrowEx(@"There are no hoppings."); } if (tb.symmetries.Count == 0) { tb.symmetries.Add(new Symmetry(Matrix.Identity(3))); } if (tb.Nelec != null) { if (tb.MuMesh != null) { ThrowEx(@"Specify only one of Nelec or Mu."); } tb.MuMesh = new double[tb.Nelec.Length]; for (int i = 0; i < tb.Nelec.Length; i++) { if (tb.Nelec[i] > tb.Orbitals.Count * 2) { ThrowEx(@"Nelec is too large."); } else if (tb.Nelec[i] < 0) { ThrowEx(@"Nelec cannot be less than zero."); } } } if (tb.MuMesh == null) { tb.MuMesh = new double[] { 0 } } ; if (tb.TemperatureMesh == null) { tb.TemperatureMesh = new double[] { 1 } } ; if (tb.FrequencyMesh == null) { tb.FrequencyMesh = new double[] { 0 } } ; foreach (HoppingPair h in tb.hoppings) { if (h.Left >= tb.sites.Count || h.Right >= tb.sites.Count) { ThrowEx(string.Format(@"The hopping {0} to {1} was specified, but there are only {2} sites.", h.Left + 1, h.Right + 1, tb.sites.Count)); } } foreach (Orbital orb in tb.Orbitals) { var interactionOrbs = tb.Orbitals.Where((x, y) => x.InteractionGroup == orb.InteractionGroup); foreach (Orbital otherOrb in interactionOrbs) { Vector3 delta = otherOrb.Location - orb.Location; if (delta.Magnitude > 1e-8) { ThrowEx(string.Format("In the interaction group {0}, orbitals {1} and {2} are present, but they are in different positions.", orb.InteractionGroup, orb.Name, otherOrb.Name)); } } } }
public static KptList GeneratePlane(Lattice lattice, Vector3[] points, SymmetryList syms, int[] qgrid, int[] qshift) { KptList qmesh = GenerateMesh(lattice, qgrid, qshift, syms, true); return(GeneratePlane(lattice, points, syms, qmesh)); }
public KptList Clone() { KptList retval = new KptList(); retval.allKpts.AddRange(allKpts.Select(x => x.Clone())); retval.kpts.AddRange(kpts.Select(x => x.Clone())); if (mesh != null) retval.mesh = (int[])mesh.Clone(); if (shift != null) retval.shift = (int[])shift.Clone(); retval.gammaCentered = gammaCentered; foreach (KeyValuePair<int, int> var in Nvalues) retval.Nvalues.Add(var.Key, var.Value); foreach (KeyValuePair<int, int> var in AllNvalues) retval.AllNvalues.Add(var.Key, var.Value); retval.sdir = sdir; retval.tdir = tdir; retval.origin = origin; return retval; }
public static KptList GeneratePlane(Lattice lattice, Vector3[] points, SymmetryList syms, KptList qmesh) { Vector3 diff_1 = points[1] - points[0]; Vector3 diff_2 = points[2] - points[0]; Vector3 norm = Vector3.CrossProduct(diff_1, diff_2); KptList retval = new KptList(); retval.mesh = (int[])qmesh.mesh.Clone(); retval.shift = new int[3]; retval.gammaCentered = true; retval.origin = points[0]; retval.sdir = diff_1; retval.tdir = Vector3.CrossProduct(norm, diff_1); NormalizeST(lattice, retval); int zmax = qmesh.mesh[2] * 2; int ymax = qmesh.mesh[1] * 2; int xmax = qmesh.mesh[0] * 2; int index = 0; List<KPoint> planePoints = new List<KPoint>(); for (int i = 0; i < qmesh.AllKpts.Count; i++) { var qpt = qmesh.AllKpts[i]; Vector3 diff = qpt.Value - points[0]; double dot = Math.Abs(diff.DotProduct(norm)); if (dot < 1e-8) { double s, t; retval.GetPlaneST(qpt, out s, out t); planePoints.Add(qpt); } } SortByDistanceFromGamma(planePoints); for (int i = 0; i <planePoints.Count; i++) { var qpt = planePoints[i]; double s, t; retval.GetPlaneST(qpt, out s, out t); //if (CenterOnGamma(lattice, ref qpt, retval) == false) // continue; //retval.GetPlaneST(qpt, out news, out newt); retval.allKpts.Add(qpt); } // now sort q-points to lay them in the s,t plane. Comparison<KPoint> sorter = (x, y) => { double s_x, s_y, t_x, t_y; retval.GetPlaneST(x, out s_x, out t_x); retval.GetPlaneST(y, out s_y, out t_y); if (Math.Abs(t_x - t_y) > 1e-6) return t_x.CompareTo(t_y); else return s_x.CompareTo(s_y); }; retval.allKpts.Sort(sorter); // now reduce points by symmetry. for (int i = 0; i < retval.allKpts.Count; i++) { var qpt = retval.AllKpts[i]; int N = retval.KptToInteger(lattice, qpt); int symN = N; bool foundSym = false; List<int> orbitals = null; Vector3 pt = qpt.Value; foreach (var symmetry in syms) { Vector3 Tpt = symmetry.Value * pt; int newi, newj, newk; retval.ReduceKpt(lattice, Tpt, out newi, out newj, out newk); if (newi % 2 != 0 || newj % 2 != 0 || newk % 2 != 0) continue; symN = retval.KptToInteger(newi, newj, newk); if (retval.Nvalues.ContainsKey(symN)) { foundSym = true; if (symmetry.OrbitalTransform.Count > 0) { orbitals = symmetry.OrbitalTransform; } } if (foundSym) break; } if (foundSym == false && retval.Nvalues.ContainsKey(N) == false) { retval.kpts.Add(qpt); retval.Nvalues.Add(N, index); index++; } else if (retval.Nvalues.ContainsKey(N) == false) { int newIndex = retval.Nvalues[symN]; retval.kpts[newIndex].AddOrbitalSymmetry(orbitals); retval.Nvalues.Add(N, newIndex); } else { } // skip points which are already in there. This should only happen for zone edge points } retval.kpts.Sort(sorter); Vector3 sd = retval.sdir / SmallestNonzero(retval.sdir); Vector3 td = retval.tdir / SmallestNonzero(retval.tdir); Output.WriteLine("Plane horizontal direction: {0}", sd); Output.WriteLine("Plane vertical direction: {0}", td); Output.WriteLine("Plane horizontal vector: {0}", retval.sdir); Output.WriteLine("Plane vertical vector: {0}", retval.tdir); return retval; }