Esempio n. 1
0
/*
 **
 * \brief
 * Create the following from the given components:
 * |  M           Y             |
 * |  X  X.Minv.Y + Pinv.A.Qinv |
 */
static gf2matrix *extend_by_blocks(const gf2matrix *m, const gf2matrix *x,
		const gf2matrix *y, const gf2matrix *xminvy, const gf2matrix *pinv,
		const gf2matrix *a, const gf2matrix *qinv)
{
	gf2matrix *result = NULL;
	gf2matrix *addterm = NULL;
	/* print_matrix(xminvy, "X.Minv.Y: "); */
	{
		gf2matrix *aqinv = NULL, *pinvaqinv = NULL;
		aqinv = mul_matrices(NULL, a, qinv);
		assert(aqinv);
		pinvaqinv = mul_matrices(NULL, pinv, aqinv);
		assert(pinvaqinv);
		/* print_matrix(pinvaqinv, "Pinv.A.Qinv: "); */
		addterm = add_matrices(NULL, xminvy, pinvaqinv);
		free_matrix(aqinv);
		free_matrix(pinvaqinv);
	}
	assert(addterm);
	/* print_matrix(addterm, "X.Minv.Y + Pinv.A.Qinv: "); */
	assert(is_invertible(addterm));
	result = combine_matrices(m, y, x, addterm);
	assert(result);

	if (!is_invertible(result)) {
		/* printf("extended matrix was not invertible. incorrect calculations\n"); */
		/* print_matrix(result, "result: "); */
		free_matrix(result);
		result = NULL;
	}
	free_matrix(addterm);
	return result;
}
Esempio n. 2
0
/* solve generalized linear set of equations using LU-decomposition
 * INPUT
 *  n1, n2 : dimension
 *  A [n1 * n1] :
 *  B [n1 * n2] :
 *  C [n2 * n1] :
 *  D [n2 * n2] :
 *
 *  E [n1 * n1] :
 *  F [n1 * n2] :
 *  G [n2 * n1] :
 *  H [n2 * n2] :
 *  where the generalized linear set of equations is
 *   [A B](x) = [E F](b)
 *   [C D](y)   [G H](c)
 * OUTPUT
 *  I [n1 * n1] :
 *  J [n1 * n2] :
 *  K [n2 * n1] :
 *  L [n2 * n2] :
 *  where the generalized linear set of equations is
 *   (x) = [I J](b)
 *   (c)   [K L](y)
 *  note that A-D, E-H are destroyed!
 */
void
solve_gen_linear (int n1, int n2,
		  double * A, double * B, double * C, double * D,
		  double * E, double * F, double * G, double * H,
		  double * I, double * J, double * K, double * L)
{
  /* H := H^-1 */
  lapack_inv_ (n2, H);

  /* C := (H^-1) . C */
  mul_left_sq (C, n2, n1, H);
  /* G := (H^-1) . G */
  mul_left_sq (G, n2, n1, H);
  /* D := (H^-1) . D */
  mul_left_sq (D, n2, n2, H);


  double *a = (double *)malloc (sizeof (double) * n1 * n1);
  double *e = (double *)malloc (sizeof (double) * n1 * n1);
  double *b = (double *)malloc (sizeof (double) * n1 * n2);
  CHECK_MALLOC (a, "solve_gen_linear");
  CHECK_MALLOC (e, "solve_gen_linear");
  CHECK_MALLOC (b, "solve_gen_linear");

  /* a [n1, n1] := A - F.(H^-1).C */
  add_and_mul (A, n1, n1, F, n1, n2, C, n2, n1, 1.0, -1.0, a);
  // e [n1, n1] := E - F.(H^-1).G
  add_and_mul (E, n1, n1, F, n1, n2, G, n2, n1, 1.0, -1.0, e);
  // b [n1, n2] := - B + F.(H^-1).D
  add_and_mul (B, n1, n2, F, n1, n2, D, n2, n2, -1.0, 1.0, b);

  /* a := (A-F.(H^-1).C)^-1 */
  lapack_inv_ (n1, a);

  /* I := a.e */
  mul_matrices (a, n1, n1, e, n1, n1, I);
  /* J := a.b */
  mul_matrices (a, n1, n1, b, n1, n2, J);

  free (a);
  free (e);
  free (b);


  // K := - G + C.I
  add_and_mul (G, n2, n1, C, n2, n1, I, n1, n1, -1.0, 1.0, K);
  // L := D + C.J
  add_and_mul (D, n2, n2, C, n2, n1, J, n1, n2, 1.0, 1.0, L);
}
Esempio n. 3
0
gf2matrix *invert_matrix(gf2matrix *dest, const gf2matrix *m)
{
    if (!m)
        return NULL;
    mzd_t *temp = mzd_inv_m4ri(NULL, (mzd_t*) m, 0);
    if(!temp) {
        dest = NULL;
    }
    else {
        mzd_t *I = make_identity_matrix(m->nrows);
        mzd_t *prod = mul_matrices(NULL, m, temp);
        if(comp_matrices(prod, I) == 0) {
            // inversion was successful
            if (dest) {
                mzd_copy(dest, temp);
                mzd_free(temp);
            }
            else {
                dest = temp;
            }
        }
        else {
            dest = NULL;
        }
        mzd_free(prod);
        mzd_free(I);
    }
    return dest;
}
Esempio n. 4
0
/* D = a * A + b * B . C
 * INPUT
 *  A [na1, na2]
 *  B [nb1, nb2]
 *  C [nc1, nc2]
 *  a
 *  b
 *  where (nb2 == nc1) && (na1 = nb1) && (na2 == nc2)
 * OUTPUT
 *  D [na1, na2] = a * A [na1, na2] + b * B [nb1, nb2] . C [nc1, nc2]
 */
