Ejemplo n.º 1
0
int AZ_adjust_N_nz_to_fit_memory(int N,int N_int_arrays, int N_dbl_arrays)
{
/****************************************************************************
  Find (and return) the largest value of k <= N such that we can 
  successfully allocate  N_int_arrays integer arrays of size k and 
  N_dbl_arrays double arrays of size k.

  Author:          Ray Tuminaro, SNL, 9222
 
  Return code:     int
  ============
 
  Parameter list:
  ===============
 
  N:               On input, the maximum number of integers and doubles
                   that we wish to try and allocate.
 */

   double **dptr;
   int    **iptr;
   int    i;

   iptr = (int **) AZ_allocate(N_int_arrays*sizeof(int *));
   dptr = (double **) AZ_allocate(N_dbl_arrays*sizeof(double *));

   if ( (dptr == 0) || (iptr == 0) ) 
      AZ_perror("ERROR: not enough memory for preconditioner.\n");

   for (i = 0 ; i < N_int_arrays ; i++ ) 
      iptr[i] = (int    *) AZ_allocate((N+20)*sizeof(int));
   for (i = 0 ; i < N_dbl_arrays ; i++ ) 
      dptr[i] = (double *) AZ_allocate((N+20)*sizeof(double));
                                   /* add a little extra */
                                   /* for manage memory  */
 
   /* Decrease memory until the problem fits */
 
   while ( (dptr[N_dbl_arrays-1] == NULL) || 
           (iptr[N_int_arrays-1] == NULL) ) {

      for (i = N_dbl_arrays-1 ; i >= 0; i-- ) 
         if (dptr[i] != NULL) AZ_free(dptr[i]);
      for (i = N_int_arrays-1 ; i >= 0; i-- ) 
         if (iptr[i] != NULL) AZ_free(iptr[i]);

      N = (int) ( ((double) N)*.91);
      if (N == 0) AZ_perror("ERROR: not enough memory for preconditioner.\n");
 
      for (i = 0 ; i < N_int_arrays ; i++ ) 
         iptr[i] = (int    *) AZ_allocate((N+20)*sizeof(int));
      for (i = 0 ; i < N_dbl_arrays ; i++ ) 
         dptr[i] = (double *) AZ_allocate((N+20)*sizeof(double));
   }
   for (i = N_dbl_arrays-1 ; i >= 0; i-- ) AZ_free(dptr[i]);
   for (i = N_int_arrays-1 ; i >= 0; i-- ) AZ_free(iptr[i]);
   AZ_free(dptr);
   AZ_free(iptr);
   return(N);
}
Ejemplo n.º 2
0
void AZK_create_vector_c2k(int *options, double *params,
		       int *proc_config, AZ_MATRIX *Amat_komplex,
                       double *vc, double **vk)
{
  AZ_KOMPLEX *linsys_pass_data;
  int i;
  int N_equations, N_external;
  int *data_org, *rpntr, *update_index;

  /* First executable statement */

  linsys_pass_data = (AZ_KOMPLEX *) Amat_komplex->aux_ptr;
  data_org = Amat_komplex->data_org;
  update_index = linsys_pass_data->update_index;
  rpntr = Amat_komplex->rpntr;

  N_equations = data_org[AZ_N_internal] + data_org[AZ_N_border];

  N_external = data_org[AZ_N_external];

  (*vk) = (double *) AZ_allocate((N_equations+N_external)*sizeof(double));
  if ((*vk) == NULL) AZ_perror("AZK_create_vector_c2k: Out of memory");

  for (i=0; i <N_equations; i++) (*vk)[i] = vc[i];

  /* Check if we need to reorder vector */

  if (linsys_pass_data->From_Global_Indices)
   AZ_reorder_vec((*vk), data_org, update_index, rpntr);

  return;
}
Ejemplo n.º 3
0
void AZK_create_linsys_no_copy(double *xr, double *xi, double *br, double *bi,
                               int *options, double *params, int *proc_config,
                               AZ_MATRIX *Amat_real, AZ_MATRIX *Amat_imag,
                               double **x, double **b, AZ_MATRIX **Amat)
{
    /*
       Transforms a complex-valued system

             (Ar +i*Ai) * (xr + i*xi) = (br + i*bi)

       where double precision arrays hold the real and imaginary parts separately.

     Input arguments:
     ================

     xr,xi:         On input, contains the initial guess, real part in xr and
                    imaginary part in xi. On output contains the solution to
                    the linear system.

     br,bi:         Right hand side of linear system.

     Output arguments:
     =================

     x:             Komplex version of initial guess and solution.
     b:             Komplex version of RHS.
     Amat:          Komplex version of matrix stored as an AZ_MATRIX structure.

    */
    AZ_KOMPLEX *linsys_pass_data;
    int N_equations, N_blk_equations, N_real, N_external;
    int *data_org_real, *data_org_imag;
    int *komplex_to_real, *komplex_to_imag;
    int i;


    if (Amat_real->has_global_indices || Amat_imag->has_global_indices)
        AZ_perror("AZK_create_linsys_no_copy requires local indices");

    linsys_pass_data = (AZ_KOMPLEX *) AZ_allocate(sizeof(AZ_KOMPLEX));
    if (linsys_pass_data == NULL)
        AZ_perror("AZK_create_linsys_no_copy: Out of memory.");
    data_org_real = Amat_real->data_org;
    data_org_imag = Amat_imag->data_org;
    N_real = data_org_real[AZ_N_internal] + data_org_real[AZ_N_border];

    N_equations = 2 * N_real;
    N_blk_equations = N_equations;

    N_external = AZ_MAX(data_org_real[AZ_N_external], data_org_imag[AZ_N_external]);

    if (Amat_real->matrix_type == AZ_MSR_MATRIX) {
        Amat_real->data_org[AZ_N_int_blk] = Amat_real->data_org[AZ_N_internal];
        Amat_real->data_org[AZ_N_bord_blk] = Amat_real->data_org[AZ_N_border];
        N_blk_equations = N_equations;
    }

    else if (Amat_real->matrix_type == AZ_VBR_MATRIX)
    {
        N_blk_equations = data_org_real[AZ_N_int_blk] + data_org_real[AZ_N_bord_blk];
    }
    else if (Amat_real->matrix_type == AZ_USER_MATRIX) {
        Amat_real->data_org[AZ_N_int_blk] = Amat_real->data_org[AZ_N_internal];
        Amat_real->data_org[AZ_N_bord_blk] = Amat_real->data_org[AZ_N_border];
        N_blk_equations = N_equations;
    }
    else
        AZ_perror("AZK_create_linsys_no_copy: Unknown matrix type.");

    if (Amat_imag->matrix_type == AZ_MSR_MATRIX) {
        Amat_imag->data_org[AZ_N_int_blk] = Amat_imag->data_org[AZ_N_internal];
        Amat_imag->data_org[AZ_N_bord_blk] = Amat_imag->data_org[AZ_N_border];
    }

    else if (Amat_imag->matrix_type == AZ_USER_MATRIX) {
        Amat_imag->data_org[AZ_N_int_blk] = Amat_imag->data_org[AZ_N_internal];
        Amat_imag->data_org[AZ_N_bord_blk] = Amat_imag->data_org[AZ_N_border];
    }

    (*Amat) = AZ_create_matrix(N_equations, 0,
                               AZ_USER_MATRIX, N_blk_equations,
                               AZ_NOT_USING_AZTEC_MATVEC);

    /* Merge real and imaginary parts into K matrix order */
    komplex_to_real = (int *) AZ_allocate (N_real*sizeof(int));
    komplex_to_imag = (int *) AZ_allocate (N_real*sizeof(int));
    (*x) = (double *) AZ_allocate((N_equations+N_external)*sizeof(double));
    (*b) = (double *) AZ_allocate((N_equations+N_external)*sizeof(double));
    if ((*b) == NULL)
        AZ_perror("AZK_create_linsys_no_copy: Out of memory.");
    for (i=0; i <N_real; i++)
    {
        komplex_to_real[i] = 2*i;
        komplex_to_imag[i] = 2*i+1;
        (*x)[komplex_to_real[i]] = xr[i];
        (*x)[komplex_to_imag[i]] = xi[i];
        (*b)[komplex_to_real[i]] = br[i];
        (*b)[komplex_to_imag[i]] = bi[i];
    }
    linsys_pass_data->Amat_real = Amat_real;
    linsys_pass_data->Amat_imag = Amat_imag;
    linsys_pass_data->komplex_to_real = komplex_to_real;
    linsys_pass_data->komplex_to_imag = komplex_to_imag;

    linsys_pass_data->c11 = 1.0;
    linsys_pass_data->c12 = 0.0;
    linsys_pass_data->c21 = 0.0;
    linsys_pass_data->c22 = 1.0;
    linsys_pass_data->Form_of_Equations = AZK_Komplex_No_Copy;
    linsys_pass_data->From_Global_Indices = 0;

    (*Amat)->matvec  = AZK_matvec_no_copy;
    (*Amat)->aux_ptr = (void *)  linsys_pass_data;

    return;
}
Ejemplo n.º 4
0
void AZ_space_for_padded_matrix(int overlap, int N_nonzeros, int N, 
    int *extra_rows, int *extra_nonzeros, int N_external, int *largest)
 
