summaryrefslogtreecommitdiff
path: root/collectStokesData.hpp
blob: 54062f5866c26945f3d4e3f338c6e0cff62a4bc6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "stokes.hpp"
#include "complex_normal.hpp"
#include <fstream>

using Complex = std::complex<Real>;

template<int ...ps, class Generator, typename... T>
void collectStokesData(std::string tag, unsigned N, Generator& r, Real ε, Real δz₀, bool minimum, T... μs) {
  unsigned nIts = 5;
  unsigned nGs = 4;
  unsigned coDim = 16;
  Real newSaddleThres = 1e-4;

  pSpinModel<Real, ps...> ReM(N, r, μs...);

  std::normal_distribution<Real> Red(0, 1);

  Vector<Real> xMin(N);

  if (minimum) {
    xMin = randomMinimum<Real>(ReM, Red, r, ε);
  } else {
    xMin = randomSaddle<Real, Real>(ReM, Red, r, ε);
  }

  Real Hx;
  Vector<Real> dHx;
  Matrix<Real> ddHx;
  std::tie(Hx, dHx, ddHx, std::ignore) = ReM.hamGradHess(xMin);
  Matrix<Real> xHess = ddHx - xMin.dot(dHx) * Matrix<Real>::Identity(xMin.size(), xMin.size()) / (Real)N;
  xHess -= (xHess * xMin) * xMin.transpose() / (Real)N;
  Eigen::EigenSolver<Matrix<Real>> eigenS(xHess);

  complex_normal_distribution<Real> d(0, 1, 0);

  pSpinModel M = ReM.template cast<Complex>();;
  Vector<Complex> zMin = xMin.cast<Complex>();

  Vector<Complex> zSaddle = zMin;

  Real δz = δz₀;

  while ((zSaddle - zMin).norm() < newSaddleThres * N || abs(imag(M.getHamiltonian(zSaddle))) < 1e-10) {
    Vector<Complex> z0 = normalize(zSaddle + δz * randomVector<Complex>(N, d, r));
    zSaddle = findSaddle(M, z0, ε);
    δz *= 1.01;
  }

  Complex Hz;
  Vector<Complex> dHz;
  Matrix<Complex> ddHz;
  std::tie(Hz, dHz, ddHz, std::ignore) = M.hamGradHess(zSaddle);
  Matrix<Complex> zHess = ddHz - (zSaddle.transpose() * dHz) * Matrix<Complex>::Identity(N, N) / (Real)N;
  zHess -= (zHess * zSaddle) * zSaddle.adjoint() / zSaddle.squaredNorm();
  Eigen::ComplexEigenSolver<Matrix<Complex>> eigenSz(zHess);

  Real φ = atan2(Hz.imag(), Hx - Hz.real());

  M *= exp(Complex(0, φ));

  std::ofstream file("stokes_info_" + tag + ".dat");

  file.precision(15);

  file << N << std::endl;
  ((file << ps << " "), ...) << std::endl;;
  ((file << μs << " "), ...) << std::endl;;

  std::ofstream tensorFile("stokes_tensor_" + tag + ".dat",  std::ios::out | std::ios::binary | std::ios::trunc);
  std::apply([&tensorFile](const Tensor<Real, ps>&... Js) -> void {
      (tensorFile.write((char*)Js.data(), Js.size() * sizeof(Real)), ...);
      } , ReM.Js);

  file << xMin.transpose() << std::endl;
  file << Hx << std::endl;
  file << eigenS.eigenvalues().real().transpose() << std::endl;
  file << zSaddle.transpose() << std::endl;
  file << Hz << " " << zSaddle.squaredNorm() << std::endl;
  file << eigenSz.eigenvalues().transpose() << std::endl;
  file << φ << " " << (xMin - zSaddle).norm() << std::endl;

  unsigned nTest = 1000;

  file << nIts << " " << nGs << " " << coDim << " " << nTest << std::endl;

  std::vector<Vector<Complex>> oldGs;

  for (int j = 0; j < nIts; j++) {
    Cord c(M, zMin, zSaddle, nGs + pow(2, j));
    for (unsigned i = 0; i < oldGs.size(); i++) {
      c.gs[i] = oldGs[i];
    }
    c.relaxNewton(c.gs.size() * 2, 1, 1e-10, 1e4);
    oldGs = c.gs;

    Real reConstraintError = 0;
    Real imConstraintError = 0;
    Real imEnergyError = 0;
    Real ell = 0;

    for (unsigned i = 0; i < nTest; i++) {
      Real t = (i + 1.0) / (nTest + 1.0);
      Vector<Complex> zi = c.f(t);
      imEnergyError += pow(std::imag(M.getHamiltonian(zi) - M.getHamiltonian(zMin)), 2);
      Complex constraintError = (Complex)(zi.transpose() * zi) - (Complex)N;
      reConstraintError += pow(real(constraintError), 2);
      imConstraintError += pow(imag(constraintError), 2);
      ell += c.df(t).norm();
    }

    file << oldGs.size() << " " << ell / nTest << " " <<  c.totalCost(nTest) / (nTest) << " " << sqrt(imEnergyError / (Real)(nTest)) << " " << sqrt(reConstraintError / (Real)(nTest)) << " " << sqrt(imConstraintError / (Real)(nTest)) << std::endl;
    for (const Vector<Complex>& gi : c.gs) {
      file << gi.transpose() << std::endl;
    }
  }
}