void test_block_tridiagonal_solve () { // io::parameters <double> params ("../input/block_parameters.txt"); // omp_set_num_threads(params.nmp); int id = process_messenger->get_id (); int np = process_messenger->get_np (); int n = 60, nrhs = 70, ntop = 0, nbot = 0; if (id != 0) { ntop = 1; } if (id != np - 1) { nbot = 1; } std::vector <double> sub (n * nrhs, 0.0); std::vector <double> diag (n * nrhs, 0.0); std::vector <double> sup (n * nrhs, 0.0); std::vector <double> subcopy (n * nrhs, 0.0); std::vector <double> diagcopy (n * nrhs, 0.0); std::vector <double> supcopy (n * nrhs, 0.0); std::vector <double> supsup (n * nrhs, 0.0); std::vector <int> ipiv (n * nrhs, 0); std::vector <double> x (2 * n * nrhs + 8 * np * nrhs, 0.0); std::vector <int> xipiv (2 * np * nrhs, 0); std::vector <double> b (n * nrhs, 0.0); std::vector <double> bcopy (n * nrhs, 0.0); int info; srand (1); for (int i = 0; i < nrhs; ++i) { for (int j = 0; j < n; ++j) { sub [i * n + j] = rand () % 100; subcopy [i * n + j] = sub [i * n + j]; diag [i * n + j] = rand () % 100; diagcopy [i * n + j] = diag [i * n + j]; sup [i * n + j] = rand () % 100; supcopy [i * n + j] = sup [i * n + j]; b [i * n + j] = rand () % 100; bcopy [i * n + j] = b [i * n + j]; } } try { linalg::block::tridiag_factorize (id, np, n - ntop - nbot, &sub [0], &diag [0], &sup [0], &supsup [0], &ipiv [0], &x [0], &xipiv [0], &info, nrhs); linalg::block::tridiag_solve (id, np, n - ntop - nbot, &sub [0], &diag [0], &sup [0], &supsup [0], &ipiv [0], &b [0], &x [0], &xipiv [0], &info, nrhs); } catch (std::exception& except) { std::cout << except.what () << '\n'; } for (int j = 0; j < nrhs; ++j) { bcopy [j * n] -= diagcopy [j * n] * b [j * n] + supcopy [j * n] * b [1 + j * n]; for (int i = 1; i < n - 1; ++i) { bcopy [i + j * n] -= subcopy [i + j * n] * b [i - 1 + j * n] + diagcopy [i + j * n] * b [i + j * n] + supcopy [i + j * n] * b [i + 1 + j * n]; } bcopy [n - 1 + j * n] -= subcopy [n - 1 + j * n] * b [n - 2 + j * n] + diagcopy [n - 1 + j * n] * b [n - 1 + j * n]; } std::vector <double> edge_0 (nrhs), edge_n (nrhs), redge_0 (nrhs), redge_n (nrhs); for (int i = 0; i < nrhs; ++i) { edge_0 [i] = b [i * n]; edge_n [i] = b [i * n + n - 1]; } if (id != 0) { process_messenger->send (nrhs, &edge_0 [0], id - 1, 0); } if (id != np - 1) { process_messenger->recv (nrhs, &redge_n [0], id + 1, 0); for (int i = 0; i < nrhs; ++i) { bcopy [i * n + n - 1] -= supcopy [i * n + n - 1] * redge_n [i]; } } if (id != np - 1) { process_messenger->send (nrhs, &edge_n [0], id + 1, 1); } if (id != 0) { process_messenger->recv (nrhs, &redge_0 [0], id - 1, 1); for (int i = 0; i < nrhs; ++i) { bcopy [i * n] -= subcopy [i * n] * redge_0 [i]; } } for (int i = 0; i < n; ++i) { for (int j = 0; j < nrhs; ++j) { TSM_ASSERT_DELTA ("Tridiagonal block solver failure", bcopy [j * n + i], 0.0, TEST_TINY); } } }
/* mend face with colinear vertices */ static int mendface (face *f) { edge *e, *h, *x, *y, *z, *w, *o; double u [3], v [3], d, l [2]; double *a, *b, *c; face *g; for (e = f->e; e; e = e->n) { a = e->v [0]; b = e->v [1]; if (!(c = otherv (f, a, b))) return 0; SUB (b, a, u); SUB (c, a, v); l[0] = LEN (u); l[1] = LEN (v); d = DOT (u, v); if (d >= 0 && l[1] <= l[0]) break; /* c in [a, b] */ } if (e) { a = c; g = e->f; if (!(h = othere (g, f))) return 0; if (!(b = otherv (g, h->v[0], h->v[1]))) return 0; if (!(x = edge_0 (f, a))) return 0; if (!(y = edge_1 (g, b))) return 0; if (!(z = edge_0 (g, b))) return 0; if (!(w = edge_1 (f, a))) return 0; if (!(o = othere (y->f, g))) return 0; o->f = f; if (!(o = othere (w->f, f))) return 0; o->f = g; e->v [0] = b; e->v [1] = a; h->v [0] = a; h->v [1] = b; e->n = NULL; y->n = e; x->n = y; f->e = x; h->n = NULL; w->n = h; z->n = w; g->e = z; #if GEOMDEBUG ASSERT_DEBUG (setplane (f), "Zero normal (when mending face)"); ASSERT_DEBUG (setplane (g), "Zero normal (when mending face)"); #else if (!(setplane (f) && setplane (g))) return 0; #endif } #if GEOMDEBUG else { ASSERT_DEBUG (0, "Face mending failed"); } #else else return 0;