{
/****************************************************************************
  Estimate the number of additional rows and nonzeros due to overlapping.
  Currently, this estimate is based on the number of external variables
  and the number of nonzeros per row.

  Author:          Ray Tuminaro, SNL, 9222
 
  Return code:     void
  ============
 
  Parameter list:
  ===============
 
  overlap:         On input, 

                      == AZ_none: nonoverlapping domain decomposition
                      == AZ_diag: use rows corresponding to external variables
                                  but only keep the diagonal for these rows.
                      == k      : Obtain rows that are a distance k away from
                                  rows owned by this processor.
  
  N_nonzeros:      On input, number of nonzeros in the unpadded matrix.

  N:               On input, number of rows in the unpadded matrix.

  extra_rows:      On output, estimate of the number of additional rows 
                   needed for padding the matrix corresponding to 'overlap'.

  extra_nonzeros:  On output, estimate of the number of additional nonzeros
                   needed for padding the matrix corresponding to 'overlap'.
 
  N_external:      On input, number of external variables corresponding to
                   the unpadded matrix.

  largest:         On output, estimate of the maximum number of nonzeros
                   in any row due to overlapping.

****************************************************************************/
    int i;
    double new_exts, d_externs;
int temp;

    if ( (overlap == 0) || (overlap == AZ_diag) ) {
       *extra_rows     = N_external;
       *extra_nonzeros = N_external;
       *largest = 1;
    }
    else if (overlap >= 1) {

       /* we must estimate in this case */

       *extra_rows     = (int) 5.5*((double) (N_external*overlap));
d_externs = (double) N_external;
new_exts =  d_externs;
for (i = 2; i <= overlap; i++ ) {
   new_exts = new_exts + 4.*(sqrt(3.14159*new_exts)+3.14159);
                       /* This formula is based on the growth in */
                       /* the surface area of a sphere.          */
                       /*   S_0 = 4 pi r^2                       */
                       /*   S_1 = 4 pi (r+1)^2                   */
                       /*       = S_0 + 4 pi + 8 pi r            */
                       /*   substitute sqrt(S_0/(4 pi)) for r    */
                       /*   S_1 = S_0 + 4 ( pi + sqrt(S_0 pi))   */
   d_externs += new_exts;
}
*extra_rows = (int) d_externs;
*extra_rows = (*extra_rows)*2 + 30;

       if (N != 0) {
          temp = N_nonzeros/N;
          *extra_nonzeros = N + (*extra_rows)*temp;
          *largest        = 3.5*N_nonzeros/N;
          *extra_rows     += 25;
          *extra_nonzeros += 25;
          *largest        += 25;
       }
       else {
          *extra_rows     = 0;
          *extra_nonzeros = 0;
          *largest        = 0;
       }
    }
    else AZ_perror("Inproper level of overlap\n");
}
Ejemplo n.º 5
0
void AZK_create_precon(int *options, double *params,
    int *proc_config,double *x, double *b,
    AZ_MATRIX *Amat, AZ_PRECOND **Prec)
{
  AZ_KOMPLEX *pass_data, *Prec_pass_data;
  AZ_MATRIX *Pmat, *Amat_real, *Amat_imag;
  int N_equations, N_real;
  int *data_org_real, *data_org_imag;
  double *val;
  int i, is_VBR;

  /* Extract necessary data from pass_data */

  pass_data      = (AZ_KOMPLEX *) Amat->aux_ptr;

  if (pass_data->Form_of_Equations != AZK_Komplex_No_Copy)
    (*Prec) = AZ_precond_create(Amat,AZ_precondition,NULL);
  else
  {
    Amat_real = pass_data->Amat_real; /* Real operator in AZ_MATRIX struct */
    Amat_imag = pass_data->Amat_imag; /* Imag operator in AZ_MATRIX struct */

    data_org_real = Amat_real->data_org;
    data_org_imag = Amat_imag->data_org;
    N_real = data_org_real[AZ_N_internal] + data_org_real[AZ_N_border];

    N_equations = 2 * N_real;
    if (data_org_real[AZ_matrix_type] == AZ_VBR_MATRIX &&
        data_org_imag[AZ_matrix_type] == AZ_VBR_MATRIX )
    {
      is_VBR = 1;
    }
    else if (data_org_real[AZ_matrix_type] == AZ_MSR_MATRIX &&
        data_org_imag[AZ_matrix_type] == AZ_MSR_MATRIX)
    {
      is_VBR = 0;
    }
    else
    {
      printf("Unsupported Matrix types\n");
      abort();
    }

    /* set the preconditioning structure 'Prec'. */

    Prec_pass_data = (AZ_KOMPLEX *) AZ_allocate(sizeof(AZ_KOMPLEX));
    if (Prec_pass_data == NULL)
      AZ_perror("AZK_create_precon: Out of memory.");


    switch (options[AZ_precond]) {

      /* NO preconditioning. There is nothing to do                 */
      /* We just need to give a valid matrix to the preconditioning */
      case AZ_none:
        (*Prec) = AZ_precond_create(Amat,AZ_precondition,NULL);
        break;

        /* Polynomial preconditioning (least-squares or Neumann).     */
        /* Here we must give Aztec an upper bound for the norm of the */
        /* matrix. In addition, we need to tell Aztec to use the      */
        /* USER's matrix-vector product when applying the polynomial  */
        /* preconditioner.                                            */

      case AZ_ls:
      case AZ_Neumann:
        Amat->matrix_norm = 8.0;
        (*Prec) = AZ_precond_create(Amat,AZ_precondition,NULL);
        break;

        /* Jacobi preconditioning. In this case, Aztec needs the      */
        /* diagonal of the matrix. This can be passed in as an MSR    */
        /* matrix. However, when using Jacobi, it is important to note*/
        /* that the MSR 'bindx' array does not need to be specified.  */
        /* Only the diagonal needs to be placed in the 'val' array.   */

      case AZ_Jacobi:
        if (!is_VBR)
        {
          Pmat = AZ_create_matrix(N_equations, AZ_NO_EXTRA_SPACE,
              AZ_MSR_MATRIX, N_equations,
              AZ_NOT_USING_AZTEC_MATVEC);
          val      = (double *) AZ_allocate(N_real * sizeof(double));
          if (val == NULL)
            AZ_perror("AZK_create_precon: Out of memory");
          for ( i = 0;i < N_real; i++)
            val[i] = 1.0/(Amat_real->val[i]*Amat_real->val[i] +
                Amat_imag->val[i]*Amat_imag->val[i]);
          Pmat->val = val;
          Pmat->bindx = NULL;
          Pmat->indx = NULL;
          Pmat->bpntr = NULL;
          Pmat->rpntr = NULL;
          Pmat->cpntr = NULL;
          (*Prec) = AZ_precond_create(Pmat,AZK_precon,NULL);
          options[AZ_precond] = AZ_user_precond;
          Prec_pass_data->AZK_precond = AZ_Jacobi;
          (*Prec)->Pmat->aux_ptr = (void *) Prec_pass_data;
        }
        else
        {
          AZ_perror("Jacobi scaling is only supported for MSR matrices");
        }
        break;

        /* Domain decomposition preconditioning. In this case, Aztec  */
        /* needs the local matrix defined within the processor. This  */
        /* can be passed in as an MSR array. Note: since we do not    */
        /* overlap the subdomains in this specific example, only the  */
        /* local columns associated with local equations need to be   */
        /* kept. That is, we drop all references to external variables*/

      case AZ_dom_decomp:

        AZ_perror("AZK_linsys_create_no_copy does not support dom_decomp");

        break;
      default:
        AZ_perror("AZK_linsys_create_no_copy does not support this option");

    }
  }
  if (Prec_pass_data) free(Prec_pass_data); Prec_pass_data = NULL;
}
Ejemplo n.º 6
0
void AZ_calc_blk_diag_LU(double *val, int *indx, int *bindx, int *rpntr,
                          int *cpntr, int *bpntr, double *d_inv, int *d_indx,
                          int *d_bindx, int *d_rpntr, int *d_bpntr,
                          int *data_org, int *ipvt)