void
add_and_mul (const double *A, int na1, int na2,
	     const double *B, int nb1, int nb2,
	     const double *C, int nc1, int nc2,
	     double a, double b,
	     double *D)
{
  if (nb2 != nc1
      || na1 != nb1
      || na2 != nc2)
    {
      fprintf (stderr, "illeagal multiplication in add_and_mul().\n");
      exit (1);
    }
  if (A == D)
    {
      fprintf (stderr, "illeagal pointer D in add_and_mul().\n");
      exit (1);
    }

  mul_matrices (B, nb1, nb2, C, nc1, nc2, D);

  int i;
  for (i = 0; i < na1*na2; i ++)
    {
      D[i] = a * A[i] + b * D[i];
    }
}
Esempio n. 5
0
File: duh.c Progetto: aclark4life/CS
void main(int argc, char *argv[]) {
        if (argc!=1) {
                printf("Sorry, I don't take command line arguments.\n");
                exit(-1);
	}
        else {
		get_first();
		get_matrices();
		mul_matrices();
		print_out();
	}
}
Esempio n. 6
0
/* solve linear set of equations using LU-decomposition
 * INPUT
 *  n1, n2 : dimension
 *  A [n1 * n1] :
 *  B [n1 * n2] :
 *  C [n2 * n1] :
 *  D [n2 * n2] :
 *  where the generalized linear set of equations is
 *   (b) = [A B](x)
 *   (c)   [C D](y)
 * OUTPUT
 *  I [n1 * n1] :
 *  J [n1 * n2] :
 *  K [n2 * n1] :
 *  L [n2 * n2] :
 *  where the generalized linear set of equations is
 *   (x) = [I J](b)
 *   (c)   [K L](y)
 *  note that A-D are destroyed!
 */
