summaryrefslogtreecommitdiff
path: root/collectStokesData.hpp
blob: 433f5ad17454a511fa011da349a6cf25c5af27cc (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
#include "stokes.hpp"
#include "complex_normal.hpp"
#include <fstream>

using Complex = std::complex<Real>;

template<int ...ps, class Generator, typename... T>
void collectStokesData(std::ofstream& file, unsigned N, Generator& r, double ε, double δz, bool minimum, T... μs) {
  unsigned nGs = 8;
  unsigned nTs = 20;
  Real newSaddleThres = 1e-3;

  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;

  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, ε);
  }

  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, φ));

  file.precision(15);

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

  std::apply([&file](const Tensor<Real, ps>&... Js) -> void {
        ((file << Js << std::endl), ...);
      } , 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 << std::endl;
  file << eigenSz.eigenvalues().transpose() << std::endl;
  file << φ << std::endl;

  Cord c(M, zMin, zSaddle, nGs);
  c.relaxNewton(nTs, 1, 1e-10, 1e3);

  Complex constraintError = 0;
  Real imEnergyError = 0;

  for (unsigned i = 0; i < 100 * nTs; i++) {
    Vector<Complex> zi = c.f((i + 1.0) / (100.0 * nTs + 1.0));
    imEnergyError += pow(std::imag(M.getHamiltonian(zi) - M.getHamiltonian(zMin)), 2);
    constraintError += pow(((Complex)(zi.transpose() * zi) - (Complex)N), 2);
  }

  file << nGs << " " << nTs << std::endl;;
  file << c.totalCost(100 * nTs) / (100 * nTs) << " " << sqrt(imEnergyError) / (100 * nTs) << " " << sqrt(constraintError) / (100.0 * nTs) << std::endl;
  for (const Vector<Complex>& gi : c.gs) {
    file << gi.transpose() << std::endl;
  }
}