/*******************************************************************************

  Routine to calculate the LU factors of the block-diagonal portion of sparse
  matrix in 'val' and the associated integer pointer vectors. This is used for
  scaling.

  Author:          Scott A. Hutchinson, SNL, 1421
  =======

  Return code:     void
  ============

  Parameter list:
  ===============

  val:             Array containing the nonzero entries of the matrix (see
                   Aztec User's Guide).

  indx,
  bindx,
  rpntr,
  cpntr,
  bpntr:           Arrays used for DMSR and DVBR sparse matrix storage (see
                   file Aztec User's Guide).

  d_inv:           Vector containing the LU of the diagonal blocks.

  d_indx:          The 'indx' array corresponding to the LU-block
                   diagonals.

  d_bindx:         The 'bindx' array corresponding to the LU-block
                   diagonals.

  d_rpntr:         The 'rpntr' array corresponding to the LU-block
                   diagonals.

  d_bpntr:         The 'bpntr' array corresponding to the LU-block
                   diagonals.

  data_org:        Array containing information on the distribution of the
                   matrix to this processor as well as communication parameters
                   (see Aztec User's Guide).

*******************************************************************************/

{

  /* local variables */

  register int i, j, iblk_row, jblk, icount = 0, iblk_count = 0, ival;
  int          m1, n1, itemp;
  int          m;
  int          bpoff, idoff;
  int         info;
  double      *work;
  char        *yo = "AZ_calc_blk_diag_inv: ";

  /**************************** execution begins ******************************/

  m = data_org[AZ_N_int_blk] + data_org[AZ_N_bord_blk];

  if (m == 0) return;

  /* allocate vectors for lapack routines */

  work = (double *) AZ_allocate(rpntr[m]*sizeof(double));
  if (work == NULL) AZ_perror("Not enough space for Block Jacobi\n");

  /* offset of the first block */

  bpoff = *bpntr;
  idoff = *indx;

  /* loop over block rows */

  for (iblk_row = 0; iblk_row < m; iblk_row++) {

    /* number of rows in the current row block */

    m1 = rpntr[iblk_row+1] - rpntr[iblk_row];

    /* starting index of current row block */

    ival = indx[bpntr[iblk_row] - bpoff] - idoff;

    /* loop over column block numbers, looking for the diagonal block */

    for (j = bpntr[iblk_row] - bpoff; j < bpntr[iblk_row+1] - bpoff; j++) {
      jblk = bindx[j];

      /* determine the number of columns in this block */

      n1 = cpntr[jblk+1] - cpntr[jblk];

      itemp = m1*n1;

      if (jblk == iblk_row) {   /* diagonal block */

        /* error check */

        if (n1 != m1) {
          (void) AZ_printf_err( "%sERROR: diagonal blocks are not square\n.",
                         yo);
          exit(-1);
        }
        else {

          /* fill the vectors */

          d_indx[iblk_count]  = icount;
          d_rpntr[iblk_count] = rpntr[iblk_row];
          d_bpntr[iblk_count] = iblk_row;
          d_bindx[iblk_count] = iblk_row;

          for (i = 0; i < itemp; i++) d_inv[icount++] = val[ival + i];

          /* invert the dense matrix */

          DGETRF_F77(&m1, &m1, &d_inv[d_indx[iblk_count]], &m1, &(ipvt[rpntr[iblk_row]]), &info);

          if (info < 0) {
            (void) AZ_printf_err( "%sERROR: argument %d is illegal.\n", yo,
                           -info);
            exit(-1);
          }

          else if (info > 0) {
            (void) AZ_printf_err( "%sERROR: the factorization has produced a "
                           "singular U with U[%d][%d] being exactly zero.\n",
                           yo, info, info);
            exit(-1);
          }
          iblk_count++;
        }
        break;
      }
      else
        ival += itemp;
    }
  }

  d_indx[iblk_count]  = icount;
  d_rpntr[iblk_count] = rpntr[iblk_row];
  d_bpntr[iblk_count] = iblk_row;

  AZ_free((void *) work);

} /* AZ_calc_blk_diag_inv */
Ejemplo n.º 7
0
void AZ_factor_subdomain(struct context *context, int N, int N_nz,
	int *nz_used)
{
/****************************************************************************
  Given an overlapped subdomain matrix, factor it according to the
  chosen algorithm and store the result back in subdomain. Additionally, 
  store the number of nonzeros used in the factorization in nz_used.

  Notes:
    1) Matrix comes in as an MSR matrix.
    2) context contains several fields which need to be appropriately
       set. These fields are specific to the individual solvers.
    3) The factorization overwrites the matrix. However, different
       solvers will store the factorization in different formats.

  Author:          Ray Tuminaro, SNL, 9222 (3/98)

  Return code:     void
  ============

  Parameter list:
  ===============

  context        On input, context contains the matrix to be 
                   factored in context.A_overlapped (MSR format), 
                   On output, context contains the factored matrix
                   which is stored in a format specific to the solver and 
                   any additional parameters required by the backsolver.

  N                On input, the size of the linear system to be solved.

  N_nz             On input, the number of nonzero values in the matrix
                   to be factored.

  nz_used          On output, the number of nonzero values in the matrix
                   representing the factorization.

*******************************************************************************/

#ifdef HAVE_AZLU
	int ifail, N_nz_matrix, *rnr;
        double *fake_rhs, *aflag;
#endif
        int i, j, *bindx, *bpntr, *iw;
        double *cr, *unorm, *a, *val;
        int    *ind, *jnz, *ja, ifill;
        double dtemp = (context->aztec_choices->params)[AZ_omega];
        int    N_blk_rows, name = context->A_overlapped->data_org[AZ_name];
        char   str[80];

/* Begin Aztec 2.1 mheroux mod */
#ifdef IFPACK
	void *precon, *bmat;
	double rthresh, athresh;
	int N_int_blk, N_bord_blk, graph_fill;
#endif
/* End Aztec 2.1 mheroux mod */

        bindx = context->A_overlapped->bindx;

        *nz_used = bindx[N];

        switch(context->aztec_choices->options[AZ_subdomain_solve]) {
/* Begin Aztec 2.1 mheroux mod */
        case AZ_bilu_ifp:
#ifdef IFPACK
           if (N == 0) return;

           bindx = context->A_overlapped->bindx;
           val   = context->A_overlapped->val;

           /* for bilu(k) with k > 1 , figure out the new sparsity pattern */

           AZ_sort_msr(bindx, val, N);

           /* Let IFPACK handle fillin */
	      graph_fill = (context->aztec_choices->options)[AZ_graph_fill];
           (context->aztec_choices->options)[AZ_graph_fill] = 0;
           /* recover some space so that there will */
           /* be enough room to convert back to vbr */

           i = AZ_compress_msr(&(context->A_overlapped->bindx), 
                         &(context->A_overlapped->val), context->N_nz_allocated,
                         *nz_used, name, context);
           context->N_nz = *nz_used;
           context->N_nz_allocated = *nz_used;

           AZ_msr2vbr_mem_efficient(N, &(context->A_overlapped->bindx), 
                                 &(context->A_overlapped->val), 
                                 &(context->A_overlapped->cpntr), 
                                 &(context->A_overlapped->bpntr), 
                                 &(context->A_overlapped->indx), &N_blk_rows, 
                                 (context->A_overlapped->data_org)[AZ_name],
                                 context->tag,i);

	   context->A_overlapped->matrix_type = AZ_VBR_MATRIX;
   
	   /*ifp_initialize();*/
  
	   /* Create IFPACK encapsulation of Amat */

	   context->A_overlapped->rpntr = context->A_overlapped->cpntr;
	   N_int_blk = context->A_overlapped->data_org[AZ_N_int_blk];
	   N_bord_blk = context->A_overlapped->data_org[AZ_N_bord_blk];
	   context->A_overlapped->data_org[AZ_N_int_blk] = N_blk_rows;
	   context->A_overlapped->data_org[AZ_N_bord_blk] = 0;
	   (context->aztec_choices->options)[AZ_graph_fill] = graph_fill;

	   az2ifp_blockmatrix(&bmat, context->A_overlapped); 

	   context->A_overlapped->data_org[AZ_N_int_blk] = N_int_blk;
	   context->A_overlapped->data_org[AZ_N_bord_blk] = N_bord_blk;

	   rthresh =  (context->aztec_choices->params)[AZ_rthresh];
	   athresh =  (context->aztec_choices->params)[AZ_athresh];
           ifill = (context->aztec_choices->options)[AZ_graph_fill];
	   ifp_preconditioner(&precon, bmat, IFP_BILUK, (double) ifill, 0.0,
			    IFP_SVD, rthresh, athresh);
        if ((context->aztec_choices->options)[AZ_output]>0) {
              ifp_biluk_stats(precon);
        }
	   context->precon = precon;
           break;

/* End Aztec 2.1 mheroux mod */

#else
        AZ_perror("IFPACK not linked.  Must compile with -DIFPACK");
#endif
        case AZ_bilu:
           if (N == 0) return;

           bindx = context->A_overlapped->bindx;
           val   = context->A_overlapped->val;

           /* for bilu(k) with k > 1 , figure out the new sparsity pattern */

           AZ_sort_msr(bindx, val, N);
           ifill = (context->aztec_choices->options)[AZ_graph_fill];
           if (ifill > 0) {
              *nz_used = AZ_fill_sparsity_pattern(context, ifill, 
                                                  bindx, val, N);

           }
           /* recover some space so that there will */
           /* be enough room to convert back to vbr */

           i = AZ_compress_msr(&(context->A_overlapped->bindx), 
                         &(context->A_overlapped->val), context->N_nz_allocated,
                         *nz_used, name, context);
           context->N_nz = *nz_used;
           context->N_nz_allocated = *nz_used;

           AZ_msr2vbr_mem_efficient(N, &(context->A_overlapped->bindx), 
                                 &(context->A_overlapped->val), 
                                 &(context->A_overlapped->cpntr), 
                                 &(context->A_overlapped->bpntr), 
                                 &(context->A_overlapped->indx), &N_blk_rows, 
                                 (context->A_overlapped->data_org)[AZ_name],
                                 context->tag,i);

	   context->A_overlapped->matrix_type = AZ_VBR_MATRIX;
   
           bindx = context->A_overlapped->bindx;
           bpntr = context->A_overlapped->bpntr;
           val   = context->A_overlapped->val;

	   sprintf(str,"ipvt %s",context->tag);
           context->ipvt  = (int *) AZ_manage_memory((N+1)*sizeof(int),
                                    AZ_ALLOC, name, str, &i);
           sprintf(str,"dblock %s",context->tag);
           context->dblock= (int *) AZ_manage_memory((N_blk_rows+1)*
                                                 sizeof(int), AZ_ALLOC, name,
                                                 str, &i);

           context->N_blk_rows = N_blk_rows;

           /* set dblock to point to the diagonal block in each block row */

           for (i = 0 ; i < N_blk_rows ; i++ ) {
              for (j = bpntr[i] ; j < bpntr[i+1] ; j++ ) {
                 if (bindx[j] == i) context->dblock[i] = j;
              }
           }

           AZ_fact_bilu(N_blk_rows, context->A_overlapped, context->dblock,
                        context->ipvt);
           break;

	case AZ_ilut:
           cr = (double *) AZ_allocate((2*N+3+context->max_row)*sizeof(int)+
                                     (2*N+2+context->max_row)*sizeof(double));
           if (cr == NULL) AZ_perror("Out of space in ilut.\n");
           unorm = &(cr[N+2]);
           a     = &(unorm[N]);
           ind   = (int *) &(a[context->max_row]);
           jnz   = &(ind[N+3]);
           ja    = &(jnz[N]);
           sprintf(str,"iu %s",context->tag);
           context->iu    = (int *) AZ_manage_memory((N+1)*sizeof(int),
                                             AZ_ALLOC, name, str, &i);
           AZ_fact_ilut(&N, context->A_overlapped, a, ja,
                        (context->aztec_choices->params)[AZ_drop], 
                        context->extra_fact_nz_per_row, N_nz - bindx[N],
                        context->iu,cr,unorm,ind, nz_used, jnz,
                        (context->aztec_choices->params)[AZ_rthresh],
                        (context->aztec_choices->params)[AZ_athresh]);
           AZ_free(cr);
           break;
	case AZ_ilu:
           dtemp = 0.0;
	case AZ_rilu:
           if (N == 0) return;
           sprintf(str,"iu %s",context->tag);
           bindx = context->A_overlapped->bindx;
           val   = context->A_overlapped->val;

           /* for ilu(k) with k > 1 , figure out the new sparsity pattern */

           AZ_sort_msr(bindx, val, N);
           ifill = (context->aztec_choices->options)[AZ_graph_fill];
           if (ifill > 0) {
              *nz_used = AZ_fill_sparsity_pattern(context, ifill, 
                                                  bindx, val, N);
           }
           context->iu= (int *) AZ_manage_memory((N+1)*sizeof(int),AZ_ALLOC,
                                                    name, str, &i);
           iw = (int *) AZ_allocate((N+1)*sizeof(int));
           if (iw == NULL) AZ_perror("Out of space in ilu.\n");
           AZ_fact_rilu(N, nz_used, context->iu, iw, context->A_overlapped, 
                        dtemp,
                        (context->aztec_choices->params)[AZ_rthresh],
                        (context->aztec_choices->params)[AZ_athresh]);
           AZ_free(iw);
           break;
	case AZ_icc:
           sprintf(str,"iu %s",context->tag);
           bindx = context->A_overlapped->bindx;
           val   = context->A_overlapped->val;

           /* for ilu(k) with k > 1 , figure out the new sparsity pattern */

           AZ_sort_msr(bindx, val, N);
           ifill = (context->aztec_choices->options)[AZ_graph_fill];
           if (ifill > 0)
              *nz_used = AZ_fill_sparsity_pattern(context, ifill, 
                                                  bindx, val, N);

           AZ_fact_chol(context->A_overlapped->bindx,
                        context->A_overlapped->val,N,
                        (context->aztec_choices->params)[AZ_rthresh],
                        (context->aztec_choices->params)[AZ_athresh]);
           break;
	case AZ_lu:
#ifdef HAVE_AZLU
           if (N == 0) return;
           aflag = (double *) AZ_allocate(8*sizeof(double));
           rnr   = (int *) AZ_allocate(N_nz*sizeof(int));
           if (rnr == NULL) AZ_perror("Out of space in lu.\n");

           sprintf(str,"iflag %s",context->tag);
           context->iflag = (int *) AZ_manage_memory(10*sizeof(int), AZ_ALLOC,
                                                       name, str ,&i);
           sprintf(str,"ha %s",context->tag);
           context->ha = (int *) AZ_manage_memory(11*(N+1)*sizeof(int),
                                             AZ_ALLOC, name, str, &i);
           sprintf(str,"pivot %s",context->tag);
           context->pivot = (double *) AZ_manage_memory((N+1)*sizeof(double),
                                             AZ_ALLOC, name, str,&i);

           aflag[0] = 16.0;    aflag[2] = 1.0e8;   aflag[3] = 1.0e-12;   
           aflag[1] = (context->aztec_choices->params)[AZ_drop];

           /* set up flags for the sparse factorization solver */

           context->iflag[0] = 1;         context->iflag[1] = 2;
           context->iflag[2] = 1;         context->iflag[3] = 0;
           context->iflag[4] = 2;    
           /*    Note: if matrix is pos def, iflag[2] = 2 is cheaper */

           N_nz_matrix = bindx[N] - 1;

           AZ_msr2lu(N, context->A_overlapped, rnr);

           /* Mark bindx so we can see what was not used later */

           for (i =  N_nz_matrix ; i < N_nz ; i++) bindx[i] = -7;

           /* factor the matrix */ 

           if (N == 1) {
             context->A_overlapped->val[0]=1./context->A_overlapped->val[0];
           }
           else {
              context->N_nz_factors = N_nz;
              fake_rhs = (double *) AZ_allocate(N*sizeof(double));
              if (fake_rhs == NULL) {
                 AZ_printf_out("Not enough memory inside subdomain_solve\n");
              }
              for (i = 0 ; i < N ; i++ ) fake_rhs[i] = 0.0;
              AZ_fact_lu(fake_rhs, context->A_overlapped,aflag, 
                         context->pivot, rnr, context->ha, 
			 context->iflag, &N_nz_matrix,
                         &ifail, &(context->N_nz_factors),
                         &N, &N);

              (context->iflag)[4] = 3; 
              AZ_free(fake_rhs);

              /* find out what was not used by checking what was not touched */

              *nz_used = N_nz;
              for (i = N_nz_matrix; i < N_nz ; i++ ) {
                 if (bindx[i] != -7) *nz_used = i;
              }
              (*nz_used)++;
              context->N_nz_factors = *nz_used;
           }
           AZ_free(rnr);
           AZ_free(aflag);
#else
	   AZ_printf_err("AZ_lu unavailable: configure with --enable-aztecoo-azlu to make available\n");
	   exit(1);
#endif
           break;
        default:
           if (context->aztec_choices->options[AZ_subdomain_solve]
                  >= AZ_SOLVER_PARAMS) {
              AZ_printf_err("Unknown subdomain solver(%d)\n",
                   context->aztec_choices->options[AZ_subdomain_solve]);
              exit(1);
           }
        }      
}
Ejemplo n.º 8
0
void AZ_hold_space(struct context *context, int N) 
{
/****************************************************************************
  This routine is used in conjunction with AZ_free_space_holder().
  Essentially, this routine allocates memory while AZ_free_space_holder()
  deallocates.  The whole point of these two routines is to
  allocated all the space needed during the factorization process
  EXCLUDING all arrays whose size is related to the number of 
  nonzeros. Once this is done, we can determine how much space 
  there is left for the large arrays required for the factorization
  and split the remaining space amoung these large arrays. In this
  way LU routines where it is difficult to know the space requirements
  ahead of time can try to use as large an array as possible.

  Note: after factorization 'realloc' is used to reduce the array sizes.

  Author:          Ray Tuminaro, SNL, 9222 (3/98)

  Return code:     void
  ============

  Parameter list:
  ===============

  context          On input, context->aztec_choices->
	           options[AZ_subdomain_solve]
                   indicates the solver being used.
                   On output, context->space_holder points to a
                   block of memory which can hold all the 'nonlarge' arrays
                   required by this solver.
     
  N                On input, the size of the matrix to be allocated.

*******************************************************************************/


   switch(context->aztec_choices->options[AZ_subdomain_solve]) {
   case AZ_ilut:
      context->space_holder = (int *) AZ_allocate((2*N+2+context->max_row)*
                                                   sizeof(double) + sizeof(int)*
                                                   (3*N+8+context->max_row));
      if (context->space_holder  == NULL) AZ_perror("No space in ilut.\n");

      /*   Space for cr (N+2 doubles), unorm (N doubles), a (max_row doubles),*/
      /*   ind (N+3 ints), jnz (N ints), iu (N+1 ints), ja(max_row ints),     */
      /*   + 4 ints for manage memory header                                  */
      break;
#ifdef HAVE_AZLU
   case AZ_lu:
        context->space_holder = (int *) AZ_allocate((2*N+9)* sizeof(double) + 
                                           (11*(N+1)+22)*sizeof(int) );

      /*   Space for aflag (8 doubles), ifail (10 ints), ha (11*(N+1) ints), */
      /*   pivot (N+1 doubles), fake_rhs (N doubles)+12 ints for manage      */
      /*   memory header                                                     */
      /*   Note: Arrays of size N_nz (e.g. rnr) are not allocated by this    */
      /*   routine. Instead the subdomain field N_int_arrays is set.         */

        if (context->space_holder == NULL) AZ_perror("Out of space in lu.\n");
#else
	AZ_printf_err("AZ_lu unavailable: configure with --enable-aztecoo-azlu to make available\n");
	exit(1);
#endif
      break;
   case AZ_bilu:
/* Begin Aztec 2.1 mheroux mod */
   case AZ_bilu_ifp:
/* End Aztec 2.1 mheroux mod */
        context->space_holder= (int *) AZ_allocate((N+1)*sizeof(double));
        if (context->space_holder == NULL) AZ_perror("No space for bilu.\n");

        /* BILU is a little funny in that the maximum amount of memory */
        /* required does not occur during the factorization. Instead   */
        /* it occurs when converting MSR to VBR. At this point, an     */
        /* additional array of length N is needed.                     */
      break;

   case AZ_icc:
       context->space_holder= (int *) AZ_allocate((2*(N+1))*sizeof(int)+
                                                     (N+1)*sizeof(double));
       if (context->space_holder == NULL) AZ_perror("Out of space in ilu.\n");
       break;
   case AZ_ilu:
   case AZ_rilu:
       context->space_holder= (int *) AZ_allocate((2*(N+1)+4)*sizeof(int));

       /*   Space for iu (N+1 ints), iw (N+1 ints) + 4 ints for manage_memory */

       if (context->space_holder == NULL) AZ_perror("Out of space in ilu.\n");
       break;
    default:
      ;
   }
}
Ejemplo n.º 9
0
double AZK_residual_norm_no_copy(double *xr, double *xi, double *br, double *bi, 
				int *options, double *params,
				int *proc_config,
				AZ_MATRIX *Amat_real, AZ_MATRIX *Amat_imag)

