void lis_sort_i(LIS_INT is, LIS_INT ie, LIS_INT *i1)
{
  LIS_INT i,j;
  LIS_INT p,t1;
  LIS_INT v;

  if( ie <= is ) return;

  p = (is+ie)/2;
  v = i1[p];
  lis_swap(i1[p],i1[ie],t1);

  i = is; j = ie;
  while(i<=j)
  {
    while(i1[i] < v) { i++; }
    while(i1[j] > v) { j--; }
    if( i<=j )
    {
      lis_swap(i1[i],i1[j],t1);
      i++; j--;
    }
  }
  lis_sort_i(is,j ,i1);
  lis_sort_i(i ,ie,i1);
}
示例#2
0
void lis_sort_i(int is, int ie, int *i1)
{
	int i,j;
	int p,t1;
	int v;

	if( ie <= is ) return;

	p = (is+ie)/2;
	v = i1[p];
	lis_swap(i1[p],i1[ie],t1);

	i = is; j = ie;
	while(i<=j)
	{
		while(i1[i] < v) { i++; }
		while(i1[j] > v) { j--; }
		if( i<=j )
		{
			lis_swap(i1[i],i1[j],t1);
			i++; j--;
		}
	}
	lis_sort_i(is,j ,i1);
	lis_sort_i(i ,ie,i1);
}
LIS_INT lis_precon_create_ilut_csr(LIS_SOLVER solver, LIS_PRECON precon)
{
#ifdef _OPENMP
  LIS_INT        err;
  LIS_INT        i,j,k,ii,jj,kk;
  LIS_INT        is,ie,my_rank,nprocs;
  LIS_INT        n,nr,nnz,lfil,len;
  LIS_SCALAR    gamma,t,tol,toldd,m;
  LIS_MATRIX    A;
  LIS_MATRIX_ILU  L,U;
  LIS_VECTOR    D;

  LIS_SCALAR    tnorm, tolnorm;
  LIS_SCALAR    fact,lxu,*wn,*w;
  LIS_INT        lenu,lenl,col,jpos,jrow,upos,para;
  LIS_INT        *jbuf,*iw;

  LIS_DEBUG_FUNC_IN;


  A      = solver->A;
  n      = A->n;
  tol    = solver->params[LIS_PARAMS_DROP-LIS_OPTIONS_LEN];
  m      = solver->params[LIS_PARAMS_RATE-LIS_OPTIONS_LEN];
  gamma  = solver->params[LIS_PARAMS_GAMMA-LIS_OPTIONS_LEN];
  lfil   = (LIS_INT)((double)A->nnz/(2.0*n))*m;
  nprocs = omp_get_max_threads();

  L      = NULL;
  U      = NULL;


  err = lis_matrix_ilu_create(n,1,&L);
  if( err ) return err;
  err = lis_matrix_ilu_create(n,1,&U);
  if( err ) return err;
  err = lis_matrix_ilu_setCR(L);
  if( err ) return err;
  err = lis_matrix_ilu_setCR(U);
  if( err ) return err;
  err = lis_vector_duplicate(A,&D);
  if( err )
  {
    return err;
  }

  w   = (LIS_SCALAR *)lis_malloc(nprocs*(n+1)*sizeof(LIS_SCALAR),"lis_precon_create_ilut_csr::w");
  if( w==NULL )
  {
    LIS_SETERR_MEM(nprocs*(n+1)*sizeof(LIS_SCALAR));
    return LIS_OUT_OF_MEMORY;
  }
  wn = (LIS_SCALAR *)lis_malloc(nprocs*n*sizeof(LIS_SCALAR),"lis_precon_create_ilut_csr::w");
  if( wn==NULL )
  {
    LIS_SETERR_MEM(nprocs*n*sizeof(LIS_SCALAR));
    return LIS_OUT_OF_MEMORY;
  }

  jbuf   = (LIS_INT *)lis_malloc(nprocs*n*sizeof(LIS_INT),"lis_precon_create_ilut_csr::iw");
  if( jbuf==NULL )
  {
    LIS_SETERR_MEM(nprocs*n*sizeof(LIS_INT));
    return LIS_OUT_OF_MEMORY;
  }
  iw   = (LIS_INT *)lis_malloc(nprocs*n*sizeof(LIS_INT),"lis_precon_create_ilut_csr::iw");
  if( iw==NULL )
  {
    LIS_SETERR_MEM(nprocs*n*sizeof(LIS_INT));
    return LIS_OUT_OF_MEMORY;
  }


  #pragma omp parallel private(is,ie,my_rank,i,j,k,jj,tnorm,tolnorm,len,lenu,lenl,col,t,jpos,jrow,fact,lxu,upos)
  {
    my_rank  = omp_get_thread_num();
    LIS_GET_ISIE(my_rank,nprocs,n,is,ie);

    for(i=is;i<ie;i++) iw[my_rank*n+i] = -1;

    for(i=is;i<ie;i++)
    {
      tnorm = 0;
      k = 0;
      for(j=A->ptr[i];j<A->ptr[i+1];j++)
      {
        jj = A->index[j];
        if( jj<is || jj>=ie ) continue;
        tnorm += fabs(A->value[j]);
        k++;
      }
      tnorm   = tnorm / (double)k;
      tolnorm = tol * tnorm;

      lenu = 0;
      lenl = 0;
      jbuf[my_rank*n+i] = i;
      w[my_rank*n+i] = 0;
      iw[my_rank*n+i] = i;

      for(j=A->ptr[i];j<A->ptr[i+1];j++)
      {
        col = A->index[j];
        if( col<is || col>=ie ) continue;
        t = A->value[j];
        if( col < i )
        {
          jbuf[my_rank*n+lenl] = col;
          iw[my_rank*n+col] = lenl;
          w[my_rank*n+lenl] = t;
          lenl++;
        }
        else if( col == i )
        {
          w[my_rank*n+i] = t;
        }
        else
        {
          lenu++;
          jpos = i + lenu;
          jbuf[my_rank*n+jpos] = col;
          iw[my_rank*n+col] = jpos;
          w[my_rank*n+jpos] = t;
        }
      }

      j = -1;
      len = 0;

      while( ++j < lenl )
      {
        jrow = jbuf[my_rank*n+j];
        jpos = j;
        for(k=j+1;k<lenl;k++)
        {
          if( jbuf[my_rank*n+k]<jrow )
          {
            jrow = jbuf[my_rank*n+k];
            jpos = k;
          }
        }
        if( jpos!=j )
        {
          col = jbuf[my_rank*n+j];
          jbuf[my_rank*n+j] = jbuf[my_rank*n+jpos];
          jbuf[my_rank*n+jpos] = col;
          iw[my_rank*n+jrow] = j;
          iw[my_rank*n+col] = jpos;
          t = w[my_rank*n+j];
          w[my_rank*n+j] = w[my_rank*n+jpos];
          w[my_rank*n+jpos] = t;
        }
        fact = w[my_rank*n+j] * D->value[jrow];
        w[my_rank*n+j] = fact;
        iw[my_rank*n+jrow] = -1;

        for(k=0;k<U->nnz[jrow];k++)
        {
          col = U->index[jrow][k];
          jpos = iw[my_rank*n+col];
          lxu = -fact * U->value[jrow][k];

          if( fabs(lxu) < tolnorm && jpos==-1 ) continue;
          if( col >= i )
          {
            if( jpos == -1 )
            {
              lenu++;
              upos = i + lenu;
              jbuf[my_rank*n+upos] = col;
              iw[my_rank*n+col] = upos;
              w[my_rank*n+upos] = lxu;
            }
            else
            {
              w[my_rank*n+jpos] += lxu;
            }
          }
          else
          {
            if( jpos == -1 )
            {
              jbuf[my_rank*n+lenl] = col;
              iw[my_rank*n+col] = lenl;
              w[my_rank*n+lenl] = lxu;
              lenl++;
            }
            else
            {
              w[my_rank*n+jpos] += lxu;
            }
          }
        }
      }

      iw[my_rank*n+i] = -1;
      for(j=0;j<lenu;j++)
      {
        iw[ my_rank*n+jbuf[my_rank*n+i+j+1] ] = -1;
      }

      D->value[i] = 1.0 / w[my_rank*n+i];


      len = _min(lfil,lenl);
      for(j=0;j<lenl;j++)
      {
        wn[my_rank*n+j] = fabs(w[my_rank*n+j]);
        iw[my_rank*n+j] = j;
      }
      lis_sort_di(0,lenl-1,&wn[my_rank*n],&iw[my_rank*n]);
      lis_sort_i(0,len-1,&iw[my_rank*n]);
      
      L->nnz[i] = len;
      if( len>0 )
      {
        L->index[i] = (LIS_INT *)malloc(len*sizeof(LIS_INT));
        L->value[i] = (LIS_SCALAR *)malloc(len*sizeof(LIS_SCALAR));
      }
      for(j=0;j<len;j++)
      {
        jpos = iw[my_rank*n+j];
        L->index[i][j] = jbuf[my_rank*n+jpos];
        L->value[i][j] = w[my_rank*n+jpos];
      }
      for(j=0;j<lenl;j++) iw[my_rank*n+j] = -1;

      len = _min(lfil,lenu);
      for(j=0;j<lenu;j++)
      {
        wn[my_rank*n+j] = fabs(w[my_rank*n+i+j+1]);
        iw[my_rank*n+j] = i+j+1;
      }
      lis_sort_di(0,lenu-1,&wn[my_rank*n],&iw[my_rank*n]);
      lis_sort_i(0,len-1,&iw[my_rank*n]);
      
      U->nnz[i] = len;
      if( len>0 )
      {
        U->index[i] = (LIS_INT *)malloc(len*sizeof(LIS_INT));
        U->value[i] = (LIS_SCALAR *)malloc(len*sizeof(LIS_SCALAR));
      }
      for(j=0;j<len;j++)
      {
        jpos = iw[my_rank*n+j];
        U->index[i][j] = jbuf[my_rank*n+jpos];
        U->value[i][j] = w[my_rank*n+jpos];
      }
      for(j=0;j<lenu;j++) iw[my_rank*n+j] = -1;
    }
  }

  precon->L  = L;
  precon->U  = U;
  precon->D  = D;

  lis_free2(4,w,iw,wn,jbuf);

  LIS_DEBUG_FUNC_OUT;
  return LIS_SUCCESS;
#else
  LIS_INT        err;
  LIS_INT        i,j,k;
  LIS_INT        n,lfil,len;
  LIS_SCALAR    gamma,t,tol,m;
  LIS_MATRIX    A;
  LIS_MATRIX_ILU  L,U;
  LIS_VECTOR    D;

  LIS_SCALAR    tnorm, tolnorm;
  LIS_SCALAR    fact,lxu,*wn,*w;
  LIS_INT        lenu,lenl,col,jpos,jrow,upos;
  LIS_INT        *jbuf,*iw;

  LIS_DEBUG_FUNC_IN;


  A      = solver->A;
  n      = A->n;
  tol    = solver->params[LIS_PARAMS_DROP-LIS_OPTIONS_LEN];
  m      = solver->params[LIS_PARAMS_RATE-LIS_OPTIONS_LEN];
  gamma  = solver->params[LIS_PARAMS_GAMMA-LIS_OPTIONS_LEN];
  lfil   = (LIS_INT)(((double)A->nnz/(2.0*n))*m);

  L      = NULL;
  U      = NULL;


  err = lis_matrix_ilu_create(n,1,&L);
  if( err ) return err;
  err = lis_matrix_ilu_create(n,1,&U);
  if( err ) return err;
  err = lis_matrix_ilu_setCR(L);
  if( err ) return err;
  err = lis_matrix_ilu_setCR(U);
  if( err ) return err;
  err = lis_vector_duplicate(A,&D);
  if( err )
  {
    return err;
  }

  w   = (LIS_SCALAR *)lis_malloc((n+1)*sizeof(LIS_SCALAR),"lis_precon_create_ilut_csr::w");
  if( w==NULL )
  {
    LIS_SETERR_MEM(n*sizeof(LIS_SCALAR));
    return LIS_OUT_OF_MEMORY;
  }
  wn = (LIS_SCALAR *)lis_malloc(n*sizeof(LIS_SCALAR),"lis_precon_create_ilut_csr::w");
  if( wn==NULL )
  {
    LIS_SETERR_MEM(n*sizeof(LIS_SCALAR));
    return LIS_OUT_OF_MEMORY;
  }

  jbuf   = (LIS_INT *)lis_malloc(n*sizeof(LIS_INT),"lis_precon_create_ilut_csr::iw");
  if( jbuf==NULL )
  {
    LIS_SETERR_MEM(n*sizeof(LIS_INT));
    return LIS_OUT_OF_MEMORY;
  }
  iw   = (LIS_INT *)lis_malloc(n*sizeof(LIS_INT),"lis_precon_create_ilut_csr::iw");
  if( iw==NULL )
  {
    LIS_SETERR_MEM(n*sizeof(LIS_INT));
    return LIS_OUT_OF_MEMORY;
  }


  for(i=0;i<n;i++) iw[i] = -1;

  for(i=0;i<n;i++)
  {
    tnorm = 0;
    for(j=A->ptr[i];j<A->ptr[i+1];j++)
    {
      tnorm += fabs(A->value[j]);
    }
    tnorm   = tnorm / (double)(A->ptr[i+1]-A->ptr[i]);
    tolnorm = tol * tnorm;

    lenu = 0;
    lenl = 0;
    jbuf[i] = i;
    w[i] = 0;
    iw[i] = i;

    for(j=A->ptr[i];j<A->ptr[i+1];j++)
    {
      col = A->index[j];
      #ifdef USE_MPI
        if( col>n-1 ) continue;
      #endif
      t = A->value[j];
      if( col < i )
      {
        jbuf[lenl] = col;
        iw[col] = lenl;
        w[lenl] = t;
        lenl++;
      }
      else if( col == i )
      {
        w[i] = t;
      }
      else
      {
        lenu++;
        jpos = i + lenu;
        jbuf[jpos] = col;
        iw[col] = jpos;
        w[jpos] = t;
      }
    }

    j = -1;
    len = 0;

    while( ++j < lenl )
    {
      jrow = jbuf[j];
      jpos = j;
      for(k=j+1;k<lenl;k++)
      {
        if( jbuf[k]<jrow )
        {
          jrow = jbuf[k];
          jpos = k;
        }
      }
      if( jpos!=j )
      {
        col = jbuf[j];
        jbuf[j] = jbuf[jpos];
        jbuf[jpos] = col;
        iw[jrow] = j;
        iw[col] = jpos;
        t = w[j];
        w[j] = w[jpos];
        w[jpos] = t;
      }
      fact = w[j] * D->value[jrow];
      w[j] = fact;
      iw[jrow] = -1;

      for(k=0;k<U->nnz[jrow];k++)
      {
        col = U->index[jrow][k];
        jpos = iw[col];
        lxu = -fact * U->value[jrow][k];

        if( fabs(lxu) < tolnorm && jpos==-1 ) continue;
        if( col >= i )
        {
          if( jpos == -1 )
          {
            lenu++;
            upos = i + lenu;
            jbuf[upos] = col;
            iw[col] = upos;
            w[upos] = lxu;
          }
          else
          {
            w[jpos] += lxu;
          }
        }
        else
        {
          if( jpos == -1 )
          {
            jbuf[lenl] = col;
            iw[col] = lenl;
            w[lenl] = lxu;
            lenl++;
          }
          else
          {
            w[jpos] += lxu;
          }
        }
      }
/*      for(kk=0;kk<bs;kk++)
      {
        w[bs*len+kk] = -buf_fact[kk];
      }
      jbuf[len] = jrow;
      len++;*/
    }

    iw[i] = -1;
    for(j=0;j<lenu;j++)
    {
      iw[ jbuf[i+j+1] ] = -1;
    }

    D->value[i] = 1.0 / w[i];


    len = _min(lfil,lenl);
    for(j=0;j<lenl;j++)
    {
      wn[j] = fabs(w[j]);
      iw[j] = j;
    }
    lis_sort_di(0,lenl-1,wn,iw);
    lis_sort_i(0,len-1,iw);
    
    L->nnz[i] = len;
    if( len>0 )
    {
      L->index[i] = (LIS_INT *)malloc(len*sizeof(LIS_INT));
      L->value[i] = (LIS_SCALAR *)malloc(len*sizeof(LIS_SCALAR));
    }
    for(j=0;j<len;j++)
    {
      jpos = iw[j];
      L->index[i][j] = jbuf[jpos];
      L->value[i][j] = w[jpos];
    }
    for(j=0;j<lenl;j++) iw[j] = -1;

    len = _min(lfil,lenu);
    for(j=0;j<lenu;j++)
    {
      wn[j] = fabs(w[i+j+1]);
      iw[j] = i+j+1;
    }
    lis_sort_di(0,lenu-1,wn,iw);
    lis_sort_i(0,len-1,iw);
    
    U->nnz[i] = len;
    if( len>0 )
    {
      U->index[i] = (LIS_INT *)malloc(len*sizeof(LIS_INT));
      U->value[i] = (LIS_SCALAR *)malloc(len*sizeof(LIS_SCALAR));
    }
    for(j=0;j<len;j++)
    {
      jpos = iw[j];
      U->index[i][j] = jbuf[jpos];
      U->value[i][j] = w[jpos];
    }
    for(j=0;j<lenu;j++) iw[j] = -1;
  }

  precon->L  = L;
  precon->U  = U;
  precon->D  = D;

  lis_free2(4,w,iw,wn,jbuf);

  LIS_DEBUG_FUNC_OUT;
  return LIS_SUCCESS;
#endif
}
LIS_INT lis_precon_create_ilut_bsr(LIS_SOLVER solver, LIS_PRECON precon)
{
  LIS_INT        err;
  LIS_INT        i,j,k,kk,bnr,bs;
  LIS_INT        n,nr,annz,lfil,len;
  LIS_SCALAR    gamma,t,tol,m;
  LIS_MATRIX    A;
  LIS_MATRIX_ILU  L,U;
  LIS_MATRIX_DIAG  D;

  LIS_SCALAR    tnorm, tolnorm;
  LIS_SCALAR    buf_ns[16],buf_fact[16],*xnrm,*wn,*w;
  LIS_INT        lenu,lenl,col,jpos,jrow,upos,para;
  LIS_INT        *jbuf,*iw;

  LIS_DEBUG_FUNC_IN;


  A      = solver->A;
  n      = A->n;
  nr     = A->nr;
  bnr    = A->bnr;
  bs     = bnr*bnr;
  tol    = solver->params[LIS_PARAMS_DROP-LIS_OPTIONS_LEN];
  m      = solver->params[LIS_PARAMS_RATE-LIS_OPTIONS_LEN];
  gamma  = solver->params[LIS_PARAMS_GAMMA-LIS_OPTIONS_LEN];
  annz   = 10+A->bnnz / A->nr;
  lfil   = (LIS_INT)(((double)A->bnnz/(2.0*nr))*m);

  L      = NULL;
  U      = NULL;


  err = lis_matrix_ilu_create(nr,bnr,&L);
  if( err ) return err;
  err = lis_matrix_ilu_create(nr,bnr,&U);
  if( err ) return err;
  err = lis_matrix_ilu_setCR(L);
  if( err ) return err;
  err = lis_matrix_ilu_setCR(U);
  if( err ) return err;
  err = lis_matrix_diag_duplicateM(A,&D);
  if( err )
  {
    return err;
  }

  w   = (LIS_SCALAR *)lis_malloc(bs*(nr+1)*sizeof(LIS_SCALAR),"lis_precon_create_iluc_csr::w");
  if( w==NULL )
  {
    LIS_SETERR_MEM(n*sizeof(LIS_SCALAR));
    return LIS_OUT_OF_MEMORY;
  }
  xnrm = (LIS_SCALAR *)lis_malloc(nr*sizeof(LIS_SCALAR),"lis_precon_create_iluc_csr::w");
  if( xnrm==NULL )
  {
    LIS_SETERR_MEM(n*sizeof(LIS_SCALAR));
    return LIS_OUT_OF_MEMORY;
  }
  wn = (LIS_SCALAR *)lis_malloc(nr*sizeof(LIS_SCALAR),"lis_precon_create_iluc_csr::w");
  if( wn==NULL )
  {
    LIS_SETERR_MEM(n*sizeof(LIS_SCALAR));
    return LIS_OUT_OF_MEMORY;
  }

  jbuf   = (LIS_INT *)lis_malloc(n*sizeof(LIS_INT),"lis_precon_create_iluc_csr::iw");
  if( jbuf==NULL )
  {
    LIS_SETERR_MEM(n*sizeof(LIS_INT));
    return LIS_OUT_OF_MEMORY;
  }
  iw   = (LIS_INT *)lis_malloc(nr*sizeof(LIS_INT),"lis_precon_create_iluc_csr::iw");
  if( iw==NULL )
  {
    LIS_SETERR_MEM(n*sizeof(LIS_INT));
    return LIS_OUT_OF_MEMORY;
  }


  for(i=0;i<nr;i++) iw[i] = -1;

  for(i=0;i<nr;i++)
  {
    tnorm = 0;
    for(j=A->bptr[i];j<A->bptr[i+1];j++)
    {
      lis_array_nrm2(bs,&A->value[bs*j],&t);
      tnorm = _max(t,tnorm);
    }
    tolnorm = tol * tnorm;

    lenu = 1;
    lenl = 0;
    jbuf[i] = i;
    memset(&w[bs*i],0,bs*sizeof(LIS_SCALAR));
    iw[i] = i;

    for(j=A->bptr[i];j<A->bptr[i+1];j++)
    {
      col = A->bindex[j];
      lis_array_nrm2(bs,&A->value[bs*j],&t);
      if( t<tolnorm && col!=i ) continue;
      if( col < i )
      {
        jbuf[lenl] = col;
        iw[col] = lenl;
        memcpy(&w[bs*lenl],&A->value[bs*j],bs*sizeof(LIS_SCALAR));
        lenl++;
      }
      else if( col == i )
      {
        memcpy(&w[bs*i],&A->value[bs*j],bs*sizeof(LIS_SCALAR));
      }
      else
      {
        jpos = i + lenu;
        jbuf[jpos] = col;
        iw[col] = jpos;
        memcpy(&w[bs*jpos],&A->value[bs*j],bs*sizeof(LIS_SCALAR));
        lenu++;
      }
    }

    j = -1;
    len = 0;

    while( ++j < lenl )
    {
      jrow = jbuf[j];
      jpos = j;
      for(k=j+1;k<lenl;k++)
      {
        if( jbuf[k]<jrow )
        {
          jrow = jbuf[k];
          jpos = k;
        }
      }
      if( jpos!=j )
      {
        col = jbuf[j];
        jbuf[j] = jbuf[jpos];
        jbuf[jpos] = col;
        iw[jrow] = j;
        iw[col] = jpos;
        memcpy(buf_ns,&w[bs*j],bs*sizeof(LIS_SCALAR));
        memcpy(&w[bs*j],&w[bs*jpos],bs*sizeof(LIS_SCALAR));
        memcpy(&w[bs*jpos],buf_ns,bs*sizeof(LIS_SCALAR));
      }
/*      lis_array_matmat(bnr,&D->value[bs*jrow],&w[bs*j],buf_fact,LIS_INS_VALUE);*/
      lis_array_matinv(bnr,&D->value[bs*jrow],&w[bs*j],buf_fact);
      iw[jrow] = -1;

      lis_array_nrm2(bs,buf_fact,&t);
      if( t * xnrm[jrow] <= tolnorm ) continue;

      for(k=0;k<U->nnz[jrow];k++)
      {
        col = U->index[jrow][k];
        lis_array_matmat(bnr,buf_fact,&U->value[jrow][bs*k],buf_ns,LIS_INS_VALUE);
        jpos = iw[col];

        lis_array_nrm2(bs,buf_ns,&t);
        if( t < tolnorm && jpos == -1 )
        {
          continue;
        }

        if( col >= i )
        {
          if( jpos == -1 )
          {
            upos = i + lenu;
            jbuf[upos] = col;
            iw[col] = upos;
            memcpy(&w[bs*upos],buf_ns,bs*sizeof(LIS_SCALAR));
            lenu++;
          }
          else
          {
            for(kk=0;kk<bs;kk++)
            {
              w[bs*jpos+kk] += buf_ns[kk];
            }
          }
        }
        else
        {
          if( jpos == -1 )
          {
            jbuf[lenl] = col;
            iw[col] = lenl;
            memcpy(&w[bs*lenl],buf_ns,bs*sizeof(LIS_SCALAR));
            lenl++;
          }
          else
          {
            for(kk=0;kk<bs;kk++)
            {
              w[bs*jpos+kk] += buf_ns[kk];
            }
          }
        }
      }
      for(kk=0;kk<bs;kk++)
      {
        w[bs*len+kk] = -buf_fact[kk];
      }
      jbuf[len] = jrow;
      len++;
    }
    lenl = len;
    len = _min(lfil,lenl);
    for(j=0;j<lenl;j++)
    {
      lis_array_nrm2(bs,&w[bs*j],&wn[j]);
      iw[j] = j;
    }
    lis_sort_di(0,lenl-1,wn,iw);
    lis_sort_i(0,len-1,iw);
    
    L->nnz[i] = len;
    if( len>0 )
    {
      L->index[i] = (LIS_INT *)malloc(len*sizeof(LIS_INT));
      L->value[i] = (LIS_SCALAR *)malloc(bs*len*sizeof(LIS_SCALAR));
    }
    for(j=0;j<len;j++)
    {
      jpos = iw[j];
      L->index[i][j] = jbuf[jpos];
      memcpy(&L->value[i][bs*j],&w[bs*jpos],bs*sizeof(LIS_SCALAR));
    }
    for(j=0;j<lenl;j++) iw[j] = -1;

    len = _min(lfil,lenu);
    for(j=1;j<lenu;j++)
    {
      jpos = i+j;
      lis_array_nrm2(bs,&w[bs*jpos],&wn[j-1]);
      iw[j-1] = jpos;
    }
    para = lenu - 1;
    lis_sort_di(0,para-1,wn,iw);
    lis_sort_i(0,len-2,iw);
    
    U->nnz[i] = len-1;
    if( len>1 )
    {
      U->index[i] = (LIS_INT *)malloc((len-1)*sizeof(LIS_INT));
      U->value[i] = (LIS_SCALAR *)malloc(bs*(len-1)*sizeof(LIS_SCALAR));
    }
    lis_array_nrm2(bs,&w[bs*i],&t);
    for(j=0;j<len-1;j++)
    {
      jpos = iw[j];
      U->index[i][j] = jbuf[jpos];
      memcpy(&U->value[i][bs*j],&w[bs*jpos],bs*sizeof(LIS_SCALAR));
      t = _max(t,wn[j]);
    }
    for(j=0;j<lenu-1;j++) iw[j] = -1;

    xnrm[i] = t;

    memcpy(&D->value[bs*i],&w[bs*i],bs*sizeof(LIS_SCALAR));

    if( i==nr-1 )
    {
      switch(bnr)
      {
      case 2:
        if( n%2!=0 )
        {
          D->value[4*(nr-1)+3] = 1.0;
        }
        break;
      case 3:
        if( n%3==1 )
        {
          D->value[9*(nr-1)+4] = 1.0;
          D->value[9*(nr-1)+8] = 1.0;
        }
        else if( n%3==2 )
        {
          D->value[9*(nr-1)+8] = 1.0;
        }
        break;
      }
    }
/*    lis_array_invGauss(bnr,&D->value[bs*i]);*/
    lis_array_LUdecomp(bnr,&D->value[bs*i]);

    for(j=0;j<lenu;j++)
    {
      iw[ jbuf[i+j] ] = -1;
    }
  }

  precon->L  = L;
  precon->U  = U;
  precon->WD  = D;

  lis_free2(5,w,iw,xnrm,wn,jbuf);

  LIS_DEBUG_FUNC_OUT;
  return LIS_SUCCESS;
}