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; }
int main(int argc, char *argv[]) { char global[]="global"; char local[]="local"; 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. */ int *data_org; /* Array to specify data layout */ double status[AZ_STATUS_SIZE]; /* Information returned from AZ_solve(). */ int *update; /* vector elements updated on this node. */ int *external; /* vector elements needed by this node. */ int *update_index; /* ordering of update[] and external[] */ int *extern_index; /* locally on this processor. */ int *indx; /* MSR format of real and imag parts */ int *bindx; int *bpntr; int *rpntr; int *cpntr; AZ_MATRIX *Amat; AZ_PRECOND *Prec; double *val; double *x, *b, *xexact, *xsolve; int n_nonzeros, n_blk_nonzeros; int N_update; /* # of block unknowns updated on this node */ int N_local; /* Number scalar equations on this node */ int N_global, N_blk_global; /* Total number of equations */ int N_external, N_blk_eqns; double *val_msr; int *bindx_msr; double norm, d ; int matrix_type; int has_global_indices, option; int i, j, m, mp ; int ione = 1; #ifdef TEST_SINGULAR double * xnull; /* will contain difference of given exact solution and computed solution*/ double * Axnull; /* Product of A time xnull */ double norm_Axnull; #endif #ifdef AZTEC_MPI double MPI_Wtime(void) ; #endif double time ; #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 printf("proc %d of %d is alive\n", proc_config[AZ_node],proc_config[AZ_N_procs]) ; #ifdef AZTEC_MPI MPI_Barrier(MPI_COMM_WORLD) ; #endif #ifdef VBRMATRIX if(argc != 3) perror("error: enter name of data and partition file on command line") ; #else if(argc != 2) perror("error: enter name of data file on command line") ; #endif /* Set exact solution to NULL */ xexact = NULL; /* Read matrix file and distribute among processors. Returns with this processor's set of rows */ #ifdef VBRMATRIX read_hb(argv[1], proc_config, &N_global, &n_nonzeros, &val_msr, &bindx_msr, &x, &b, &xexact); create_vbr(argv[2], proc_config, &N_global, &N_blk_global, &n_nonzeros, &n_blk_nonzeros, &N_update, &update, bindx_msr, val_msr, &val, &indx, &rpntr, &cpntr, &bpntr, &bindx); if(proc_config[AZ_node] == 0) { free ((void *) val_msr); free ((void *) bindx_msr); free ((void *) cpntr); } matrix_type = AZ_VBR_MATRIX; #ifdef AZTEC_MPI MPI_Barrier(MPI_COMM_WORLD) ; #endif distrib_vbr_matrix( proc_config, N_global, N_blk_global, &n_nonzeros, &n_blk_nonzeros, &N_update, &update, &val, &indx, &rpntr, &cpntr, &bpntr, &bindx, &x, &b, &xexact); #else read_hb(argv[1], proc_config, &N_global, &n_nonzeros, &val, &bindx, &x, &b, &xexact); #ifdef AZTEC_MPI MPI_Barrier(MPI_COMM_WORLD) ; #endif distrib_msr_matrix(proc_config, N_global, &n_nonzeros, &N_update, &update, &val, &bindx, &x, &b, &xexact); #ifdef DEBUG for (i = 0; i<N_update; i++) if (val[i] == 0.0 ) printf("Zero diagonal at row %d\n",i); #endif matrix_type = AZ_MSR_MATRIX; #endif /* convert matrix to a local distributed matrix */ cpntr = NULL; AZ_transform(proc_config, &external, bindx, val, update, &update_index, &extern_index, &data_org, N_update, indx, bpntr, rpntr, &cpntr, matrix_type); printf("Processor %d: Completed AZ_transform\n",proc_config[AZ_node]) ; has_global_indices = 0; option = AZ_LOCAL; #ifdef VBRMATRIX N_local = rpntr[N_update]; #else N_local = N_update; #endif Amat = AZ_matrix_create(N_local); #ifdef VBRMATRIX AZ_set_VBR(Amat, rpntr, cpntr, bpntr, indx, bindx, val, data_org, N_update, update, option); #else AZ_set_MSR(Amat, bindx, val, data_org, N_update, update, option); #endif printf("proc %d Completed AZ_create_matrix\n",proc_config[AZ_node]) ; #ifdef AZTEC_MPI MPI_Barrier(MPI_COMM_WORLD) ; #endif /* initialize AZTEC options */ AZ_defaults(options, params); options[AZ_solver] = AZ_gmres; options[AZ_precond] = AZ_sym_GS; options[AZ_poly_ord] = 1; options[AZ_graph_fill] = 1; params[AZ_rthresh] = 0.0E-7; params[AZ_athresh] = 0.0E-7; options[AZ_overlap] = 1; /* params[AZ_ilut_fill] = 2.0; params[AZ_drop] = 0.01; options[AZ_overlap] = 0; options[AZ_reorder] = 0; params[AZ_rthresh] = 1.0E-1; params[AZ_athresh] = 1.0E-1; options[AZ_precond] = AZ_dom_decomp ; options[AZ_subdomain_solve] = AZ_bilu_ifp; options[AZ_reorder] = 0; options[AZ_graph_fill] = 0; params[AZ_rthresh] = 1.0E-7; params[AZ_athresh] = 1.0E-7; options[AZ_poly_ord] = 1; options[AZ_precond] = AZ_Jacobi; params[AZ_omega] = 1.0; options[AZ_precond] = AZ_none ; options[AZ_poly_ord] = 1; options[AZ_precond] = AZ_Jacobi ; options[AZ_scaling] = AZ_sym_row_sum ; options[AZ_scaling] = AZ_sym_diag; options[AZ_conv] = AZ_noscaled; options[AZ_scaling] = AZ_Jacobi ; options[AZ_precond] = AZ_dom_decomp ; options[AZ_subdomain_solve] = AZ_icc ; options[AZ_subdomain_solve] = AZ_ilut ; params[AZ_omega] = 1.2; params[AZ_ilut_fill] = 2.0; params[AZ_drop] = 0.01; options[AZ_reorder] = 0; options[AZ_overlap] = 0; options[AZ_type_overlap] = AZ_symmetric; options[AZ_precond] = AZ_dom_decomp ; options[AZ_subdomain_solve] = AZ_bilu ; options[AZ_graph_fill] = 0; options[AZ_overlap] = 0; options[AZ_precond] = AZ_dom_decomp ; options[AZ_subdomain_solve] = AZ_bilu_ifp ; options[AZ_graph_fill] = 0; options[AZ_overlap] = 0; params[AZ_rthresh] = 1.0E-3; params[AZ_athresh] = 1.0E-3; options[AZ_poly_ord] = 1; options[AZ_precond] = AZ_Jacobi ; */ options[AZ_kspace] = 600 ; options[AZ_max_iter] = 600 ; params[AZ_tol] = 1.0e-14; #ifdef BGMRES options[AZ_gmres_blocksize] = 3; options[AZ_gmres_num_rhs] = 1; #endif #ifdef DEBUG if (proc_config[AZ_N_procs]==1) write_vec("rhs.dat", N_local, b); #endif /* xsolve is a little longer vector needed to account for external entries. Make it and copy x (initial guess) into it. */ if (has_global_indices) { N_external = 0; } else { N_external = data_org[AZ_N_external]; } xsolve = (double *) calloc(N_local + N_external, sizeof(double)) ; for (i=0; i<N_local; i++) xsolve[i] = x[i]; /* Reorder rhs and xsolve to match matrix ordering from AZ_transform */ if (!has_global_indices) { AZ_reorder_vec(b, data_org, update_index, rpntr) ; AZ_reorder_vec(xsolve, data_org, update_index, rpntr) ; } #ifdef VBRMATRIX AZ_check_vbr(N_update, data_org[AZ_N_ext_blk], AZ_LOCAL, bindx, bpntr, cpntr, rpntr, proc_config); #else AZ_check_msr(bindx, N_update, N_external, AZ_LOCAL, proc_config); #endif printf("Processor %d of %d N_local = %d N_external = %d NNZ = %d\n", proc_config[AZ_node],proc_config[AZ_N_procs],N_local,N_external, n_nonzeros); /* solve the system of equations using b as the right hand side */ Prec = AZ_precond_create(Amat,AZ_precondition, NULL); AZ_iterate(xsolve, b, options, params, status, proc_config, Amat, Prec, NULL); /*AZ_ifpack_iterate(xsolve, b, options, params, status, proc_config, Amat);*/ if (proc_config[AZ_node]==0) { printf("True residual norm = %22.16g\n",status[AZ_r]); printf("True scaled res = %22.16g\n",status[AZ_scaled_r]); printf("Computed res norm = %22.16g\n",status[AZ_rec_r]); } #ifdef TEST_SINGULAR xnull = (double *) calloc(N_local + N_external, sizeof(double)) ; Axnull = (double *) calloc(N_local + N_external, sizeof(double)) ; for (i=0; i<N_local; i++) xnull[i] = xexact[i]; if (!has_global_indices) AZ_reorder_vec(xnull, data_org, update_index, rpntr); for (i=0; i<N_local; i++) xnull[i] -= xsolve[i]; /* fill with nullerence */ Amat->matvec(xnull, Axnull, Amat, proc_config); norm_Axnull = AZ_gvector_norm(N_local, 2, Axnull, proc_config); if (proc_config[AZ_node]==0) printf("Norm of A(xexact-xsolve) = %12.4g\n",norm_Axnull); free((void *) xnull); free((void *) Axnull); #endif /* Get solution back into original ordering */ if (!has_global_indices) { AZ_invorder_vec(xsolve, data_org, update_index, rpntr, x); free((void *) xsolve); } else { free((void *) x); x = xsolve; } #ifdef DEBUG if (proc_config[AZ_N_procs]==1) write_vec("solution.dat", N_local, x); #endif if (xexact != NULL) { double sum = 0.0; double largest = 0.0; for (i=0; i<N_local; i++) sum += fabs(x[i]-xexact[i]); printf("Processor %d: Difference between exact and computed solution = %12.4g\n", proc_config[AZ_node],sum); for (i=0; i<N_local; i++) largest = AZ_MAX(largest,fabs(xexact[i])); printf("Processor %d: Difference divided by max abs value of exact = %12.4g\n", proc_config[AZ_node],sum/largest); } free((void *) val); free((void *) bindx); #ifdef VBRMATRIX free((void *) rpntr); free((void *) bpntr); free((void *) indx); #endif free((void *) b); free((void *) x); if (xexact!=NULL) free((void *) xexact); AZ_free((void *) update); AZ_free((void *) update_index); AZ_free((void *) external); AZ_free((void *) extern_index); AZ_free((void *) data_org); if (cpntr!=NULL) AZ_free((void *) cpntr); AZ_precond_destroy(&Prec); AZ_matrix_destroy(&Amat); #ifdef AZTEC_MPI MPI_Finalize() ; #endif /* end main */ return 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); }
int test_AZ_iterate_AZ_pre_calc_AZ_reuse(Epetra_Comm& Comm, int* options, bool verbose) { (void)Comm; if (verbose) { cout << "testing AZ_keep_info/AZ_reuse with 'old' Aztec (solver " <<options[AZ_solver] <<", precond "<<options[AZ_precond]<<"/" << options[AZ_subdomain_solve]<<")"<<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 //We're going to create 2 Aztec matrices, one MSR and one VBR. We're going //to do 2 solves with each, reusing the preconditioner for the second solve. int *external, *update_index, *external_index; int *external2, *update_index2, *external_index2; int i, N = 5; AZ_MATRIX* Amsr = NULL; AZ_MATRIX* Avbr = NULL; int err = create_and_transform_simple_matrix(AZ_MSR_MATRIX, N, 3.0, proc_config, Amsr, external, update_index, external_index); err += create_and_transform_simple_matrix(AZ_VBR_MATRIX, N, 3.0, proc_config, Avbr, external2, update_index2, external_index2); int* az_options = new int[AZ_OPTIONS_SIZE]; double* params = new double[AZ_PARAMS_SIZE]; double* status = new double[AZ_STATUS_SIZE]; AZ_defaults(az_options, params); az_options[AZ_solver] = options[AZ_solver]; az_options[AZ_precond] = options[AZ_precond]; az_options[AZ_subdomain_solve] = options[AZ_subdomain_solve]; az_options[AZ_scaling] = AZ_sym_diag; if (verbose) { az_options[AZ_output] = AZ_warnings; } else { az_options[AZ_output] = 0; } int N_update = N+Amsr->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* Pmsr = AZ_precond_create(Amsr, AZ_precondition, NULL); AZ_SCALING* Smsr = AZ_scaling_create(); AZ_PRECOND* Pvbr = AZ_precond_create(Avbr, AZ_precondition, NULL); AZ_SCALING* Svbr = AZ_scaling_create(); // Amsr->data_org[AZ_name] = 1; // Avbr->data_org[AZ_name] = 2; //First solve with the first matrix (Amsr). if (verbose) cout << "solve Amsr, name: "<<Amsr->data_org[AZ_name]<<endl; call_AZ_iterate(Amsr, Pmsr, Smsr, x, b, az_options, params, status, proc_config, 1, AZ_calc, verbose); //First solve with the second matrix (Avbr). if (verbose) cout << "solve Avbr, name: " <<Avbr->data_org[AZ_name]<<endl; call_AZ_iterate(Avbr, Pvbr, Svbr, x, b, az_options, params, status, proc_config, 0, AZ_calc, verbose); //Second solve with Amsr, reusing preconditioner if (verbose) cout << "solve Amsr (first reuse)"<<endl; call_AZ_iterate(Amsr, Pmsr, Smsr, x, b, az_options, params, status, proc_config, 1, AZ_reuse, verbose); //Second solve with Avbr, not reusing preconditioner if (verbose) cout << "solve Avbr (keepinfo==0), name: " <<Avbr->data_org[AZ_name]<<endl; call_AZ_iterate(Avbr, Pvbr, Svbr, x, b, az_options, params, status, proc_config, 0, AZ_calc, verbose); if (verbose) std::cout << "calling AZ_free_memory..."<<std::endl; AZ_free_memory(Amsr->data_org[AZ_name]); AZ_free_memory(Avbr->data_org[AZ_name]); //solve with Amsr again, not reusing preconditioner if (verbose) cout << "solve Amsr (keepinfo==0)"<<endl; call_AZ_iterate(Amsr, Pmsr, Smsr, x, b, az_options, params, status, proc_config, 0, AZ_calc, verbose); //Second solve with Avbr, this time with keepinfo==1 if (verbose) cout << "solve Avbr (keepinfo==1), name: " <<Avbr->data_org[AZ_name]<<endl; call_AZ_iterate(Avbr, Pvbr, Svbr, x, b, az_options, params, status, proc_config, 1, AZ_calc, verbose); //Second solve with Amsr, not reusing preconditioner if (verbose) cout << "solve Amsr (keepinfo==0, calc)"<<endl; call_AZ_iterate(Amsr, Pmsr, Smsr, x, b, az_options, params, status, proc_config, 0, AZ_calc, verbose); //Second solve with Avbr, not reusing preconditioner if (verbose) cout << "solve Avbr (keepinfo==1, reuse), name: "<<Avbr->data_org[AZ_name]<<endl; call_AZ_iterate(Avbr, Pvbr, Svbr, x, b, az_options, params, status, proc_config, 1, AZ_reuse, verbose); AZ_free_memory(Amsr->data_org[AZ_name]); AZ_free_memory(Avbr->data_org[AZ_name]); AZ_scaling_destroy(&Smsr); AZ_precond_destroy(&Pmsr); AZ_scaling_destroy(&Svbr); AZ_precond_destroy(&Pvbr); destroy_matrix(Amsr); destroy_matrix(Avbr); delete [] x; delete [] b; delete [] az_options; delete [] params; delete [] status; delete [] proc_config; free(update_index); free(external); free(external_index); free(update_index2); free(external2); free(external_index2); return(0); }
void AZ_ifpack_prec_create(double *x, double *b, int *options, double *params, int *proc_config, AZ_MATRIX *Amat, AZ_PRECOND **Prec) { AZ_IFPACK *Prec_pass_data; void *precon, *bmat ; int nr, nc, *data_org; double rthresh, athresh; Prec_pass_data = (AZ_IFPACK *) AZ_allocate(sizeof(AZ_IFPACK)); az2ifp_blockmatrix(&bmat, Amat); /* Create IFPACK encapsulation of Amat */ /* set the preconditioning structure 'Prec'. */ if (options[AZ_precond] == AZ_none) ifp_preconditioner(&precon, bmat, IFP_NONE, (double) options[AZ_graph_fill], 0.0, IFP_INVERSE, 0.0, 0.0); else if (options[AZ_precond] == AZ_Jacobi) { rthresh = params[AZ_rthresh]; athresh = params[AZ_athresh]; ifp_preconditioner(&precon, bmat, IFP_BJACOBI, 0.0, 0.0, IFP_SVD, rthresh, athresh); /*IFP_INVERSE, 0.0, 0.0); */ } else if (options[AZ_precond] == AZ_dom_decomp && options[AZ_subdomain_solve] == AZ_bilu_ifp) { rthresh = params[AZ_rthresh]; athresh = params[AZ_athresh]; ifp_preconditioner(&precon, bmat, IFP_BILUK, (double) options[AZ_graph_fill], 0.0, IFP_SVD, rthresh, athresh); /*IFP_INVERSE, 0.0, 0.0); */ } else { printf("Not a supported preconditioner in az_ifpack_prec_create\n"); abort(); } (*Prec) = AZ_precond_create(Amat,AZ_ifpack_precon,NULL); /* Store pointers to preconditioner and IFPACK encapsulation of Amat */ Prec_pass_data->precon = precon; Prec_pass_data->bmat = bmat; /* Construct auxiliary vector for use with apply function. NOTE: We are assuming only one RHS at this time !!! */ data_org = Amat->data_org; nr = data_org[AZ_N_internal] + data_org[AZ_N_border]; nc = 1; /*input_vector = (double *) malloc (nr * sizeof(double)); Prec_pass_data.input_vector = input_vector; */ Prec_pass_data->nr = nr; Prec_pass_data->nc = nc; (*Prec)->Pmat = Amat; Prec_pass_data->user_aux_ptr = (*Prec)->Pmat->aux_ptr; /* Save this to be able to restore*/ (*Prec)->Pmat->aux_ptr = (void *) Prec_pass_data; (*Prec)->prec_function = AZ_ifpack_precon; Prec_pass_data->user_precon = options[AZ_precond]; /* Save this to be able to restore*/ options[AZ_precond] = AZ_user_precond; }