void AZK_destroy_linsys( int *options, double *params, int *proc_config, double **x, double **b, AZ_MATRIX **Amat_komplex) { AZ_KOMPLEX *linsys_pass_data; int *komplex_to_real, *komplex_to_imag; linsys_pass_data = (AZ_KOMPLEX *) (*Amat_komplex)->aux_ptr; if (linsys_pass_data->Form_of_Equations != AZK_Komplex_No_Copy) { /* Destroy RHS, initial guess and matrix */ AZK_destroy_vector( options, params, proc_config, (*Amat_komplex), x); AZK_destroy_vector( options, params, proc_config, (*Amat_komplex), b); AZK_destroy_matrix( options, params, proc_config, Amat_komplex); } else { komplex_to_real = linsys_pass_data->komplex_to_real; komplex_to_imag = linsys_pass_data->komplex_to_imag; /* Free allocated memory */ AZ_free((void *) komplex_to_real); AZ_free((void *) komplex_to_imag); AZ_free ((void **) x); AZ_free ((void **) b); AZ_free((void *) linsys_pass_data); /* Free data_org if Aztec doesn't do it */ if (!(*Amat_komplex)->must_free_data_org) AZ_free((void *) (*Amat_komplex)->data_org); AZ_matrix_destroy (Amat_komplex); } }
int main(int argc, char *argv[]) { int proc_config[AZ_PROC_SIZE];/* Processor information. */ int options[AZ_OPTIONS_SIZE]; /* Array used to select solver options. */ double params[AZ_PARAMS_SIZE]; /* User selected solver paramters. */ double status[AZ_STATUS_SIZE]; /* Information returned from AZ_solve(). */ int *bindx_real; /* index and values arrays for MSR matrices */ double *val_real, *val_imag; int * update; /* List of global eqs owned by the processor */ double *x_real, *b_real; /* initial guess/solution, RHS */ double *x_imag, *b_imag; unsigned int N_local; /* Number of equations on this node */ double residual; /* Used for computing residual */ double *xx_real, *xx_imag, *xx; /* Known exact solution */ int myPID, nprocs; AZ_MATRIX *Amat_real; /* Real matrix structure */ AZ_MATRIX *Amat; /* Komplex matrix to be solved. */ AZ_PRECOND *Prec; /* Komplex preconditioner */ double *x, *b; /* Komplex Initial guess and RHS */ int i; /******************************/ /* First executable statement */ /******************************/ #ifdef AZTEC_MPI MPI_Init(&argc,&argv); #endif /* Get number of processors and the name of this processor */ #ifdef AZTEC_MPI AZ_set_proc_config(proc_config,MPI_COMM_WORLD); #else AZ_set_proc_config(proc_config,0); #endif nprocs = proc_config[AZ_N_procs]; myPID = proc_config[AZ_node]; printf("proc %d of %d is alive\n",myPID, nprocs); /* Define two real diagonal matrices. Will use as real and imaginary parts */ /* Get the number of local equations from the command line */ if (argc!=2) { if (myPID==0) printf("Usage: %s number_of_local_equations\n",argv[0]); exit(1); } N_local = atoi(argv[1]); const unsigned int N_local_max = 1000000; if (N_local > N_local_max) { if (myPID==0) printf("No more than %d local equation allowed\n", N_local_max); exit(1); } /* Need N_local+1 elements for val/bindx arrays */ val_real = malloc((N_local+1)*sizeof(double)); val_imag = malloc((N_local+1)*sizeof(double)); /* bindx_imag is not needed since real/imag have same pattern */ bindx_real = malloc((N_local+1)*sizeof(int)); update = malloc((N_local+1)*sizeof(int)); /* Malloc equation update list */ b_real = malloc((N_local+1)*sizeof(double)); /* Malloc x and b arrays */ b_imag = malloc((N_local+1)*sizeof(double)); x_real = malloc((N_local+1)*sizeof(double)); x_imag = malloc((N_local+1)*sizeof(double)); xx_real = malloc((N_local+1)*sizeof(double)); xx_imag = malloc((N_local+1)*sizeof(double)); for (i=0; i<N_local; i++) { val_real[i] = 10 + i/(N_local/10); /* Some very fake diagonals */ val_imag[i] = 10 - i/(N_local/10); /* Should take exactly 20 GMRES steps */ x_real[i] = 0.0; /* Zero initial guess */ x_imag[i] = 0.0; xx_real[i] = 1.0; /* Let exact solution = 1 */ xx_imag[i] = 0.0; /* Generate RHS to match exact solution */ b_real[i] = val_real[i]*xx_real[i] - val_imag[i]*xx_imag[i]; b_imag[i] = val_imag[i]*xx_real[i] + val_real[i]*xx_imag[i]; /* All bindx[i] have same value since no off-diag terms */ bindx_real[i] = N_local + 1; /* each processor owns equations myPID*N_local through myPID*N_local + N_local - 1 */ update[i] = myPID*N_local + i; } bindx_real[N_local] = N_local+1; /* Need this last index */ /* Register Aztec Matrix for Real Part, only imaginary values are needed*/ Amat_real = AZ_matrix_create(N_local); AZ_set_MSR(Amat_real, bindx_real, val_real, NULL, N_local, update, AZ_GLOBAL); /* initialize AZTEC options */ AZ_defaults(options, params); options[AZ_solver] = AZ_gmres; /* Use CG with no preconditioning */ options[AZ_precond] = AZ_none; options[AZ_kspace] = 21; options[AZ_max_iter] = 21; params[AZ_tol] = 1.e-14; /**************************************************************/ /* Construct linear system. Form depends on input parameters */ /**************************************************************/ /**************************************************************/ /* Method 1: Construct A, x, and b in one call. */ /* Useful if using A,x,b only one time. Equivalent to Method 2*/ /**************************************************************/ AZK_create_linsys_ri2k (x_real, x_imag, b_real, b_imag, options, params, proc_config, Amat_real, val_imag, &x, &b, &Amat); /**************************************************************/ /* Method 2: Construct A, x, and b in separate calls. */ /* Useful for having more control over the construction. */ /* Note that the matrix must be constructed first. */ /**************************************************************/ /* Uncomment these three calls and comment out the above call AZK_create_matrix_ri2k (options, params, proc_config, Amat_real, val_imag, &Amat); AZK_create_vector_ri2k(options, params, proc_config, Amat, x_real, x_imag, &x); AZK_create_vector_ri2k(options, params, proc_config, Amat, b_real, b_imag, &b); */ /**************************************************************/ /* Build exact solution vector. */ /* Check residual of init guess and exact solution */ /**************************************************************/ AZK_create_vector_ri2k(options, params, proc_config, Amat, xx_real, xx_imag, &xx); residual = AZK_residual_norm(x, b, options, params, proc_config, Amat); if (proc_config[AZ_node]==0) printf("\n\n\nNorm of residual using initial guess = %12.4g\n",residual); residual = AZK_residual_norm(xx, b, options, params, proc_config, Amat); AZK_destroy_vector(options, params, proc_config, Amat, &xx); if (proc_config[AZ_node]==0) printf("\n\n\nNorm of residual using exact solution = %12.4g\n",residual); /**************************************************************/ /* Create preconditioner */ /**************************************************************/ AZK_create_precon(options, params, proc_config, x, b, Amat, &Prec); /**************************************************************/ /* Solve linear system using Aztec. */ /**************************************************************/ AZ_iterate(x, b, options, params, status, proc_config, Amat, Prec, NULL); /**************************************************************/ /* Extract solution. */ /**************************************************************/ AZK_extract_solution_k2ri(options, params, proc_config, Amat, Prec, x, x_real, x_imag); /**************************************************************/ /* Destroy Preconditioner. */ /**************************************************************/ AZK_destroy_precon (options, params, proc_config, Amat, &Prec); /**************************************************************/ /* Destroy linear system. */ /**************************************************************/ AZK_destroy_linsys (options, params, proc_config, &x, &b, &Amat); if (proc_config[AZ_node]==0) { printf("True residual norm squared = %22.16g\n",status[AZ_r]); printf("True scaled res norm squared = %22.16g\n",status[AZ_scaled_r]); printf("Computed res norm squared = %22.16g\n",status[AZ_rec_r]); } /* Print comparison between known exact and computed solution */ {double sum = 0.0; for (i=0; i<N_local; i++) sum += fabs(x_real[i]-xx_real[i]); for (i=0; i<N_local; i++) sum += fabs(x_imag[i]-xx_imag[i]); printf("Processor %d: Difference between exact and computed solution = %12.4g\n", proc_config[AZ_node],sum); } /* Free memory allocated */ free((void *) val_real ); free((void *) bindx_real ); free((void *) val_imag ); free((void *) update ); free((void *) b_real ); free((void *) b_imag ); free((void *) x_real ); free((void *) x_imag ); free((void *) xx_real ); free((void *) xx_imag ); AZ_matrix_destroy(&Amat_real); #ifdef AZTEC_MPI MPI_Finalize(); #endif return 0 ; }