/*******************************************************************************

  Author:          Mike Heroux, SNL, 9222
  =======

  Return code:     double
  ============

  Parameter list:
  ===============

  xr,xi:           On input, contains the initial guess, real part in xr and
                   imaginary part in xi.

  br,bi:           Right hand side of linear system.

  options:         Determines specific solution method and other parameters.

  params:          Drop tolerance and convergence tolerance info.

  proc_config:     Machine configuration.  proc_config[AZ_node] is the node
                   number.  proc_config[AZ_N_procs] is the number of processors.

 Amat_real,
 Amat_imag:        The real and imaginary parts of the complex operator, each
                   stored separately as AZ_MATRIX structures.

  Overview
  ========

  AZK_residual_norm_no_copy computes the two norm of the residual ||r|| where
  r = b - A*x.  Specifically, writing in terms of real and imaginary parts, 
  we have

  (rr + i*ri) = (br + i*bi) - (Ar + i*Ai)*(xr + i*xi).

  The two-norm of the complex vector r is identical to the two-norm of the
  twice-length real vector formed by concatenating rr = real(r) and 
  ri = imag(r).
  


*******************************************************************************/


{

  AZ_MATRIX  *Amat;   /* Structure representing matrix to be solved.          */
  double *x, *b;      /* Solution  and right-hand side to linear system.      */
  int N_equations, i;
  double *y_tmp, result;

  /* Transform complex system into komplex system */
  
  AZK_create_linsys_no_copy (xr,  xi,  br,  bi, options,  params,  
			    proc_config, Amat_real, Amat_imag, &x, &b, &Amat);
  
  /* Allocate temp vector y */
  
  N_equations = Amat->data_org[AZ_N_internal] + Amat->data_org[AZ_N_border];
  
  y_tmp = (double *) AZ_allocate(N_equations*sizeof(double));
  if (y_tmp == NULL) 
  AZ_perror("AZK_residual_norm_no_copy: Out of memory.");
  
  /* Compute y = A*x. */
  Amat->matvec(x, y_tmp, Amat, proc_config);

  /* Compute r = b - A*x (put in y_tmp) */
  /*daxpy_(&N_equations, &neg_one, b, &ione, y_tmp, &ione);*/

	for (i=0; i<N_equations; i++) y_tmp[i] = y_tmp[i] - b[i];

  /* Use Aztec function to compute norm */

  result = AZ_gvector_norm(N_equations, 2, y_tmp, proc_config);

  /* Free memory space */

  AZK_destroy_linsys (options,  params, proc_config, &x, &b, &Amat);
 
  AZ_free((void *) y_tmp);

  result = sqrt(result);
  return(result);
/* AZK_residual_norm */
}
Ejemplo n.º 10
0
double AZK_residual_norm(double *xk, double *bk, 
			 int *options, double *params,
			 int *proc_config,
			 AZ_MATRIX *Amat_komplex)

