12 #ifndef MFEM_LINALG_KERNELS_HPP
13 #define MFEM_LINALG_KERNELS_HPP
15 #include "../config/config.hpp"
16 #include "../general/backends.hpp"
17 #include "../general/globals.hpp"
43 for (
int i = 0; i <
dim; i++) { d += (x[i]-y[i])*(x[i]-y[i]); }
49 MFEM_HOST_DEVICE
inline void Diag(
const double c,
double *data)
52 for (
int i = 0; i < N; i++) { data[i] = 0.0; }
53 for (
int i = 0; i <
dim; i++) { data[i*(dim+1)] = c; }
58 MFEM_HOST_DEVICE
inline void Subtract(
const double a,
59 const double *x,
const double *y,
62 for (
int i = 0; i <
dim; i++) { z[i] = a * (x[i] - y[i]); }
67 MFEM_HOST_DEVICE
inline void AddMultVWt(
const double *v,
const double *w,
70 for (
int i = 0; i <
dim; i++)
72 const double vi = v[i];
73 for (
int j = 0; j <
dim; j++) { VWt[i*dim+j] += vi * w[j]; }
77 template<
int H,
int W,
typename T>
78 MFEM_HOST_DEVICE
inline
79 void FNorm(
double &scale_factor,
double &scaled_fnorm2,
const T *data)
82 T max_norm = 0.0, entry, fnorm2;
84 for (i = 0; i < hw; i++)
86 entry = fabs(data[i]);
95 scale_factor = scaled_fnorm2 = 0.0;
100 for (i = 0; i < hw; i++)
102 entry = data[i] / max_norm;
103 fnorm2 += entry * entry;
106 scale_factor = max_norm;
107 scaled_fnorm2 = fnorm2;
111 template<
int H,
int W,
typename T>
112 MFEM_HOST_DEVICE
inline
116 kernels::FNorm<H,W>(
s, n2, data);
121 template<
int H,
int W,
typename T>
122 MFEM_HOST_DEVICE
inline
126 kernels::FNorm<H,W>(
s, n2, data);
132 MFEM_HOST_DEVICE
inline
133 double Norml2(
const int size,
const T *data)
135 if (0 == size) {
return 0.0; }
136 if (1 == size) {
return std::abs(data[0]); }
139 for (
int i = 0; i < size; i++)
143 const T absdata = fabs(data[i]);
144 if (scale <= absdata)
146 const T sqr_arg = scale / absdata;
147 sum = 1.0 + sum * (sqr_arg * sqr_arg);
151 const T sqr_arg = absdata / scale;
152 sum += (sqr_arg * sqr_arg);
155 return scale * sqrt(sum);
161 template<
typename TA,
typename TX,
typename TY>
162 MFEM_HOST_DEVICE
inline
163 void Mult(
const int height,
const int width,
const TA *data,
const TX *x, TY *y)
167 for (
int row = 0; row < height; row++)
173 const TA *d_col = data;
175 for (
int row = 0; row < height; row++)
177 y[row] = x_col*d_col[row];
180 for (
int col = 1; col < width; col++)
183 for (
int row = 0; row < height; row++)
185 y[row] += x_col*d_col[row];
194 template<
typename TA,
typename TX,
typename TY>
195 MFEM_HOST_DEVICE
inline
201 for (
int row = 0; row < width; row++)
208 for (
int i = 0; i < width; ++i)
211 for (
int j = 0; j < height; ++j)
213 val += x[j] * data[i * height + j];
222 MFEM_HOST_DEVICE
inline
225 for (
int i = 0; i < size; i++)
227 for (
int j = 0; j < i; j++)
229 const T
a = 0.5 * (data[i*size+j] + data[j*size+i]);
230 data[j*size+i] = data[i*size+j] =
a;
236 template<
int dim,
typename T>
237 MFEM_HOST_DEVICE
inline T
Det(
const T *data)
244 template<
int dim,
typename T>
245 MFEM_HOST_DEVICE
inline
249 const T det = TAdjDetHD<T>(layout_t(), data, layout_t(), inv_data);
250 TAssignHD<AssignOp::Mult>(layout_t(), inv_data,
static_cast<T
>(1.0)/det);
254 template<
int dim,
typename T>
255 MFEM_HOST_DEVICE
inline
259 TAdjugateHD<T>(layout_t(), data, layout_t(), adj_data);
264 template<
typename TALPHA,
typename TA,
typename TB,
typename TC>
265 MFEM_HOST_DEVICE
inline
266 void Add(
const int height,
const int width,
const TALPHA
alpha,
267 const TA *Adata,
const TB *Bdata, TC *Cdata)
269 for (
int j = 0; j < width; j++)
271 for (
int i = 0; i < height; i++)
273 const int n = i*width+j;
274 Cdata[n] = Adata[n] + alpha * Bdata[n];
281 template<
typename TALPHA,
typename TBETA,
typename TA,
typename TB,
typename TC>
282 MFEM_HOST_DEVICE
inline
283 void Add(
const int height,
const int width,
284 const TALPHA
alpha,
const TA *Adata,
285 const TBETA beta,
const TB *Bdata,
288 const int m = height * width;
289 for (
int i = 0; i < m; i++)
291 Cdata[i] = alpha * Adata[i] + beta * Bdata[i];
297 template<
typename TA,
typename TB>
298 MFEM_HOST_DEVICE
inline
299 void Add(
const int height,
const int width,
const TA *Adata, TB *Bdata)
301 const int m = height * width;
302 for (
int i = 0; i < m; i++)
304 Bdata[i] += Adata[i];
310 template<
typename TA,
typename TB>
311 MFEM_HOST_DEVICE
inline
312 void Add(
const int height,
const int width,
313 const double alpha,
const TA *Adata, TB *Bdata)
315 const int m = height * width;
316 for (
int i = 0; i < m; i++)
318 Bdata[i] += alpha * Adata[i];
324 template<
typename TA,
typename TB>
325 MFEM_HOST_DEVICE
inline
326 void Set(
const int height,
const int width,
327 const double alpha,
const TA *Adata, TB *Bdata)
329 const int m = height * width;
330 for (
int i = 0; i < m; i++)
332 Bdata[i] = alpha * Adata[i];
339 template<
typename TA,
typename TB,
typename TC>
340 MFEM_HOST_DEVICE
inline
341 void Mult(
const int Aheight,
const int Awidth,
const int Bwidth,
342 const TB *Bdata,
const TC *Cdata, TA *Adata)
344 const int ah_x_aw = Aheight * Awidth;
345 for (
int i = 0; i < ah_x_aw; i++) { Adata[i] = 0.0; }
346 for (
int j = 0; j < Awidth; j++)
348 for (
int k = 0; k < Bwidth; k++)
350 for (
int i = 0; i < Aheight; i++)
352 Adata[i+j*Aheight] += Bdata[i+k*Aheight] * Cdata[k+j*Bwidth];
361 template<
typename TA,
typename TB,
typename TC>
362 MFEM_HOST_DEVICE
inline
363 void MultABt(
const int Aheight,
const int Awidth,
const int Bheight,
364 const TA *Adata,
const TB *Bdata, TC *ABtdata)
366 const int ah_x_bh = Aheight * Bheight;
367 for (
int i = 0; i < ah_x_bh; i++) { ABtdata[i] = 0.0; }
368 for (
int k = 0; k < Awidth; k++)
371 for (
int j = 0; j < Bheight; j++)
373 const double bjk = Bdata[j];
374 for (
int i = 0; i < Aheight; i++)
376 c[i] += Adata[i] * bjk;
388 template<
typename TA,
typename TB,
typename TC>
389 MFEM_HOST_DEVICE
inline
390 void MultAtB(
const int Aheight,
const int Awidth,
const int Bwidth,
391 const TA *Adata,
const TB *Bdata, TC *AtBdata)
394 for (
int i = 0; i < Bwidth; ++i)
396 for (
int j = 0; j < Awidth; ++j)
399 for (
int k = 0; k < Aheight; ++k)
401 val += Adata[j * Aheight + k] * Bdata[i * Aheight + k];
412 template<
int dim> MFEM_HOST_DEVICE
416 template<
int dim> MFEM_HOST_DEVICE
426 MFEM_HOST_DEVICE
static inline
437 MFEM_HOST_DEVICE
static inline
438 void Eigenvalues2S(
const double &d12,
double &d1,
double &d2)
440 const double sqrt_1_eps = sqrt(1./Epsilon);
445 const double zeta = (d2 - d1)/(2*d12);
446 if (fabs(zeta) < sqrt_1_eps)
448 t = d12*copysign(1./(fabs(zeta) + sqrt(1. + zeta*zeta)), zeta);
452 t = d12*copysign(0.5/fabs(zeta), zeta);
460 MFEM_HOST_DEVICE
static inline
461 void Eigensystem2S(
const double &d12,
double &d1,
double &d2,
462 double &c,
double &
s)
464 const double sqrt_1_eps = sqrt(1./Epsilon);
474 const double zeta = (d2 - d1)/(2*d12);
475 const double azeta = fabs(zeta);
476 if (azeta < sqrt_1_eps)
478 t = copysign(1./(azeta + sqrt(1. + zeta*zeta)), zeta);
482 t = copysign(0.5/azeta, zeta);
484 c = sqrt(1./(1. + t*t));
494 MFEM_HOST_DEVICE
static inline
495 void GetScalingFactor(
const double &d_max,
double &mult)
500 mult = frexp(d_max, &d_exp);
501 if (d_exp == std::numeric_limits<double>::max_exponent)
503 mult *= std::numeric_limits<double>::radix;
516 MFEM_HOST_DEVICE
static inline
517 bool KernelVector2G(
const int &mode,
518 double &d1,
double &d12,
double &d21,
double &d2)
529 double n1 = fabs(d1) + fabs(d21);
530 double n2 = fabs(d2) + fabs(d12);
532 bool swap_columns = (n2 > n1);
544 if (fabs(d1) > fabs(d21))
552 if (fabs(d1) < fabs(d21))
564 if (fabs(d12) > fabs(d2))
577 if (fabs(d12) < fabs(d2))
596 mu = copysign(n1, d1);
597 n1 = -d21*(d21/(d1 +
mu));
601 if (fabs(n1) <= fabs(d21))
605 mu = (2./(1. + n1*n1))*(n1*d12 + d2);
613 mu = (2./(1. + n2*n2))*(d12 + n2*d2);
635 n2 = 1./(1. + fabs(mu));
637 if (fabs(d1) <= n2*fabs(d2))
658 MFEM_HOST_DEVICE
static inline
659 void Vec_normalize3_aux(
const double &x1,
const double &x2,
661 double &n1,
double &n2,
double &n3)
665 const double m = fabs(x1);
669 t = sqrt(1./(t + r*r));
670 n1 = copysign(t, x1);
677 MFEM_HOST_DEVICE
static inline
678 void Vec_normalize3(
const double &x1,
const double &x2,
const double &x3,
679 double &n1,
double &n2,
double &n3)
682 if (fabs(x1) >= fabs(x2))
684 if (fabs(x1) >= fabs(x3))
688 Vec_normalize3_aux(x1, x2, x3, n1, n2, n3);
697 else if (fabs(x2) >= fabs(x3))
699 Vec_normalize3_aux(x2, x1, x3, n2, n1, n3);
702 Vec_normalize3_aux(x3, x1, x2, n3, n1, n2);
706 MFEM_HOST_DEVICE
static inline
707 int KernelVector3G_aux(
const int &mode,
708 double &d1,
double &d2,
double &d3,
709 double &c12,
double &c13,
double &c23,
710 double &c21,
double &c31,
double &c32)
713 double mu, n1, n2, n3, s1, s2, s3;
715 s1 = hypot(c21, c31);
722 mu = copysign(n1, d1);
723 n1 = -s1*(s1/(d1 +
mu));
728 if (fabs(n1) >= fabs(c21))
730 if (fabs(n1) >= fabs(c31))
735 mu = 2./(1. + s2*s2 + s3*s3);
736 n2 = mu*(c12 + s2*d2 + s3*c32);
737 n3 = mu*(c13 + s2*c23 + s3*d3);
747 else if (fabs(c21) >= fabs(c31))
752 mu = 2./(1. + s1*s1 + s3*s3);
753 n2 = mu*(s1*c12 + d2 + s3*c32);
754 n3 = mu*(s1*c13 + c23 + s3*d3);
766 mu = 2./(1. + s1*s1 + s2*s2);
767 n2 = mu*(s1*c12 + s2*d2 + c32);
768 n3 = mu*(s1*c13 + s2*c23 + d3);
782 if (KernelVector2G(mode, d2, c23, c32, d3))
803 d1 = -(c12*d2 + c13*d3)/d1;
807 Vec_normalize3(d1, d2, d3, d1, d2, d3);
813 MFEM_HOST_DEVICE
static inline
814 int KernelVector3S(
const int &mode,
const double &d12,
815 const double &d13,
const double &d23,
816 double &d1,
double &d2,
double &d3)
829 double c12 = d12, c13 = d13, c23 = d23;
830 double c21, c31, c32;
834 c32 = fabs(d1) + fabs(c12) + fabs(c13);
835 c31 = fabs(d2) + fabs(c12) + fabs(c23);
836 c21 = fabs(d3) + fabs(c13) + fabs(c23);
841 col = (c32 >= c31) ? 1 : 2;
845 col = (c31 >= c21) ? 2 : 3;
877 if (fabs(d1) <= fabs(c13))
879 row = (fabs(d1) <= fabs(c12)) ? 1 : 2;
883 row = (fabs(c12) <= fabs(c13)) ? 2 : 3;
888 if (fabs(d1) >= fabs(c13))
890 row = (fabs(d1) >= fabs(c12)) ? 1 : 2;
894 row = (fabs(c12) >= fabs(c13)) ? 2 : 3;
925 row = KernelVector3G_aux(mode, d1, d2, d3, c12, c13, c23, c21, c31, c32);
941 MFEM_HOST_DEVICE
static inline
942 int Reduce3S(
const int &mode,
943 double &d1,
double &d2,
double &d3,
944 double &d12,
double &d13,
double &d23,
945 double &z1,
double &z2,
double &z3,
946 double &v1,
double &v2,
double &v3,
966 double s, w1, w2, w3;
972 if (fabs(z1) <= fabs(z3))
974 k = (fabs(z1) <= fabs(z2)) ? 1 : 2;
978 k = (fabs(z2) <= fabs(z3)) ? 2 : 3;
984 if (fabs(z1) >= fabs(z3))
986 k = (fabs(z1) >= fabs(z2)) ? 1 : 2;
990 k = (fabs(z2) >= fabs(z3)) ? 2 : 3;
1017 g = copysign(1., z1);
1018 v1 = -s*(s/(z1 + g));
1021 if (fabs(z2) > g) { g = fabs(z2); }
1022 if (fabs(z3) > g) { g = fabs(z3); }
1026 g = 2./(v1*v1 + v2*v2 + v3*v3);
1031 w1 = g*( d1*v1 + d12*v2 + d13*v3);
1032 w2 = g*(d12*v1 + d2*v2 + d23*v3);
1033 w3 = g*(d13*v1 + d23*v2 + d3*v3);
1035 s = (g/2)*(v1*w1 + v2*w2 + v3*w3);
1042 d23 -= v2*w3 + v3*w2;
1047 s = d12 - v1*w2 - v2*w1;
1048 s = d13 - v1*w3 - v3*w1;
1071 template<> MFEM_HOST_DEVICE
inline
1074 double d0 = data[0];
1075 double d2 = data[2];
1076 double d3 = data[3];
1078 internal::Eigensystem2S(d2, d0, d3, c, s);
1102 template<> MFEM_HOST_DEVICE
inline
1105 double d11 = data[0];
1106 double d12 = data[3];
1107 double d22 = data[4];
1108 double d13 = data[6];
1109 double d23 = data[7];
1110 double d33 = data[8];
1114 double d_max = fabs(d11);
1115 if (d_max < fabs(d22)) { d_max = fabs(d22); }
1116 if (d_max < fabs(d33)) { d_max = fabs(d33); }
1117 if (d_max < fabs(d12)) { d_max = fabs(d12); }
1118 if (d_max < fabs(d13)) { d_max = fabs(d13); }
1119 if (d_max < fabs(d23)) { d_max = fabs(d23); }
1121 internal::GetScalingFactor(d_max, mult);
1124 d11 /= mult; d22 /= mult; d33 /= mult;
1125 d12 /= mult; d13 /= mult; d23 /= mult;
1127 double aa = (d11 + d22 + d33)/3;
1128 double c1 = d11 - aa;
1129 double c2 = d22 - aa;
1130 double c3 = d33 - aa;
1134 Q = (2*(d12*d12 + d13*d13 + d23*d23) + c1*c1 + c2*c2 + c3*c3)/6;
1135 R = (c1*(d23*d23 - c2*c3)+ d12*(d12*c3 - 2*d13*d23) + d13*d13*c2)/2;
1139 lambda[0] = lambda[1] = lambda[2] = aa;
1140 vec[0] = 1.; vec[3] = 0.; vec[6] = 0.;
1141 vec[1] = 0.; vec[4] = 1.; vec[7] = 0.;
1142 vec[2] = 0.; vec[5] = 0.; vec[8] = 1.;
1146 double sqrtQ = sqrt(Q);
1147 double sqrtQ3 = Q*sqrtQ;
1151 if (fabs(R) >= sqrtQ3)
1170 r = -2*sqrtQ*cos((acos(R) + 2.0*M_PI)/3);
1174 r = -2*sqrtQ*cos(acos(R)/3);
1198 switch (internal::KernelVector3S(mode, d12, d13, d23, c1, c2, c3))
1202 lambda[0] = lambda[1] = lambda[2] = aa;
1203 vec[0] = 1.; vec[3] = 0.; vec[6] = 0.;
1204 vec[1] = 0.; vec[4] = 1.; vec[7] = 0.;
1205 vec[2] = 0.; vec[5] = 0.; vec[8] = 1.;
1219 double v1, v2, v3, g;
1220 int k = internal::Reduce3S(mode, d11, d22, d33, d12, d13, d23,
1221 c1, c2, c3, v1, v2, v3, g);
1229 internal::Eigensystem2S(d23, d22, d33, c, s);
1232 double *vec_1, *vec_2, *vec_3;
1237 lambda[0] = d11; vec_1 = vec;
1238 lambda[1] = d22; vec_2 = vec + 3;
1239 lambda[2] = d33; vec_3 = vec + 6;
1241 else if (d11 <= d33)
1243 lambda[0] = d11; vec_1 = vec;
1244 lambda[1] = d33; vec_3 = vec + 3;
1245 lambda[2] = d22; vec_2 = vec + 6;
1249 lambda[0] = d33; vec_3 = vec;
1250 lambda[1] = d11; vec_1 = vec + 3;
1251 lambda[2] = d22; vec_2 = vec + 6;
1258 lambda[0] = d22; vec_2 = vec;
1259 lambda[1] = d11; vec_1 = vec + 3;
1260 lambda[2] = d33; vec_3 = vec + 6;
1262 else if (d22 <= d33)
1264 lambda[0] = d22; vec_2 = vec;
1265 lambda[1] = d33; vec_3 = vec + 3;
1266 lambda[2] = d11; vec_1 = vec + 6;
1270 lambda[0] = d33; vec_3 = vec;
1271 lambda[1] = d22; vec_2 = vec + 3;
1272 lambda[2] = d11; vec_1 = vec + 6;
1279 d22 = g*(v2*c - v3*
s);
1280 d33 = g*(v2*s + v3*c);
1281 vec_2[0] = - v1*d22; vec_3[0] = - v1*d33;
1282 vec_2[1] = c - v2*d22; vec_3[1] = s - v2*d33;
1283 vec_2[2] = -s - v3*d22; vec_3[2] = c - v3*d33;
1304 template<> MFEM_HOST_DEVICE
inline
1307 double d0, d1, d2, d3;
1315 double d_max = fabs(d0);
1316 if (d_max < fabs(d1)) { d_max = fabs(d1); }
1317 if (d_max < fabs(d2)) { d_max = fabs(d2); }
1318 if (d_max < fabs(d3)) { d_max = fabs(d3); }
1319 internal::GetScalingFactor(d_max, mult);
1327 double t = 0.5*((d0+d2)*(d0-d2)+(d1-d3)*(d1+d3));
1328 double s = d0*d2 + d1*d3;
1329 s = sqrt(0.5*(d0*d0 + d1*d1 + d2*d2 + d3*d3) + sqrt(t*t + s*s));
1335 t = fabs(d0*d3 - d1*d2) /
s;
1352 template<> MFEM_HOST_DEVICE
inline
1355 double d0, d1, d2, d3, d4, d5, d6, d7, d8;
1356 d0 = data[0]; d3 = data[3]; d6 = data[6];
1357 d1 = data[1]; d4 = data[4]; d7 = data[7];
1358 d2 = data[2]; d5 = data[5]; d8 = data[8];
1361 double d_max = fabs(d0);
1362 if (d_max < fabs(d1)) { d_max = fabs(d1); }
1363 if (d_max < fabs(d2)) { d_max = fabs(d2); }
1364 if (d_max < fabs(d3)) { d_max = fabs(d3); }
1365 if (d_max < fabs(d4)) { d_max = fabs(d4); }
1366 if (d_max < fabs(d5)) { d_max = fabs(d5); }
1367 if (d_max < fabs(d6)) { d_max = fabs(d6); }
1368 if (d_max < fabs(d7)) { d_max = fabs(d7); }
1369 if (d_max < fabs(d8)) { d_max = fabs(d8); }
1370 internal::GetScalingFactor(d_max, mult);
1373 d0 /= mult; d1 /= mult; d2 /= mult;
1374 d3 /= mult; d4 /= mult; d5 /= mult;
1375 d6 /= mult; d7 /= mult; d8 /= mult;
1377 double b11 = d0*d0 + d1*d1 + d2*d2;
1378 double b12 = d0*d3 + d1*d4 + d2*d5;
1379 double b13 = d0*d6 + d1*d7 + d2*d8;
1380 double b22 = d3*d3 + d4*d4 + d5*d5;
1381 double b23 = d3*d6 + d4*d7 + d5*d8;
1382 double b33 = d6*d6 + d7*d7 + d8*d8;
1401 double aa = (b11 + b22 + b33)/3;
1407 double b11_b22 = ((d0-d3)*(d0+d3)+(d1-d4)*(d1+d4)+(d2-d5)*(d2+d5));
1408 double b22_b33 = ((d3-d6)*(d3+d6)+(d4-d7)*(d4+d7)+(d5-d8)*(d5+d8));
1409 double b33_b11 = ((d6-d0)*(d6+d0)+(d7-d1)*(d7+d1)+(d8-d2)*(d8+d2));
1410 c1 = (b11_b22 - b33_b11)/3;
1411 c2 = (b22_b33 - b11_b22)/3;
1412 c3 = (b33_b11 - b22_b33)/3;
1415 Q = (2*(b12*b12 + b13*b13 + b23*b23) + c1*c1 + c2*c2 + c3*c3)/6;
1416 R = (c1*(b23*b23 - c2*c3)+ b12*(b12*c3 - 2*b13*b23) +b13*b13*c2)/2;
1449 double sqrtQ = sqrt(Q);
1450 double sqrtQ3 = Q*sqrtQ;
1455 if (fabs(R) >= sqrtQ3)
1477 aa -= 2*sqrtQ*cos(acos(R)/3);
1481 aa -= 2*sqrtQ*cos((acos(R) + 2.0*M_PI)/3);
1485 aa -= 2*sqrtQ*cos((acos(R) - 2.0*M_PI)/3);
1492 r = -2*sqrtQ*cos((acos(R) + 2.0*M_PI)/3);
1501 r = -2*sqrtQ*cos(acos(R)/3);
1532 switch (internal::KernelVector3S(mode, b12, b13, b23, c1, c2, c3))
1548 double v1, v2, v3, g;
1549 internal::Reduce3S(mode, b11, b22, b33, b12, b13, b23,
1550 c1, c2, c3, v1, v2, v3, g);
1557 internal::Eigenvalues2S(b23, b22, b33);
1561 aa = fmin(fmin(b11, b22), b33);
1567 aa = (b22 <= b33) ? b22 : fmax(b11, b33);
1571 aa = (b11 <= b33) ? b11 : fmax(b33, b22);
1576 aa = fmax(fmax(b11, b22), b33);
1582 return sqrt(fabs(aa))*mult;
1594 inline void LUSolve(
const double *data,
const int m,
const int *ipiv,
1598 for (
int i = 0; i < m; i++)
1600 internal::Swap<double>(x[i], x[ipiv[i]]);
1604 for (
int j = 0; j < m; j++)
1606 const double x_j = x[j];
1607 for (
int i = j + 1; i < m; i++)
1609 x[i] -= data[i + j * m] * x_j;
1614 for (
int j = m - 1; j >= 0; j--)
1616 const double x_j = (x[j] /= data[j + j * m]);
1617 for (
int i = 0; i < j; i++)
1619 x[i] -= data[i + j * m] * x_j;
1628 #endif // MFEM_LINALG_KERNELS_HPP
MFEM_HOST_DEVICE T Det(const T *data)
Compute the determinant of a square matrix of size dim with given data.
MFEM_HOST_DEVICE double DistanceSquared(const double *x, const double *y)
Compute the square of the Euclidean distance to another vector.
MFEM_HOST_DEVICE void FNorm(double &scale_factor, double &scaled_fnorm2, const T *data)
MFEM_HOST_DEVICE void MultABt(const int Aheight, const int Awidth, const int Bheight, const TA *Adata, const TB *Bdata, TC *ABtdata)
Multiply a matrix of size Aheight x Awidth and data Adata with the transpose of a matrix of size Bhei...
MFEM_HOST_DEVICE void Diag(const double c, double *data)
Creates n x n diagonal matrix with diagonal elements c.
MFEM_HOST_DEVICE void Add(const int height, const int width, const TALPHA alpha, const TA *Adata, const TB *Bdata, TC *Cdata)
Compute C = A + alpha*B, where the matrices A, B and C are of size height x width with data Adata...
MFEM_HOST_DEVICE void MultAtB(const int Aheight, const int Awidth, const int Bwidth, const TA *Adata, const TB *Bdata, TC *AtBdata)
Multiply the transpose of a matrix of size Aheight x Awidth and data Adata with a matrix of size Ahei...
MFEM_HOST_DEVICE double CalcSingularvalue< 3 >(const double *data, const int i)
Return the i'th singular value of the matrix of size 3 with given data.
MFEM_HOST_DEVICE void CalcEigenvalues(const double *data, double *lambda, double *vec)
MFEM_HOST_DEVICE void CalcEigenvalues< 2 >(const double *data, double *lambda, double *vec)
MFEM_HOST_DEVICE void LUSolve(const double *data, const int m, const int *ipiv, double *x)
Assuming L.U = P.A for a factored matrix (m x m),.
MFEM_HOST_DEVICE double Norml2(const int size, const T *data)
Returns the l2 norm of the Vector with given size and data.
MFEM_HOST_DEVICE void CalcAdjugate(const T *data, T *adj_data)
Return the adjugate of a matrix.
MFEM_HOST_DEVICE void Mult(const int height, const int width, const TA *data, const TX *x, TY *y)
Matrix vector multiplication: y = A x, where the matrix A is of size height x width with given data...
void Swap(Array< T > &, Array< T > &)
MFEM_HOST_DEVICE void MultTranspose(const int height, const int width, const TA *data, const TX *x, TY *y)
Matrix transpose vector multiplication: y = At x, where the matrix A is of size height x width with g...
MFEM_HOST_DEVICE double CalcSingularvalue(const double *data, const int i)
Return the i'th singular value of the matrix of size dim with given data.
MFEM_HOST_DEVICE double CalcSingularvalue< 2 >(const double *data, const int i)
Return the i'th singular value of the matrix of size 2 with given data.
MFEM_HOST_DEVICE void CalcEigenvalues< 3 >(const double *data, double *lambda, double *vec)
MFEM_HOST_DEVICE void CalcInverse(const T *data, T *inv_data)
Return the inverse of a matrix with given size and data into the matrix with data inv_data...
MFEM_HOST_DEVICE void Subtract(const double a, const double *x, const double *y, double *z)
Vector subtraction operation: z = a * (x - y)
MFEM_HOST_DEVICE void Set(const int height, const int width, const double alpha, const TA *Adata, TB *Bdata)
Compute B = alpha*A, where the matrices A and B are of size height x width with data Adata and Bdata...
MFEM_HOST_DEVICE void AddMultVWt(const double *v, const double *w, double *VWt)
Dense matrix operation: VWt += v w^t.
MFEM_HOST_DEVICE void Symmetrize(const int size, T *data)
Symmetrize a square matrix with given size and data: A -> (A+A^T)/2.
MFEM_HOST_DEVICE double FNorm2(const T *data)
Compute the square of the Frobenius norm of the matrix.