void
solve_linear (int n1, int n2,
	      double * A, double * B, double * C, double * D,
	      double * I, double * J, double * K, double * L)
{
  int i;
  /* type 1 */

  /* A := A^-1 */
  lapack_inv_ (n1, A);

  /* B := (A^-1).B */
  double *tmp = (double *) malloc (sizeof (double) * n1 * n2);
  CHECK_MALLOC (tmp, "solve_linear");

  mul_matrices (A, n1, n1,
		B, n1, n2,
		tmp);

  for (i = 0; i < n1 * n2; i ++)
    {
      B[i] = tmp[i];
    }
  free (tmp);

  // L [n2, n2] := D - C.(A^-1).B
  add_and_mul (D, n2, n2, C, n2, n1, B, n1, n2, 1.0, -1.0, L);
  // K := C.A
  mul_matrices (C, n2, n1, A, n1, n1, K);

  for (i = 0; i < n1 * n1; ++i)
    {
      I [i] = A [i];
    }
  for (i = 0; i < n1 * n2; ++i)
    {
      J [i] = - B [i];
    }
}
Esempio n. 7
0
int mul_byte_by_matrix(uint8_t *result, const gf2matrix *m, uint8_t byte)
{
	/**
	 * 1. convert byte to a matrix (vector)
	 * 2. multiply vector by m; obtain result matrix
	 * 3. convert result matrix into byte array
	 */
	int i;
	int octets = get_rows(m) / 8;
	gf2matrix *vec = new_matrix(8, 1);
	byte2vector(vec, byte);
	gf2matrix *prod = mul_matrices(NULL, (gf2matrix *) m, vec);
	for (i = 0; i < octets; ++i) {
		vector2byte_offset(&result[i], prod, i * 8);
	}
	free_matrix(vec);
	free_matrix(prod);
	return 0;
}
Esempio n. 8
0
/* return B . A in A, where B is square matrix
 * Remark!! this is not A.B!!
 * INPUT
 *  A [na1, na2]
 *  B [nb, nb] : square matrix!
 *  where (nb == na1)
 * OUTPUT
 *  A [na1, na2] = B [nb, nb] . A [na1, na2]
 */
static void
mul_left_sq (double * A, int na1, int na2,
	     const double * B)
{
  int i;
  int nb = na1;

  double *tmp = (double *) malloc (sizeof (double) * na1 * na2);
  CHECK_MALLOC (tmp, "mul_left_sq");

  mul_matrices (B, nb, nb,
		A, na1, na2,
		tmp);

  for (i = 0; i < na1 * na2; ++i)
    {
      A [i] = tmp [i];
    }

  free (tmp);
}
Esempio n. 9
0
int mul_array_by_matrix(uint8_t *result, const gf2matrix *m,
		const uint8_t *bytes)
{
	/**
	 * 1. convert the input byte array to a matrix (vector)
	 * 2. multiply vector by m; obtain result matrix
	 * 3. convert result matrix into byte array
	 */
	int i;
	int octets = get_rows(m) / 8;
	gf2matrix *prod;
	gf2matrix *vec = new_matrix(get_rows(m), 1);
	for (i = 0; i < octets; ++i) {
		byte2vector_offset(vec, bytes[i], i * 8);
	}
	prod = mul_matrices(NULL, m, vec);
	for (i = 0; i < octets; ++i) {
		vector2byte_offset(&result[i], prod, i * 8);
	}
	free_matrix(vec);
	free_matrix(prod);
	return 0;
}
Esempio n. 10
0
/*
 * INPUT
 *  verbose : if non-zero, print results
 * OUTPUT
 *  (returned value) : 0 => passed
 *                     otherwise => failed
 */
int
check_lapack_inv_ (int n, int verbose, double tiny)
{
    if (verbose != 0)
    {
        fprintf (stdout,
                 "==================================================\n"
                 "check_lapack_inv_(n=%d) : start\n", n);
    }

    int check = 0;
    double max = 0.0;


    double *a  = (double *)malloc (sizeof (double) * n * n);
    double *a_ = (double *)malloc (sizeof (double) * n * n);
    double *b  = (double *)malloc (sizeof (double) * n * n);
    CHECK_MALLOC (a,  "check_lapack_inv_");
    CHECK_MALLOC (a_, "check_lapack_inv_");
    CHECK_MALLOC (b, "check_lapack_inv_");

    int i;
    srand48 (0);
    for (i = 0; i < n * n; i ++)
    {
        a [i] = drand48();
        a_[i] = a [i];
    }

    // a = a^-1
    lapack_inv_ (n, a);

    // b = a^-1 . a
    mul_matrices (a, n, n, a_, n, n, b);
    /*
    int j, k;
    for (i = 0; i < n; i ++)
      {
        for (j = 0; j < n; j ++)
    {
      b[i*n+j] = 0.0;
      for (k = 0; k < n; k ++)
        {
          b[i*n+j] += a[i*n+k] * a_[k*n+j];
        }
    }
      }
    */

    char label[80];
    double d;
    for (i = 0; i < n; i ++)
    {
        int j;
        for (j = 0; j < n; j ++)
        {
            if (i == j) d = fabs (b [i*n+j] - 1.0);
            else        d = fabs (b [i*n+j]);

            sprintf (label, "check_lapack_inv_ : [%d]", i);
            check += compare_max (d+1.0, 1.0, label, verbose, tiny, &max);
        }
    }

    free (a);
    free (a_);
    free (b);

    if (verbose != 0)
    {
        fprintf (stdout, " max error = %e vs tiny = %e\n", max, tiny);
        if (check == 0) fprintf (stdout, " => PASSED\n\n");
        else            fprintf (stdout, " => FAILED\n\n");
    }

    return (check);
}
Esempio n. 11
0
/**
 * @detail
 * All variables are named as in the fore mentioned paper
 * 1. Use a row of blocks of Matrix M to create a matrix X
 * 2. Use a column of blocks of Matrix M to create a matrix Y
 * 3. Get invertible matrices P and Q such that P(X.Minv.Y)Q = [I 0]
 *    (I is of r dimension; 0 is of 2-r dimension; 0 < r < 3)
 * 4. Define matrix A as follows:
 * 		a) if r = 0 then A = I
 * 		b) if r = 1 then A = [[1 1] [1 0]]
 * 		c) if r = 2 then A = [[0 1] [1 1]]
 * 5. Then the following is a (t+2, 2) block invertible matrix:
 * 		|  M           Y             |
 * 		|  X  X.Minv.Y + Pinv.A.Qinv |
 */
