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);
			}
		}
	}
Exemple #2
0
/* 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;