flexiblesusy is hosted by Hepforge, IPPP Durham
FlexibleSUSY
lattice_solver.cpp
Go to the documentation of this file.
1#include <iomanip>
2#include <algorithm>
3#include <cassert>
4#include <gsl/gsl_spline.h>
5
6#include "mathdefs.hpp"
7#include "lattice_model.hpp"
10#include "lattice_solver.hpp"
11#include "rk.hpp"
12#include "logger.hpp"
13
14
15namespace flexiblesusy {
16
17using namespace std;
18
19
20ostream& operator<<(ostream &out, const RGFlow<Lattice>& f)
21{
22 for (size_t T = 0; T < f.efts.size(); T++) {
23 out << "EFT " << T << '\n';
24 for (size_t m = 0; m < f.efts[T].height; m++) {
25 out << m;
26 for (size_t i = 0; i < f.efts[T].w->width; i++)
27 out << ' ' << f.y(T,m,i)*f.efts[T].units[i];
28 out << '\n';
29 }
30 }
31 return out;
32}
33
34int Lattice_model::run_to(double, double /* eps */)
35{
36 // TODO: slide scale pointer
37 return 0;
38}
39
41(Lattice_model *model, const vector<SingleSiteConstraint*>& cs,
42 InterTheoryConstraint* m, RGFlow *flow) :
43 EFT(model, flow), constraints(cs), matching(m)
44{
45}
46
48 tiny_dy(1e-2), huge_dy(100),
49 max_a_steps(1024), max_iter(100),
50 units_set(false), hybrid(false), scl0(1),
51 multithreading(true)
52{
53}
54
56{
57 delete A_;
58 for (auto i: teqidx) delete constraints[i];
59 for (auto i: rgeidx) delete constraints[i];
60}
61
63(Lattice_model *model, const vector<SingleSiteConstraint*>& constraints)
64{
65 add_model(model, nullptr, constraints);
66}
67
69(Lattice_model *model, InterTheoryConstraint *matching,
70 const vector<SingleSiteConstraint*>& constraints)
71{
72 efts.emplace_back(model, constraints, matching, this);
73}
74
76(Lattice_model *model,
77 const vector<SingleSiteConstraint*>& upward_constraints,
78 const vector<SingleSiteConstraint*>& downward_constraints)
79{
80 add_model(model, nullptr, upward_constraints, downward_constraints);
81}
82
84(Lattice_model *model,
85 InterTheoryConstraint *matching,
86 const vector<SingleSiteConstraint*>& us,
87 const vector<SingleSiteConstraint*>& ds)
88{
89 using ci_t = vector<SingleSiteConstraint*>::const_iterator;
90
91 vector<SingleSiteConstraint*> rs(ds.size());
92 reverse_copy(ds.begin(), ds.end(), rs.begin());
93
94 vector<SingleSiteConstraint*> combined;
95 auto pu = us.begin();
96 ci_t pr = rs.begin();
97
98 while (pu != us.cend() || pr != rs.cend()) {
99 auto pun = find(pu, us.cend(), pr != rs.cend() ? *pr : nullptr);
100 auto prn = find(pr, rs.cend(), pu != us.cend() ? *pu : nullptr);
101
102 if (pun == pu && prn == pr) {
103 assert(*pu == *pr);
104 combined.push_back(*pu);
105 pu++; pr++;
106 }
107 else if ((pr == rs.cend() && pu != us.cend()) ||
108 (prn == rs.cend() && pun != us.cend()))
109 while (pu != pun)
110 combined.push_back(*pu++);
111 else if ((pu == us.cend() && pr != rs.cend()) ||
112 (pun == us.cend() && prn != rs.cend()))
113 while (pr != prn)
114 combined.push_back(*pr++);
115 else {
116 stringstream msg;
117 msg << "RGFlow<Lattice>::Error: failed to combine upward "
118 "and downward constraints in model" << model->name();
119 throw SetupError(msg.str());
120 }
121 }
122#ifdef ENABLE_VERBOSE
123 {
124 stringstream uss, rss, css;
125 for (auto c: us ) uss << ' ' << c;
126 for (auto c: rs ) rss << ' ' << c;
127 for (auto c: combined) css << ' ' << c;
128 VERBOSE_MSG(" upward constraints:" << uss.str() << "\n"
129 "reversed downward constraints:" << rss.str() << "\n"
130 " combined constraints:" << css.str());
131 }
132#endif
133 add_model(model, matching, combined);
134}
135
137{
138 // TODO: do something reasonable
139}
140
142{
143 // TODO: do something reasonable
144}
145
147{
148 // TODO: do something reasonable
149}
150
152{
153 init_profile = guesser;
154 init_profile->init(this);
155}
156
158{
159 if (efts.empty())
160 throw SetupError("RGFlow<Lattice>::Error: EFT tower empty");
161
162 init_lattice();
163 create_threads();
164 increase_a();
165 if (hybrid) rk_stage();
166 else increase_density();
167 join_threads();
168}
169
171{
172 size_t max_width = 0;
173 size_t offset = 0;
174 for (size_t T = 0; T < efts.size(); T++) {
175 efts[T].w->init(this, T);
176 size_t height = !!T;
177 for (auto c: efts[T].constraints)
178 c->init(this, T, height++);
179 if (efts[T].matching) {
180 efts[T].matching->init(this, T);
181 height++;
182 }
183 efts[T].height = height;
184 efts[T].T = T;
185 efts[T].offset = offset;
186 size_t width = efts[T].w->width;
187 if (width > max_width) max_width = width;
188 offset += width * height;
189 }
190 y_.resize(offset);
191 z.resize(offset);
192 row_pool.resize(offset);
193 init_free_row_list();
194
195 for (size_t T = 0; T < efts.size(); T++) {
196 for (size_t m = 0; m < efts[T].height-1; m++) {
197 teqidx.push_back(constraints.size());
198 auto *teq = new Uniform_dt;
199 teq->init(this, T, m, 2);
200 constraints.push_back(teq);
201
202 rgeidx.push_back(constraints.size());
203 auto *rge = new Lattice_RGE;
204 rge->init(this, T, m, 2);
205 constraints.push_back(rge);
206 }
207 for (auto c: efts[T].constraints)
208 constraints.push_back(c);
209 if (efts[T].matching)
210 constraints.push_back(efts[T].matching);
211 }
212
213 for (auto c: constraints) c->alloc_rows();
214 sort_rows();
215
216 N = y_.size();
217 KL = KU = 2*max_width;
218 LDA = 2*KL + KU + 1;
219 IPIV.resize(N);
220 A_ = new band_matrix<Real>(N, KL, KU, LDA);
221 if (A_ == nullptr)
222 throw MemoryError("RGFlow<Lattice>::Error: failed to allocate matrix");
223}
224
226{
227 enum { END, INIT, RUN } state = INIT;
228 size_t a_steps = 1;
229
230 VERBOSE_MSG("\n\nentering a-loop with a_steps=" << a_steps);
231 while (state != END) {
232 (*init_profile)();
233 if (state == INIT) {
234 VERBOSE_MSG("initial RG flow:\n" << *this);
235 state = RUN;
236 }
237
238 for (size_t a_i = 0; a_i <= a_steps; a_i++) {
239 a = Real(a_i)/a_steps;
240 VERBOSE_MSG("\n\nentering Newton loop with a=" <<
241 a_i << '/' << a_steps);
242 Inner_status s = iterate();
243 switch (s) {
244 case JUMPED:
245 a_steps *= 2;
246 if (a_steps <= max_a_steps) {
247 VERBOSE_MSG("RG flow jumped, restarting a-loop "
248 "with doubled a_steps=" << a_steps);
249 goto end_outer;
250 }
251 else
252 throw DivergenceError
253 ("RGFlow<Lattice>::Error: Newton iterations diverged");
254 case ENDLESS:
255 a_steps *= 2;
256 if (a_steps <= max_a_steps) {
257 VERBOSE_MSG("Newton iterations do not converge, "
258 "restarting a-loop "
259 "with doubled a_steps=" << a_steps);
260 goto end_outer;
261 }
262 else
263 throw NoConvergenceError(max_iter);
264 default:
265 VERBOSE_MSG(*this);
266 break;
267 }
268 }
269 VERBOSE_MSG("exiting a-loop");
270 state = END;
271 end_outer:
272 ;
273 }
274}
275
277{
278 VERBOSE_MSG("\n\nbeginning to increase lattice density");
279
280 for (;;) {
281 RVec old_y = y_;
282 vector<size_t> old_heights(efts.size());
283 vector<size_t> old_offsets(efts.size());
284 for (size_t T = 0; T < efts.size(); T++) {
285 old_heights[T] = efts[T].height;
286 old_offsets[T] = efts[T].offset;
287 }
288 vector<vector<size_t>> site_maps = refine_lattice();
289 stringstream heights;
290#ifdef ENABLE_VERBOSE
291 for (auto& e: efts) heights << ' ' << e.height;
292 VERBOSE_MSG("\n\nentering Newton loop with heights:" <<
293 heights.str());
294#endif
295 Inner_status s = iterate();
296 switch (s) {
297 case JUMPED:
298 throw DivergenceError("RGFlow<Lattice>::Error: RG flow jumped, "
299 "this cannot happen");
300 case ENDLESS:
301 throw NoConvergenceError(max_iter);
302 default:
303 Real maxdy = 0;
304 for (size_t T = 0; T < efts.size(); T++)
305 for (size_t m = 0; m < old_heights[T]; m++)
306 for (size_t i = 0; i < efts[T].w->width; i++) {
307 Real diff =
308 fabs(y(T,site_maps[T][m],i) -
309 old_y[old_offsets[T]+m*efts[T].w->width+i]);
310 if (diff > maxdy) maxdy = diff;
311 }
312 VERBOSE_MSG("maxdy=" << maxdy);
313 if (maxdy < tiny_dy) {
314 VERBOSE_MSG("discretization fine enough");
315 return;
316 }
317 break;
318 }
319 }
320}
321
322vector<vector<size_t>> RGFlow<Lattice>::refine_lattice()
323{
324 size_t T_top = efts.size() - 1;
325 Real t_top = x(T_top,efts[T_top].height-1,0);
326 Real t_bot = x(0,0,0);
327 Real min_Dt = t_top - t_bot + 1;
328 Real max_Dt = 0;
329 for (size_t T = 0; T < efts.size(); T++) {
330 for (size_t m = 0; m < efts[T].height-1; m++) {
331 Real Dt = x(T,m+1,0) - x(T,m,0);
332 if (Dt > max_Dt) max_Dt = Dt;
333 if (Dt < min_Dt) min_Dt = Dt;
334 }
335 }
336
337 Real spacing = max_Dt > 2*min_Dt ? min_Dt : min_Dt/2;
338 vector<vector<size_t>> site_maps(efts.size());
339 for (size_t T = 0; T < efts.size(); T++) {
340 size_t new_m = 0;
341 site_maps[T].push_back(new_m);
342 for (size_t m = 0; m < efts[T].height-1; m++) {
343 Real Dt = x(T,m+1,0) - x(T,m,0);
344 size_t q = Dt / spacing + 0.5;
345 site_maps[T].push_back(new_m += q);
346 }
347 }
348
349 resample(site_maps);
350
351 return site_maps;
352}
353
355{
356 VERBOSE_MSG("\n\nentering Runge-Kutta stage");
357 enable_Runge_Kutta();
358 VERBOSE_MSG("\n\nentering Newton loop");
359 Inner_status s = iterate();
360 switch (s) {
361 case JUMPED:
362 throw DivergenceError("RGFlow<Lattice>::Error: RG flow jumped, "
363 "this cannot happen");
364 case ENDLESS:
365 throw NoConvergenceError(max_iter);
366 default:
367 break;
368 }
369 VERBOSE_MSG("exiting Runge-Kutta stage");
370}
371
373{
374 join_threads();
375
376 vector<vector<bool>> original(efts.size());
377 for (size_t T = efts.size(); T--; ) {
378 original[T].resize(efts[T].height);
379 for (auto c: efts[T].constraints)
380 original[T][c->mbegin] = true;
381 if (efts[T].matching)
382 original[T][efts[T].height-1] = original[T+1][0] = true;
383 }
384
385 vector<vector<size_t>> site_maps(efts.size());
386 for (size_t T = 0; T < efts.size(); T++) {
387 site_maps[T].resize(efts[T].height);
388 for (size_t m = 0, new_m = 0; m < efts[T].height; m++) {
389 site_maps[T][m] = new_m;
390 if (original[T][m]) new_m++;
391 }
392 }
393
394 resample(site_maps);
395
396 VERBOSE_MSG("switching to Runge-Kutta RGEs");
397 for (size_t i = 0, T = 0; T < efts.size(); T++)
398 for (size_t m = 0; m < efts[T].height-1; m++, i++) {
399 constraints[rgeidx[i]]->free_rows();
400 constraints[rgeidx[i]]->deactivate();
401 delete constraints[rgeidx[i]];
402 auto *rkrge = new Lattice_RKRGE;
403 rkrge->init(this, T, m, 2);
404 constraints[rgeidx[i]] = rkrge;
405 }
406 for (auto i: rgeidx) constraints[i]->alloc_rows();
407 sort_rows();
408
409 create_threads();
410}
411
413{
414 join_threads();
415
416 VERBOSE_MSG("switching to difference RGEs");
417 for (size_t i = 0, T = 0; T < efts.size(); T++)
418 for (size_t m = 0; m < efts[T].height-1; m++, i++) {
419 constraints[rgeidx[i]]->free_rows();
420 constraints[rgeidx[i]]->deactivate();
421 delete constraints[rgeidx[i]];
422 auto *rge = new Lattice_RGE;
423 rge->init(this, T, m, 2);
424 constraints[rgeidx[i]] = rge;
425 }
426 for (auto i: rgeidx) constraints[i]->alloc_rows();
427 sort_rows();
428
429 create_threads();
430}
431
432void RGFlow<Lattice>::resample(const vector<vector<size_t>>& site_maps)
433{
434 vector<size_t> new_heights(efts.size());
435 vector<size_t> new_offsets(efts.size());
436 size_t offset = 0;
437 for (size_t T = 0; T < efts.size(); T++) {
438 new_heights[T] = site_maps[T][efts[T].height-1] + 1;
439 new_offsets[T] = offset;
440 offset += efts[T].w->width * new_heights[T];
441 }
442#ifdef ENABLE_VERBOSE
443 for (size_t T = 0; T < efts.size(); T++) {
444 stringstream maps;
445 maps << "EFT " << T << ":";
446 for (size_t m = 0; m < efts[T].height; m++)
447 maps << ' ' << m << "->" << site_maps[T][m];
448 VERBOSE_MSG(maps.str());
449 }
450#endif
451
452 RVec new_y(offset);
453 for (size_t T = 0; T < efts.size(); T++) {
454 RVec y0(efts[T].height);
455 for (size_t m = 0; m < efts[T].height; m++) {
456 size_t new_m = site_maps[T][m];
457 y0[m] = new_y[new_offsets[T] + new_m*efts[T].w->width] = y(T,m,0);
458 }
459 for (size_t m = 0; m < efts[T].height-1; m++) {
460 size_t q = site_maps[T][m+1] - site_maps[T][m];
461 for (size_t n = 1; n < q; n++) {
462 size_t new_m = site_maps[T][m] + n;
463 new_y[new_offsets[T] + new_m*efts[T].w->width] =
464 ((q-n)*y(T,m,0) + n*y(T,m+1,0)) / q;
465 }
466 }
467 RVec yi(efts[T].height);
468 for (size_t i = 1; i < efts[T].w->width; i++) {
469 gsl_interp_accel *acc = gsl_interp_accel_alloc();
470 const gsl_interp_type *itype =
471 efts[T].height > 2 ? gsl_interp_cspline : gsl_interp_linear;
472 gsl_spline *spl = gsl_spline_alloc(itype, efts[T].height);
473 for (size_t m = 0; m < efts[T].height; m++) yi[m] = y(T,m,i);
474 gsl_spline_init(spl, &y0[0], &yi[0], efts[T].height);
475 for (size_t m = 0; m < new_heights[T]; m++)
476 new_y[new_offsets[T] + m*efts[T].w->width + i] =
477 gsl_spline_eval
478 (spl, new_y[new_offsets[T] + m*efts[T].w->width], acc);
479 gsl_spline_free(spl);
480 gsl_interp_accel_free(acc);
481 }
482 }
483
484 for (auto c: constraints) c->free_rows();
485 y_ = new_y;
486 z.resize(offset);
487 row_pool.resize(offset);
488 init_free_row_list();
489 for (auto c: constraints) c->relocate(site_maps);
490 for (size_t T = 0; T < efts.size(); T++) {
491 efts[T].height = new_heights[T];
492 efts[T].offset = new_offsets[T];
493 }
494 for (auto c: constraints) c->alloc_rows();
495 sort_rows();
496
497 N = y_.size();
498 IPIV.resize(N);
499 delete A_;
500 A_ = new band_matrix<Real>(N, KL, KU, LDA);
501 if (A_ == nullptr)
502 throw MemoryError("RGFlow<Lattice>::Error: failed to allocate matrix");
503}
504
506{
507 for (size_t T = 0; T < efts.size(); T++) {
508 for (size_t i = 0; i < efts[T].w->width; i++) {
509 Real miny = y(T,0,i);
510 Real maxy = miny;
511 for (size_t m = 0; m < efts[T].height; m++) {
512 if (y(T,m,i) < miny) miny = y(T,m,i);
513 if (y(T,m,i) > maxy) maxy = y(T,m,i);
514 }
515 efts[T].units[i] = max(maxy-miny,max(fabs(maxy),fabs(miny)));
516 if (efts[T].units[i] == 0) {
517 VERBOSE_MSG("no hint about unit of x[" << i << "] in EFT "
518 << T << ", defaulting to 1");
519 efts[T].units[i] = 1;
520 }
521 for (size_t m = 0; m < efts[T].height; m++)
522 y(T,m,i) /= efts[T].units[i];
523 }
524 }
525}
526
528{
529 A_->clear();
530
531 if (multithreading) {
532 threads_begin->wait();
533 (**elementary_constraints.begin())();
534 threads_end->wait();
535 }
536 else
537 for (auto c: elementary_constraints) (*c)();
538
539 // for (auto c: constraints) (*c)();
540}
541
543{
544 while (threads_begin->wait(), keep_threads) {
545 (*c)();
546 threads_end->wait();
547 }
548}
549
551{
552 if (!multithreading) return;
553
554 threads_begin = new boost::barrier(elementary_constraints.size());
555 threads_end = new boost::barrier(elementary_constraints.size());
556 keep_threads = true;
557 threads = new boost::thread_group;
558 for (auto c: elementary_constraints)
559 if (c != *elementary_constraints.begin())
560 threads->add_thread(
561 new boost::thread
563 VERBOSE_MSG("launched " << threads->size() << " subthreads");
564}
565
567{
568 if (!multithreading) return;
569
570 keep_threads = false;
571 threads_begin->wait();
572 threads->join_all();
573 VERBOSE_MSG("joined " << threads->size() << " subthreads");
574 delete threads;
575 delete threads_begin;
576 delete threads_end;
577}
578
580{
581 assert(y0.size() == y1.size());
582 Real max = 0;
583 auto p = y0.begin();
584 auto q = y1.begin();
585 while (p < y0.end()) {
586 Real diff = fabs(*p++ - *q++);
587 if (diff > max) max = diff;
588 }
589 return max;
590}
591
593(size_t T, size_t m, size_t span)
594{
595 EqRow *r = free_row_list_head;
596 assert(r != nullptr);
597 if (r != nullptr) {
598 free_row_list_head = r->next;
599 r->rowSpec = { T, m, span, 0/* to be determined by sort_rows() */ };
600 }
601 return r;
602}
603
605{
606 r->next = free_row_list_head;
607 free_row_list_head = r;
608}
609
611{
612 if (free_row_list_head != nullptr)
613 throw SetupError("RGFlow<Lattice>::Error: constraints not enough");
614 vector<EqRow *> layout(row_pool.size());
615 for (size_t r = 0; r < layout.size(); r++)
616 layout[r] = &row_pool[r];
617 sort(layout.begin(), layout.end(),
618 [](EqRow *a, EqRow *b) -> bool {
619 if (a->rowSpec.T < b->rowSpec.T) return true;
620 if (a->rowSpec.T > b->rowSpec.T) return false;
621 if (a->rowSpec.m < b->rowSpec.m) return true;
622 if (a->rowSpec.m > b->rowSpec.m) return false;
623 if (a->rowSpec.n < b->rowSpec.n) return true;
624 return false;
625 });
626 for (size_t r = 0; r < layout.size(); r++)
627 layout[r]->rowSpec.realRow = r;
628}
629
631{
632 for (size_t r = 0; r < row_pool.size() - 1; r++)
633 row_pool[r].next = &row_pool[r+1];
634 row_pool.back().next = nullptr;
635 free_row_list_head = &row_pool[0];
636}
637
638extern "C" void dgbsv_
639(const int& N, const int& KL, const int& KU, const int& NRHS,
640 double *AB, const int& LDAB, int *IPIV, double *B, const int& LDB, int *INFO);
641
643{
644 if (!units_set) { set_units(); units_set = true; }
645
646 // const Real epsdy = 1e-8;
647 // const Real jumpdy = .5; // TODO: find a better criterion
648 size_t iter = 0;
649 enum { END, INIT } state = INIT;
650
651 int NRHS = 1;
652 int LDB = N;
653 int INFO;
654
655 while (iter < max_iter && state != END) {
656 iter++;
657 apply_constraints();
658#ifdef DUMP_MATRIX
659 cout << setprecision(15) << scientific;
660 for (size_t i = 0; i < y_.size(); i++) {
661 for (size_t j = 0; j < y_.size(); j++) {
662 if (j) cout << " ";
663 if (abs(signed(i)-signed(j)) < KL) cout << (*A_)(i,j);
664 else cout << 0;
665 }
666 cout << "\n";
667 }
668#endif
669 dgbsv_(N,KL,KU,NRHS,A_->pointer(),LDA,&IPIV[0],&z[0],LDB,&INFO);
670 assert(INFO >= 0);
671 if (INFO > 0) {
672 stringstream msg;
673 msg << "RGFlow<Lattice>::Error: failed to solve equations, "
674 "DGBSV returned INFO = " << INFO;
675 throw NonInvertibleMatrixError(msg.str());
676 }
677 Real maxdy = maxdiff(y_, z);
678 VERBOSE_MSG("iter=" << iter << " maxdy=" << maxdy);
679 if (maxdy < tiny_dy)
680 state = END;
681 else if (maxdy > huge_dy)
682 return JUMPED;
683 y_ = z;
684 }
685
686 if (state == END) {
687 VERBOSE_MSG("converged after " << iter << " Newton iterations");
688 return CONVERGED;
689 }
690 else
691 return ENDLESS;
692}
693
694} // namespace flexiblesusy
virtual void init(RGFlow< Lattice > *flow)
virtual void init(RGFlow< Lattice > *flow, size_t theory, size_t site, size_t span_)
void init(RGFlow< Lattice > *flow, size_t theory, size_t site, size_t span)
void init(RGFlow< Lattice > *flow, size_t theory, size_t site, size_t span)
virtual int run_to(double, double eps=-1.0)
No convergence while solving the RGEs.
Definition: error.hpp:57
void add_model(Lattice_model *model, const std::vector< SingleSiteConstraint * > &constraints)
Spectrum generator was not setup correctly.
Definition: error.hpp:46
#define INFO(msg)
Definition: logger.hpp:61
#define VERBOSE_MSG(msg)
Definition: logger.hpp:57
void() B(bb)) coeff_t &arr
std::complex< double > f(double tau) noexcept
double Real
Definition: mathdefs.hpp:12
std::vector< Real > RVec
Matching< Lattice > InterTheoryConstraint
std::ostream & operator<<(std::ostream &ostr, const Dynamic_array_view< ElementType > &av)
Definition: array_view.hpp:143
void sort(Eigen::Array< double, N, 1 > &v)
sorts an Eigen array
void dgbsv_(const int &N, const int &KL, const int &KU, const int &NRHS, double *AB, const int &LDAB, int *IPIV, double *B, const int &LDB, int *INFO)
Integration of ODEs by Runge-Kutta.