static gf2matrix *extend_block_invertible_by2(const gf2matrix *m)
{
	gf2matrix *result = NULL;
	gf2matrix *x = NULL, *y = NULL;
	int multiples = get_rows(m) / 2;
	int x_start = get_random(0, multiples - 1) * 2;
	int y_start = get_random(0, multiples - 1) * 2;
	if (!m) {
		gf2matrix *_2x2;
		get_2x2invertible_pair(get_random(0, MAX_2X2_INVERTIBLES - 1), &_2x2,
				NULL);
		result = dup_matrix(_2x2);
		return result;
	}
	/* print_matrix(m, "Extending m by 2:"); */

	/*  step 1 */
	x = extract_block_row(NULL, x_start, m);
	assert(x);
	/* print_matrix(x, "X:"); */

	/*  step 2 */
	y = extract_block_col(NULL, y_start, m);
	assert(y);
	/* print_matrix(y, "Y:"); */
	{ /*  steps 3, 4, 5 */
		int r; /* r is the rank of X.Minv.Y */
		gf2matrix *i0mat = new_matrix(2, 2);
		gf2matrix *prod = new_matrix(2, 2);
		gf2matrix *temp = NULL;
		gf2matrix *mInv = invert_matrix(NULL, m);
		gf2matrix *xminvy = NULL;
		gf2matrix *a2 = NULL;
		{
			assert(mInv);
			/*  calculate X.Minv.Y */
			gf2matrix *minvy = mul_matrices(NULL, mInv, y);
			xminvy = mul_matrices(NULL, x, minvy);
			assert(xminvy);
			free_matrix(minvy);
		}
		/* print_matrix(xminvy, "xM-1y: "); */
		r = calc_rank(xminvy);
		/* printf("rank of X.Minv.Y = %d\n", r); */
		init_IO_matrix(i0mat, r);
		/* print_matrix(i0mat, "I0:"); */
		a2 = make_A2_matrix(r);

		temp = new_matrix(2, 2);
		while (!result) {
			int i, j, i_tries, j_tries;
			for (i = get_random(0, MAX_2X2_INVERTIBLES - 1), i_tries = 0; i_tries
					< MAX_2X2_INVERTIBLES && !result; i = (i + 1)
					% MAX_2X2_INVERTIBLES, ++i_tries) {
				gf2matrix *q, *qinv;
				get_2x2invertible_pair(i, &q, &qinv);
				/* print_matrix(q, "Q:"); */
				mul_matrices(temp, xminvy, q);
				assert(temp);
				for (j = get_random(0, MAX_2X2_INVERTIBLES - 1), j_tries = 0; j_tries
						< MAX_2X2_INVERTIBLES && !result; j = (j + 1)
						% MAX_2X2_INVERTIBLES, ++j_tries) {
					gf2matrix *p, *pinv;
					get_2x2invertible_pair(j, &p, &pinv);
					mul_matrices(prod, p, temp);
					assert(prod);
					/* print_matrix(p, "P:"); */
					/* print_matrix(prod, "P.X.Minv.Y.Q:"); */
					if (comp_matrices(prod, i0mat) == 0) {
						/*  step 5 */
						result = extend_by_blocks(m, x, y, xminvy, pinv, a2,
								qinv);
						assert(result);
						break;
					}
				}
			}
		}
		free_matrix(a2);
		free_matrix(xminvy);
		free_matrix(mInv);
		free_matrix(prod);
		free_matrix(temp);
		free_matrix(i0mat);

		if (!result)
			printf("incorrect matrix expansion algorithm");
	}
	cleanup: free_matrix(y);
	free_matrix(x);
	return result;
}
Esempio n. 12
0
/* solve natural mobility problem with lubrication
 * with fixed particles in FT version
 * for both periodic and non-periodic boundary conditions
 * INPUT
 *  sys : system parameters
 *   f [nm * 3] :
 *   t [nm * 3] :
 *   uf [nf * 3] :
 *   of [nf * 3] :
 * OUTPUT
 *   u [nm * 3] :
 *   o [nm * 3] :
 *   ff [nf * 3] :
 *   tf [nf * 3] :
 */