/*******************************************************************************

  Author:          Mike Heroux, SNL, 9222
  =======

  Return code:     double
  ============

  Parameter list:
  ===============

  xk:              On input, contains the initial guess.

  bk:              Right hand side of linear system.

  options:         Determines specific solution method and other parameters.

  params:          Drop tolerance and convergence tolerance info.

  proc_config:     Machine configuration.  proc_config[AZ_node] is the node
                   number.  proc_config[AZ_N_procs] is the number of processors.

 Amat_komplex:     The komplex operator, stored as an AZ_MATRIX structure.


  Overview
  ========

  AZK_residual_norm computes the two norm of the residual ||r|| where
  r = b - A*x.  Specifically, writing in terms of real and imaginary parts, 
  we have

  (rr + i*ri) = (br + i*bi) - (Ar + i*Ai)*(xr + i*xi).

  The two-norm of the complex vector r is identical to the two-norm of the
  twice-length real vector formed by concatenating rr = real(r) and 
  ri = imag(r).
  


*******************************************************************************/


{
  int N_equations, i;
  double *y_tmp, result;

  /* Allocate temp vector y */
  
  N_equations = Amat_komplex->data_org[AZ_N_internal] + 
                Amat_komplex->data_org[AZ_N_border];
  
  y_tmp = (double *) AZ_allocate(N_equations*sizeof(double));
  if (y_tmp == NULL) 
  AZ_perror("AZK_residual_norm: Out of memory.");
  
  /* Compute y = A*x. */
  Amat_komplex->matvec(xk, y_tmp, Amat_komplex, proc_config);

  /* Compute r = b - A*x (put in y_tmp) */
  /*daxpy_(&N_equations, &neg_one, bk, &ione, y_tmp, &ione);*/
	for (i=0; i<N_equations; i++) y_tmp[i] = y_tmp[i] - bk[i];

  /* Use Aztec function to compute norm */

  result = AZ_gvector_norm(N_equations, 2, y_tmp, proc_config);

  /* Free memory space */

  AZ_free((void *) y_tmp);

  result = sqrt(result);
  return(result);
/* AZK_residual_norm */
}