Exemplo n.º 1
0
void AZ_compute_global_scalars(AZ_MATRIX *Amat, 
                               double x[], double b[], double r[], double w[],
                               double *r_norm, double *scaled_r_norm,
                               int options[], int data_org[], int proc_config[],
                               int *r_avail, double v1[], double v2[],
                               double *value, 
			       struct AZ_CONVERGE_STRUCT *conv_info)

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

  Routine to check against 'eps' for convergence. The type of norm use is
  determined by the variable 'conv_flag' as follows:

                0: ||r||2 / ||r0||2  < eps
                1: ||r||2 / ||b||2   < eps
                2: ||r||2 / ||A||inf < eps
                3: ||r||inf / (||A||inf * ||x||1 + ||b||inf)
                4: ||r/w||2

                where ||*||2 is the Euclidean norm, ||*||inf is the
                infinity norm and ||*|| is the sum norm.

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

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

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

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

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

  x:               The current solution vector.

  b:               Right hand side of linear system.

  r:               The current residual vector.

  w:               Weighting vector for convergence norm #4.

  r_norm:          Norm of residual.

  scaled_r_norm:   Norm of residual scaled by norm of the rhs.

  options:         Determines specific solution method and other parameters.

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

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

  r_avail:         In general, this variable indicates whether or not the
                   residual is available or needs to be made available.
                   In particular,
                      first_time == TRUE     : real residual is available. The
                                               norm of this residual will be
                                               computed and stored in r_norm.
                      first_time == FALSE &&
                      r_avail    == TRUE     : real residual is available. The
                                               norm of this residual will be
                                               computed and stored in r_norm.
                      first_time == FALSE &&
                      r_avail    == FALSE    : real residual is not available.
                                               The norm of the residual is not
                                               computed. Instead, it is assumed
                                               that r_norm is an estimate of the
                                               residual norm.
                   All of this is done for gmres() and tfqmr() where we often
                   have estimates of the residual 2-norm without actually having
                   computed the residual.

                   IMPORTANT: if a convergence test requires a residual norm
                   other than the 2-norm, it is important that
                   AZ_compute_global_scalars() sets r_avail to TRUE. This tells
                   the iterative method (in particular gmres and tfqmr) that the
                   real residual must be computed (at additional cost)
                   and passed in to AZ_compute_global_scalars().

  v1,v2,value:     If v1 != NULL, *value = <v1,v2> where <.,.> is the standard
                   inner product, v1 and v2 are double precision vectors of
                   length data_org[AZ_N_internal] + data_org[AZ_N_border].

                   This is used so that 1 inner product can be grouped together
                   with the inner products required for convergence (to save
                   some messages).

  first_time:      Flag set AZ_TRUE if this is the first time this routine has
                   been called.  Set AZ_FALSE otherwise. See comments for
                   r_avail above for more information.

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

{

  /* local variables */

  register int  i;
  static double *temp, *tr;
  static int    total_N;
  int           N, j;
  double        dots[5], tmp[5], dmax, dtemp;
  int           count = 0, one = 1;

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

  N = data_org[AZ_N_internal] + data_org[AZ_N_border];
  tr = r;

  if (options[AZ_ignore_scaling]) {
     if ( (conv_info->scaling->action == AZ_left_scaling) || 
          (conv_info->scaling->action == AZ_left_and_right_scaling) ) {
        if (!(*r_avail) && (conv_info->not_initialized==AZ_FALSE)) {
           printf("AZ_compute_global_scalars: Error residual is needed to \
		   ignore scaling in convergence tests\n");
           exit(1);
        }
        *r_avail = AZ_TRUE;
        tr = AZ_manage_memory(N*sizeof(double),AZ_ALLOC,AZ_SYS, "trinconv",&j);
        for (i = 0; i < N; i++) tr[i] = r[i];
        AZ_scale_f(AZ_INVSCALE_RHS, Amat, options, tr, x, proc_config, 
                   conv_info->scaling);
     }
  }
Exemplo n.º 2
0
int test_AZ_iterate_then_AZ_scale_f(Epetra_Comm& Comm, bool verbose)
{
  (void)Comm;
  if (verbose) {
    cout << "testing AZ_iterate/AZ_scale_f with 'old' Aztec"<<endl;
  }

  int* proc_config = new int[AZ_PROC_SIZE];

#ifdef EPETRA_MPI
  AZ_set_proc_config(proc_config, MPI_COMM_WORLD);
  AZ_set_comm(proc_config, MPI_COMM_WORLD);
#else
  AZ_set_proc_config(proc_config, 0);
#endif

  int *external, *update_index, *external_index;

  int i, N = 5;
  AZ_MATRIX* Amat = NULL;
  int err = create_and_transform_simple_matrix(AZ_MSR_MATRIX, N, 3.0,
                                               proc_config, Amat,
                                                 external, update_index,
                                                 external_index);
  if (err != 0) {
    return(err);
  }
 
  int* options = new int[AZ_OPTIONS_SIZE];
  double* params = new double[AZ_PARAMS_SIZE];
  double* status = new double[AZ_STATUS_SIZE];
  AZ_defaults(options, params);
  options[AZ_scaling] = AZ_sym_diag;
  if (verbose) {
    options[AZ_output] = AZ_warnings;
  }
  else {
    options[AZ_output] = 0;
  }
  
  int N_update = N+Amat->data_org[AZ_N_border];
  double* x = new double[N_update];
  double* b = new double[N_update];

  for(i=0; i<N_update; ++i) {
    x[i] = 0.0;
    b[i] = 1.0;
  }

  AZ_PRECOND* Pmat = AZ_precond_create(Amat, AZ_precondition, NULL);
  AZ_SCALING* Scal = AZ_scaling_create();

  options[AZ_keep_info] = 1;

  AZ_iterate(x, b, options, params, status, proc_config,
             Amat, Pmat, Scal);

  //now set options[AZ_pre_calc] = AZ_reuse and try to call AZ_scale_f.
  options[AZ_pre_calc] = AZ_reuse;

  AZ_scale_f(AZ_SCALE_MAT_RHS_SOL, Amat, options, b, x, proc_config, Scal);

  AZ_scaling_destroy(&Scal);
  AZ_precond_destroy(&Pmat);
  destroy_matrix(Amat);

  delete [] x;
  delete [] b;

  delete [] options;
  delete [] params;
  delete [] status;
  delete [] proc_config;
  free(update_index);
  free(external);
  free(external_index);

  return(0);
}