diff options
-rw-r--r-- | collectMorseData.hpp | 108 | ||||
-rw-r--r-- | pureMorse.cpp | 56 |
2 files changed, 164 insertions, 0 deletions
diff --git a/collectMorseData.hpp b/collectMorseData.hpp new file mode 100644 index 0000000..d63050d --- /dev/null +++ b/collectMorseData.hpp @@ -0,0 +1,108 @@ +#include "stokes.hpp" +#include "complex_normal.hpp" +#include <fstream> + +template<int ...ps, class Generator, typename... T> +void collectMorseData(std::string tag, unsigned N, Generator& r, Real ε, Real δz₀, bool minimum, bool spike, 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; + std::tie(Hx, std::ignore, std::ignore, std::ignore) = ReM.hamGradHess(xMin); + + 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); + + pSpinModel M = ReM; + Vector<Real> zMin = xMin; + + Vector<Real> zSaddle = zMin; + + Real δz = δz₀; + + while ((zSaddle - zMin).norm() < newSaddleThres * N) { + Vector<Real> z0 = normalize(zSaddle + δz * randomVector<Real>(N, Red, r)); + zSaddle = findSaddle(M, z0, ε); + δz *= 1.01; + } + + Real Hz; + Vector<Real> dHz; + Matrix<Real> ddHz; + std::tie(Hz, dHz, ddHz, std::ignore) = M.hamGradHess(zSaddle); + Matrix<Real> zHess = ddHz - (zSaddle.transpose() * dHz) * Matrix<Real>::Identity(N, N) / (Real)N; + zHess -= (zHess * zSaddle) * zSaddle.adjoint() / zSaddle.squaredNorm(); + Eigen::EigenSolver<Matrix<Real>> eigenSz(zHess); + + 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 << 0 << " " << (xMin - zSaddle).norm() << std::endl; + + unsigned nTest = 1000; + + file << nIts << " " << nGs << " " << coDim << " " << nTest << std::endl; + + std::vector<Vector<Real>> 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<Real> zi = c.f(t); + Real constraintError = (Real)(zi.transpose() * zi) - (Real)N; + reConstraintError += pow(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<Real>& gi : c.gs) { + file << gi.transpose() << std::endl; + } + } +} diff --git a/pureMorse.cpp b/pureMorse.cpp new file mode 100644 index 0000000..f157c35 --- /dev/null +++ b/pureMorse.cpp @@ -0,0 +1,56 @@ +#include <getopt.h> +#include <chrono> + +#include "collectMorseData.hpp" + +#include "pcg-cpp/include/pcg_random.hpp" +#include "randutils/randutils.hpp" + +using Rng = randutils::random_generator<pcg32>; + +int main(int argc, char* argv[]) { + // model parameters + unsigned N = 10; // number of spins + // simulation parameters + Real ε = 1e-15; + Real δz₀ = 1e-3; + unsigned n = 10; + bool useMinima = false; + bool useSpike = false; + + int opt; + + while ((opt = getopt(argc, argv, "N:e:d:n:ms")) != -1) { + switch (opt) { + case 'N': + N = (unsigned)atof(optarg); + break; + case 'e': + ε = atof(optarg); + break; + case 'd': + δz₀ = atof(optarg); + break; + case 'n': + n = atof(optarg); + break; + case 'm': + useMinima = true; + break; + case 's': + useSpike = true; + break; + default: + exit(1); + } + } + + Rng r; + + for (unsigned i = 0; i < n; i++) { + auto tag = std::chrono::high_resolution_clock::now(); + collectMorseData<3>(std::to_string(tag.time_since_epoch().count()), N, r.engine(), ε, δz₀, useMinima, useSpike, 1.0); + } + + return 0; +} |