void
solve_mix_lub_3ft_matrix (struct stokes * sys,
			  const double *f, const double *t,
			  const double *uf, const double *of,
			  double *u, double *o,
			  double *ff, double *tf)
{
  if (sys->version != 1)
    {
      fprintf (stderr, "libstokes solve_mix_lub_3ft_matrix :"
	       " the version is wrong. reset to FT\n");
      sys->version = 1;
    }

  int np = sys->np;
  int nm = sys->nm;
  if (np == nm)
    {
      solve_mob_lub_3ft_matrix (sys, f, t,
				u, o);
      return;
    }

  int n6 = np * 6;
  int nf = np - nm;
  int nm6 = nm * 6;
  int nl = nm * 6;
  int nh = n6 - nl;

  double *uf0 = (double *) malloc (sizeof (double) * nf * 3);
  double *of0 = (double *) malloc (sizeof (double) * nf * 3);
  double *mat = (double *) malloc (sizeof (double) * n6 * n6);
  double *lub = (double *) malloc (sizeof (double) * n6 * n6);
  double *tmp = (double *) malloc (sizeof (double) * n6 * n6);
  double *mat_ll = (double *) malloc (sizeof (double) * nl * nl);
  double *mat_lh = (double *) malloc (sizeof (double) * nl * nh);
  double *mat_hl = (double *) malloc (sizeof (double) * nh * nl);
  double *mat_hh = (double *) malloc (sizeof (double) * nh * nh);
  double *mob_ll = (double *) malloc (sizeof (double) * nl * nl);
  double *mob_lh = (double *) malloc (sizeof (double) * nl * nh);
  double *mob_hl = (double *) malloc (sizeof (double) * nh * nl);
  double *mob_hh = (double *) malloc (sizeof (double) * nh * nh);
  double *b = (double *) malloc (sizeof (double) * n6);
  double *x = (double *) malloc (sizeof (double) * n6);
  CHECK_MALLOC (uf0, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (of0, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (mat, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (lub, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (tmp, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (mat_ll, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (mat_lh, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (mat_hl, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (mat_hh, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (mob_ll, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (mob_lh, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (mob_hl, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (mob_hh, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (b, "solve_mix_lub_3ft_matrix");
  CHECK_MALLOC (x, "solve_mix_lub_3ft_matrix");

  shift_labo_to_rest_U (sys, nf, uf, uf0);
  shift_labo_to_rest_O (sys, nf, of, of0);
  /* the main calculation is done in the the fluid-rest frame;
   * u(x)=0 as |x|-> infty */

  /* b := (FT,UfOf) */
  set_ft_by_FT (nm, b, f, t);
  set_ft_by_FT (nf, b + nm6, uf0, of0);
  free (uf0);
  free (of0);

  /* mob */
  make_matrix_mob_3all (sys, mat); // sys->version is 1 (FT)
  split_matrix_fix_3ft (np, nm, mat, mat_ll, mat_lh, mat_hl, mat_hh);

  /* lub */
  make_matrix_lub_3ft (sys, lub);
  /* tmp := M.L */
  mul_matrices (mat, n6, n6, lub, n6, n6, tmp);
  /* note: at this point, lub[] is free to use.
   * so that I_?? use lub [] */
  double *I_ll = lub;
  double *I_lh = I_ll + nl * nl;
  double *I_hl = I_lh + nl * nh;
  double *I_hh = I_hl + nh * nl;

  /* tmp := I + (M.T).(L.T) */
  int i;
  for (i = 0; i < n6; ++i)
    {
      tmp [i * n6 + i] += 1.0;
    }
  split_matrix_fix_3ft (np, nm, tmp, I_ll, I_lh, I_hl, I_hh);
  free (tmp);

  solve_gen_linear (nl, nh,
		    I_ll, I_lh, I_hl, I_hh,
		    mat_ll, mat_lh, mat_hl, mat_hh,
		    mob_ll, mob_lh, mob_hl, mob_hh);
  /* note: at this point, I_??, therefore lub[], is free to use. */
  free (lub);

  merge_matrix_fix_3ft (np, nm, mob_ll, mob_lh, mob_hl, mob_hh, mat);
  dot_prod_matrix (mat, n6, n6,
		   b, x);

  set_FT_by_ft (nm, u, o, x);
  set_FT_by_ft (nf, ff, tf, x + nm6);

  free (mat);
  free (mat_ll);
  free (mat_lh);
  free (mat_hl);
  free (mat_hh);
  free (mob_ll);
  free (mob_lh);
  free (mob_hl);
  free (mob_hh);
  free (b);
  free (x);

  /* for the interface, we are in the labo frame, that is
   * u(x) is given by the imposed flow field as |x|-> infty */
  shift_rest_to_labo_U (sys, nm, u);
  shift_rest_to_labo_O (sys, nm, o);
}
Esempio n. 13
0
/* solve natural mobility problem in FT version
 * for both periodic and non-periodic boundary conditions
 * INPUT
 *  sys : system parameters
 *   f [np * 3] :
 *   t [np * 3] :
 * OUTPUT
 *   u [np * 3] :
 *   o [np * 3] :
 */
void
solve_mob_lub_3ft_matrix (struct stokes * sys,
			  const double *f, const double *t,
			  double *u, double *o)
{
  if (sys->version != 1)
    {
      fprintf (stderr, "libstokes solve_mob_lub_3ft_matrix :"
	       " the version is wrong. reset to FT\n");
      sys->version = 1;
    }

  int np = sys->np;
  int n6 = np * 6;

  double *mat = (double *) malloc (sizeof (double) * n6 * n6);
  double *lub = (double *) malloc (sizeof (double) * n6 * n6);
  double *iml = (double *) malloc (sizeof (double) * n6 * n6);
  double *b = (double *) malloc (sizeof (double) * n6);
  double *x = (double *) malloc (sizeof (double) * n6);
  CHECK_MALLOC (mat, "solve_mob_lub_3ft_matrix");
  CHECK_MALLOC (lub, "solve_mob_lub_3ft_matrix");
  CHECK_MALLOC (iml, "solve_mob_lub_3ft_matrix");
  CHECK_MALLOC (b, "solve_mob_lub_3ft_matrix");
  CHECK_MALLOC (x, "solve_mob_lub_3ft_matrix");

  /* the main calculation is done in the the fluid-rest frame;
   * u(x)=0 as |x|-> infty */

  // M
  make_matrix_mob_3all (sys, mat); // sys->version is 1 (FT)
  // L
  make_matrix_lub_3ft (sys, lub);
  // IML := M.L
  mul_matrices (mat, n6, n6,
		lub, n6, n6,
		iml);
  free (lub);

  /* b := (FT) */
  set_ft_by_FT (np, b, f, t);
  // x := M.(FT)
  dot_prod_matrix (mat, n6, n6, b, x);

  // IML = I + M.L
  int i;
  for (i = 0; i < n6; ++i)
    {
      iml [i * n6 + i] += 1.0;
    }
  // b := (I+M.L)^-1.M.(FT)
  /*
  // IML^-1
  lapack_inv_ (n6, iml);
  dot_prod_matrix (iml, n6, n6, x, b);
  */
  lapack_solve_lin (n6, iml, x, b);

  set_FT_by_ft (np, u, o, b);

  free (mat);
  free (iml);
  free (b);
  free (x);

  /* for the interface, we are in the labo frame, that is
   * u(x) is given by the imposed flow field as |x|-> infty */
  shift_rest_to_labo_U (sys, sys->np, u);
  shift_rest_to_labo_O (sys, sys->np, o);
}