Bridge++  Ver. 2.0.2
projection_Stout_SU3.cpp
Go to the documentation of this file.
1 
14 #include "projection_Stout_SU3.h"
15 
16 #ifdef USE_FACTORY_AUTOREGISTER
17 namespace {
18  bool init = Projection_Stout_SU3::register_factory();
19 }
20 #endif
21 
22 const std::string Projection_Stout_SU3::class_name = "Projection_Stout_SU3";
23 
24 //====================================================================
26 {
27  std::string vlevel;
28  if (!params.fetch_string("verbose_level", vlevel)) {
29  m_vl = vout.set_verbose_level(vlevel);
30  }
31 }
32 
33 
34 //====================================================================
36 {
37  params.set_string("verbose_level", vout.get_verbose_level(m_vl));
38 }
39 
40 
41 //====================================================================
43 {
44  m_flop = 0;
45  m_time = 0.0;
46 
47  assert(CommonParameters::Nc() == NC);
48 
49  // strict check
50  if (CommonParameters::Nc() != NC) {
51  vout.crucial(m_vl, "Error at %s: Nc = 3 is needed, but Nc = %d\n", class_name.c_str(), CommonParameters::Nc());
52  exit(EXIT_FAILURE);
53  }
54 }
55 
56 
57 //====================================================================
59 {
60  const double gflops = 1.0e-9 * double(m_flop) / m_time;
61 
62  vout.general(m_vl, "%s:\n", class_name.c_str());
63  vout.general(m_vl, " total time: %f\n", m_time);
64  vout.general(m_vl, " total flop: %d\n", m_flop);
65  vout.general(m_vl, " GFlops : %f\n", gflops);
66 }
67 
68 
69 //====================================================================
71  const double alpha,
72  const Field_G& Cst, const Field_G& Uorg)
73 {
74  // int id = 31;
75  // KEK_FopCountStart(id);
76  const double time0 = Communicator::get_time();
77 
78  // in stout projection, parameter alpha is dummy.
79 
80  const int Nex = Uorg.nex();
81  const int Nvol = Uorg.nvol();
82  const int NinG = Uorg.nin();
83 
84  assert(Cst.nex() == Nex);
85  assert(Cst.nvol() == Nvol);
86  assert(U.nex() == Nex);
87  assert(U.nvol() == Nvol);
88 
89  Mat_SU_N iQ0(NC);
90  iQ0.unit();
91 
92  for (int mu = 0; mu < Nex; ++mu) {
93  for (int site = 0; site < Nvol; ++site) {
94  Mat_SU_N ut(NC);
95  Uorg.mat(ut, site, mu);
96 
97  Mat_SU_N ct(NC);
98  Cst.mat(ct, site, mu);
99 
100  Mat_SU_N iQ1(NC);
101  iQ1.mult_nd(ct, ut);
102  iQ1.at();
103 
104  Mat_SU_N iQ2(NC);
105  iQ2.mult_nn(iQ1, iQ1);
106 
107  Mat_SU_N iQ3(NC);
108  iQ3.mult_nn(iQ1, iQ2);
109 
110  Mat_SU_N e_iQ(NC);
111 
112  double norm = iQ1.norm2();
113  if (norm > 1.0e-10) {
114  double u, w;
115  set_uw(u, w, iQ2, iQ3);
116 
117  dcomplex f0, f1, f2;
118  set_fj(f0, f1, f2, u, w);
119 
120  for (int cc = 0; cc < NC * NC; ++cc) {
121  dcomplex qt = f0 * cmplx(iQ0.r(cc), iQ0.i(cc))
122  + f1 * cmplx(iQ1.i(cc), -iQ1.r(cc))
123  - f2 * cmplx(iQ2.r(cc), iQ2.i(cc));
124  e_iQ.set_r(cc, real(qt));
125  e_iQ.set_i(cc, imag(qt));
126  }
127  } else {
128  // vout.general(m_vl,"project: |iQ1|^2 too small: %lf. Set e_iQ=1.\n",norm);
129  e_iQ.unit();
130  }
131 
132  Mat_SU_N ut2(NC);
133  ut2.mult_nn(e_iQ, ut);
134  U.set_mat(site, mu, ut2);
135  }
136  }
137 
138  /*
139  unsigned long count;
140  double time;
141  KEK_FopCountFinish(id,&count,&time);
142  m_time += time;
143  m_flop += count;
144  */
145  const double time1 = Communicator::get_time();
146  m_time += time1 - time0;
147 }
148 
149 
150 //====================================================================
152 {
153  const int Nvol = iQ.nvol();
154  const int Nex = iQ.nex();
155 
156  Mat_SU_N iQ0(NC);
157 
158  iQ0.unit();
159 
160  for (int mu = 0; mu < Nex; ++mu) {
161  for (int site = 0; site < Nvol; ++site) {
162  Mat_SU_N iQ1 = iQ.mat(site, mu);
163  Mat_SU_N iQ2 = iQ1 * iQ1;
164  Mat_SU_N iQ3 = iQ1 * iQ2;
165 
166  double norm = iQ1.norm2();
167  if (norm > 1.0e-10) {
168  double u, w;
169  set_uw(u, w, iQ2, iQ3);
170 
171  dcomplex f0, f1, f2;
172  set_fj(f0, f1, f2, u, w);
173 
174  for (int cc = 0; cc < NC * NC; ++cc) {
175  dcomplex qt = f0 * cmplx(iQ0.r(cc), iQ0.i(cc))
176  + f1 * cmplx(iQ1.i(cc), -iQ1.r(cc))
177  - f2 * cmplx(iQ2.r(cc), iQ2.i(cc));
178  e_iQ.set_ri(cc, site, mu, real(qt), imag(qt));
179  }
180  } else {
181  // vout.general(m_vl,"exp_iQ: |iQ1|^2 too small: %lf. Set e_iQ=1.\n",norm);
182  e_iQ.set_mat(site, mu, iQ0);
183  }
184  }
185  }
186 }
187 
188 
189 //====================================================================
190 
203 //====================================================================
205  const double alpha, const Field_G& Sigmap,
206  const Field_G& Cst, const Field_G& Uorg)
207 {
208  // in stout projection, parameter alpha is dummy.
209 
210  // int id = 31;
211  // KEK_FopCountStart(id);
212  const double time0 = Communicator::get_time();
213 
214  const int Nvol = CommonParameters::Nvol();
215  const int Nex = Xi.nex();
216 
217  assert(Xi.nvol() == Nvol);
218  assert(iTheta.nvol() == Nvol);
219  assert(Sigmap.nvol() == Nvol);
220  assert(Cst.nvol() == Nvol);
221  assert(Uorg.nvol() == Nvol);
222  assert(iTheta.nex() == Nex);
223  assert(Sigmap.nex() == Nex);
224  assert(Cst.nex() == Nex);
225  assert(Uorg.nex() == Nex);
226 
227  Mat_SU_N iQ0(NC);
228  iQ0.unit();
229 
230  for (int mu = 0; mu < Nex; ++mu) {
231  for (int site = 0; site < Nvol; ++site) {
233  Mat_SU_N C_tmp(NC);
234  Cst.mat(C_tmp, site, mu);
235 
237  Mat_SU_N U_tmp(NC);
238  Uorg.mat(U_tmp, site, mu);
239 
240  // Sigmap_tmp \f$=\Sigma_\mu'(x)\f$
241  Mat_SU_N Sigmap_tmp(NC);
242  Sigmap.mat(Sigmap_tmp, site, mu);
243 
245  Mat_SU_N iQ1(NC);
246  iQ1.mult_nd(C_tmp, U_tmp);
247  iQ1.at();
248 
249  Mat_SU_N iQ2(NC);
250  iQ2.mult_nn(iQ1, iQ1);
251 
252  Mat_SU_N iQ3(NC);
253  iQ3.mult_nn(iQ1, iQ2);
254 
255  // In order to aviod 1Q1=0
256  Mat_SU_N e_iQ(NC), iGamma(NC);
257 
258  double norm = iQ1.norm2();
259  if (norm > 1.0e-10) {
260  double u, w;
261  set_uw(u, w, iQ2, iQ3);
262 
263  dcomplex f0, f1, f2;
264  set_fj(f0, f1, f2, u, w);
265 
266  for (int cc = 0; cc < NC * NC; ++cc) {
267  dcomplex qt = f0 * cmplx(iQ0.r(cc), iQ0.i(cc))
268  + f1 * cmplx(iQ1.i(cc), -iQ1.r(cc))
269  - f2 * cmplx(iQ2.r(cc), iQ2.i(cc));
270  e_iQ.set(cc, real(qt), imag(qt));
271  }
272 
273  double xi0 = func_xi0(w);
274  double xi1 = func_xi1(w);
275  double u2 = u * u;
276  double w2 = w * w;
277  double cos_w = cos(w);
278 
279  dcomplex emiu = cmplx(cos(u), -sin(u));
280  dcomplex e2iu = cmplx(cos(2.0 * u), sin(2.0 * u));
281 
282  dcomplex r01 = cmplx(2.0 * u, 2.0 * (u2 - w2)) * e2iu
283  + emiu * cmplx(16.0 * u * cos_w + 2.0 * u * (3.0 * u2 + w2) * xi0,
284  -8.0 * u2 * cos_w + 2.0 * (9.0 * u2 + w2) * xi0);
285 
286  dcomplex r11 = cmplx(2.0, 4.0 * u) * e2iu
287  + emiu * cmplx(-2.0 * cos_w + (3.0 * u2 - w2) * xi0,
288  2.0 * u * cos_w + 6.0 * u * xi0);
289 
290  dcomplex r21 = cmplx(0.0, 2.0) * e2iu
291  + emiu * cmplx(-3.0 * u * xi0, cos_w - 3.0 * xi0);
292 
293  dcomplex r02 = cmplx(-2.0, 0.0) * e2iu
294  + emiu * cmplx(-8.0 * u2 * xi0,
295  2.0 * u * (cos_w + xi0 + 3.0 * u2 * xi1));
296 
297  dcomplex r12 = emiu * cmplx(2.0 * u * xi0,
298  -cos_w - xi0 + 3.0 * u2 * xi1);
299 
300  dcomplex r22 = emiu * cmplx(xi0, -3.0 * u * xi1);
301 
302  double fden = 1.0 / (2 * (9.0 * u2 - w2) * (9.0 * u2 - w2));
303 
304  dcomplex b10 = cmplx(2.0 * u, 0.0) * r01 + cmplx(3.0 * u2 - w2, 0.0) * r02
305  - cmplx(30.0 * u2 + 2.0 * w2, 0.0) * f0;
306  dcomplex b11 = cmplx(2.0 * u, 0.0) * r11 + cmplx(3.0 * u2 - w2, 0.0) * r12
307  - cmplx(30.0 * u2 + 2.0 * w2, 0.0) * f1;
308  dcomplex b12 = cmplx(2.0 * u, 0.0) * r21 + cmplx(3.0 * u2 - w2, 0.0) * r22
309  - cmplx(30.0 * u2 + 2.0 * w2, 0.0) * f2;
310 
311  dcomplex b20 = r01 - cmplx(3.0 * u, 0.0) * r02 - cmplx(24.0 * u, 0.0) * f0;
312  dcomplex b21 = r11 - cmplx(3.0 * u, 0.0) * r12 - cmplx(24.0 * u, 0.0) * f1;
313  dcomplex b22 = r21 - cmplx(3.0 * u, 0.0) * r22 - cmplx(24.0 * u, 0.0) * f2;
314 
315  b10 *= cmplx(fden, 0.0);
316  b11 *= cmplx(fden, 0.0);
317  b12 *= cmplx(fden, 0.0);
318  b20 *= cmplx(fden, 0.0);
319  b21 *= cmplx(fden, 0.0);
320  b22 *= cmplx(fden, 0.0);
321 
322  Mat_SU_N B1(NC), B2(NC);
323  for (int cc = 0; cc < NC * NC; ++cc) {
324  dcomplex qt1 = b10 * cmplx(iQ0.r(cc), iQ0.i(cc))
325  + b11 * cmplx(iQ1.i(cc), -iQ1.r(cc))
326  - b12 * cmplx(iQ2.r(cc), iQ2.i(cc));
327  B1.set(cc, real(qt1), imag(qt1));
328 
329  dcomplex qt2 = b20 * cmplx(iQ0.r(cc), iQ0.i(cc))
330  + b21 * cmplx(iQ1.i(cc), -iQ1.r(cc))
331  - b22 * cmplx(iQ2.r(cc), iQ2.i(cc));
332  B2.set(cc, real(qt2), imag(qt2));
333  }
334 
335  Mat_SU_N USigmap(NC);
336  USigmap.mult_nn(U_tmp, Sigmap_tmp);
337 
338  Mat_SU_N tmp1(NC);
339  tmp1.mult_nn(USigmap, B1);
340 
341  Mat_SU_N tmp2(NC);
342  tmp2.mult_nn(USigmap, B2);
343 
344  dcomplex tr1 = cmplx(tmp1.r(0) + tmp1.r(4) + tmp1.r(8),
345  tmp1.i(0) + tmp1.i(4) + tmp1.i(8));
346  dcomplex tr2 = cmplx(tmp2.r(0) + tmp2.r(4) + tmp2.r(8),
347  tmp2.i(0) + tmp2.i(4) + tmp2.i(8));
348 
349  Mat_SU_N iQUS(NC);
350  iQUS.mult_nn(iQ1, USigmap);
351 
352  Mat_SU_N iUSQ(NC);
353  iUSQ.mult_nn(USigmap, iQ1);
354 
355  for (int cc = 0; cc < NC * NC; ++cc) {
356  dcomplex qt = tr1 * cmplx(iQ1.i(cc), -iQ1.r(cc))
357  - tr2 * cmplx(iQ2.r(cc), iQ2.i(cc))
358  + f1 * cmplx(USigmap.r(cc), USigmap.i(cc))
359  + f2 * cmplx(iQUS.i(cc), -iQUS.r(cc))
360  + f2 * cmplx(iUSQ.i(cc), -iUSQ.r(cc));
361  iGamma.set(cc, -imag(qt), real(qt));
362  }
363  } else {
364  // vout.general(m_vl,"force_recursive: |iQ1|^2 too small: %lf. Set e_iQ=1.\n",norm);
365  iGamma.zero();
366  e_iQ.unit();
367  }
368 
370  iGamma.at();
371 
372  Mat_SU_N iTheta_tmp(NC);
373  iTheta_tmp.mult_nn(iGamma, U_tmp);
374 
376  iTheta.set_mat(site, mu, iTheta_tmp);
377 
378  Mat_SU_N Xi_tmp(NC);
379  Xi_tmp.mult_nn(Sigmap_tmp, e_iQ);
380  Xi_tmp.multadd_dn(C_tmp, iGamma);
381 
383  Xi.set_mat(site, mu, Xi_tmp);
384  }
385  }
386 
387  /*
388  unsigned long count;
389  double time;
390  KEK_FopCountFinish(id,&count,&time);
391  m_time += time;
392  m_flop += count;
393  */
394  const double time1 = Communicator::get_time();
395  m_time += time1 - time0;
396 }
397 
398 
399 //====================================================================
400 void Projection_Stout_SU3::set_fj(dcomplex& f0, dcomplex& f1, dcomplex& f2,
401  const double& u, const double& w)
402 {
403  const double xi0 = func_xi0(w);
404  const double u2 = u * u;
405  const double w2 = w * w;
406  const double cos_w = cos(w);
407 
408  const double cos_u = cos(u);
409  const double sin_u = sin(u);
410 
411  const dcomplex emiu = cmplx(cos_u, -sin_u);
412  const dcomplex e2iu = cmplx(cos_u * cos_u - sin_u * sin_u, 2.0 * sin_u * cos_u);
413 
414  const dcomplex h0 = e2iu * cmplx(u2 - w2, 0.0)
415  + emiu * cmplx(8.0 * u2 * cos_w, 2.0 * u * (3.0 * u2 + w2) * xi0);
416  const dcomplex h1 = cmplx(2 * u, 0.0) * e2iu
417  - emiu * cmplx(2.0 * u * cos_w, -(3.0 * u2 - w2) * xi0);
418  const dcomplex h2 = e2iu - emiu * cmplx(cos_w, 3.0 * u * xi0);
419 
420  const double fden = 1.0 / (9.0 * u2 - w2);
421 
422  //- output
423  f0 = h0 * fden;
424  f1 = h1 * fden;
425  f2 = h2 * fden;
426 }
427 
428 
429 //====================================================================
430 void Projection_Stout_SU3::set_uw(double& u, double& w,
431  const Mat_SU_N& iQ2, const Mat_SU_N& iQ3)
432 {
433  const double c0 = -(iQ3.i(0, 0) + iQ3.i(1, 1) + iQ3.i(2, 2)) / 3.0;
434  const double c1 = -0.5 * (iQ2.r(0, 0) + iQ2.r(1, 1) + iQ2.r(2, 2));
435  const double c13r = sqrt(c1 / 3.0);
436  const double c0max = 2.0 * c13r * c13r * c13r;
437 
438  const double theta = acos(c0 / c0max);
439 
440  //- output
441  u = c13r * cos(theta / 3.0);
442  w = sqrt(c1) * sin(theta / 3.0);
443 }
444 
445 
446 //====================================================================
447 double Projection_Stout_SU3::func_xi0(const double w)
448 {
449  if (w == 0.0) {
450  return 1.0;
451  } else {
452  return sin(w) / w;
453  }
454 }
455 
456 
457 //====================================================================
458 double Projection_Stout_SU3::func_xi1(const double w)
459 {
460  if (w < 0.25) {
461  const double w2 = w * w;
462  const static double c0 = -1.0 / 3.0;
463  const static double c1 = 1.0 / 30.0;
464  const static double c2 = -1.0 / 840.0;
465  const static double c3 = 1.0 / 45360.0;
466  const static double c4 = -1.0 / 3991680.0;
467 
468  return c0 + w2 * (c1 + w2 * (c2 + w2 * (c3 + w2 * c4)));
469  } else {
470  return (w * cos(w) - sin(w)) / (w * w * w);
471  }
472 }
473 
474 
475 //====================================================================
477 {
478  // brute force version of exponentiation: for check
479 
480  const static int Nprec = 32;
481 
482  const int Nvol = iQ.nvol();
483  const int Nex = iQ.nex();
484 
485  for (int ex = 0; ex < Nex; ++ex) {
486  for (int site = 0; site < Nvol; ++site) {
487  Mat_SU_N u0(NC);
488  u0.unit();
489 
490  Mat_SU_N u1(NC);
491  u1.unit();
492 
493  Mat_SU_N h1 = iQ.mat(site, ex);
494 
495  for (int iprec = 0; iprec < Nprec; ++iprec) {
496  double exf = 1.0 / (Nprec - iprec);
497  Mat_SU_N u2 = h1 * u1;
498 
499  u2 *= exf;
500  u1 = u2;
501  u1 += u0;
502  }
503 
504  u1.reunit();
505  e_iQ.set_mat(site, ex, u1);
506  }
507  }
508 }
509 
510 
511 //====================================================================
512 //============================================================END=====
Projection_Stout_SU3::get_parameters
void get_parameters(Parameters &param) const
Definition: projection_Stout_SU3.cpp:35
Projection_Stout_SU3::m_flop
unsigned long int m_flop
Definition: projection_Stout_SU3.h:44
SU_N::Mat_SU_N::multadd_dn
void multadd_dn(const Mat_SU_N &u1, const Mat_SU_N &u2)
Definition: mat_SU_N.h:275
Communicator::get_time
static double get_time()
obtain a wall-clock time.
Definition: communicator.cpp:401
Parameters::set_string
void set_string(const string &key, const string &value)
Definition: parameters.cpp:39
Projection_Stout_SU3::print_stat
void print_stat()
Definition: projection_Stout_SU3.cpp:58
Projection_Stout_SU3::m_vl
Bridge::VerboseLevel m_vl
Definition: projection_Stout_SU3.h:42
Parameters
Class for parameters.
Definition: parameters.h:46
Projection_Stout_SU3::exp_iQ
void exp_iQ(Field_G &e_iQ, const Field_G &iQ)
Definition: projection_Stout_SU3.cpp:151
Projection_Stout_SU3::init
void init()
Definition: projection_Stout_SU3.cpp:42
Field_G::set_ri
void set_ri(const int cc, const int site, const int mn, const double re, const double im)
Definition: field_G.h:107
Field::nex
int nex() const
Definition: field.h:128
Field_G::set_mat
void set_mat(const int site, const int mn, const Mat_SU_N &U)
Definition: field_G.h:160
CommonParameters::Nvol
static int Nvol()
Definition: commonParameters.h:109
SU_N::Mat_SU_N::reunit
Mat_SU_N & reunit()
Definition: mat_SU_N.h:72
SU_N::Mat_SU_N::unit
Mat_SU_N & unit()
Definition: mat_SU_N.h:419
Field::nin
int nin() const
Definition: field.h:126
Projection_Stout_SU3::force_recursive
void force_recursive(Field_G &Xi, Field_G &iTheta, const double alpha, const Field_G &Sigmap, const Field_G &C, const Field_G &U)
determination of fields for force calculation
Definition: projection_Stout_SU3.cpp:204
SU_N::Mat_SU_N::set
void set(int c, const double &re, const double &im)
Definition: mat_SU_N.h:137
Projection_Stout_SU3::set_parameters
void set_parameters(const Parameters &param)
Definition: projection_Stout_SU3.cpp:25
CommonParameters::Nc
static int Nc()
Definition: commonParameters.h:115
Projection_Stout_SU3::m_time
double m_time
Definition: projection_Stout_SU3.h:45
NC
#define NC
Definition: field_F_imp_SU2-inc.h:2
Projection_Stout_SU3::exp_iQ_bf
void exp_iQ_bf(Field_G &e_iQ, const Field_G &iQ)
Definition: projection_Stout_SU3.cpp:476
Projection_Stout_SU3::class_name
static const std::string class_name
Definition: projection_Stout_SU3.h:39
SU_N::Mat_SU_N::zero
Mat_SU_N & zero()
Definition: mat_SU_N.h:429
Projection_Stout_SU3::set_fj
void set_fj(dcomplex &f0, dcomplex &f1, dcomplex &f2, const double &u, const double &w)
Definition: projection_Stout_SU3.cpp:400
Projection_Stout_SU3::set_uw
void set_uw(double &u, double &w, const Mat_SU_N &iQ2, const Mat_SU_N &iQ3)
Definition: projection_Stout_SU3.cpp:430
SU_N::Mat_SU_N
Definition: mat_SU_N.h:36
SU_N::Mat_SU_N::at
Mat_SU_N & at()
antihermitian traceless
Definition: mat_SU_N.h:375
SU_N::Mat_SU_N::r
double r(int c) const
Definition: mat_SU_N.h:115
SU_N::Mat_SU_N::mult_nn
void mult_nn(const Mat_SU_N &u1, const Mat_SU_N &u2)
Definition: mat_SU_N.h:189
Field::nvol
int nvol() const
Definition: field.h:127
Projection_Stout_SU3::func_xi1
double func_xi1(const double w)
Definition: projection_Stout_SU3.cpp:458
SU_N::Mat_SU_N::set_i
void set_i(int c, const double &im)
Definition: mat_SU_N.h:124
SU_N::Mat_SU_N::set_r
void set_r(int c, const double &re)
Definition: mat_SU_N.h:123
Bridge::BridgeIO::set_verbose_level
static VerboseLevel set_verbose_level(const std::string &str)
Definition: bridgeIO.cpp:133
Projection_Stout_SU3::project
void project(Field_G &U, const double alpha, const Field_G &C, const Field_G &Uorg)
projection U = P[alpha, C, Uorg]
Definition: projection_Stout_SU3.cpp:70
SU_N::Mat_SU_N::i
double i(int c) const
Definition: mat_SU_N.h:116
Parameters::fetch_string
int fetch_string(const string &key, string &value) const
Definition: parameters.cpp:378
Bridge::BridgeIO::crucial
void crucial(const char *format,...)
Definition: bridgeIO.cpp:180
Projection_Stout_SU3::func_xi0
double func_xi0(const double w)
Definition: projection_Stout_SU3.cpp:447
SU_N::Mat_SU_N::mult_nd
void mult_nd(const Mat_SU_N &u1, const Mat_SU_N &u2)
Definition: mat_SU_N.h:223
Field_G::mat
Mat_SU_N mat(const int site, const int mn=0) const
Definition: field_G.h:114
projection_Stout_SU3.h
Field_G
SU(N) gauge field.
Definition: field_G.h:38
Bridge::BridgeIO::general
void general(const char *format,...)
Definition: bridgeIO.cpp:200
Bridge::vout
BridgeIO vout
Definition: bridgeIO.cpp:512
Bridge::BridgeIO::get_verbose_level
static std::string get_verbose_level(const VerboseLevel vl)
Definition: bridgeIO.cpp:154
SU_N::Mat_SU_N::norm2
double norm2()
Definition: mat_SU_N.h:181