void LisMatrix::multiply(const LisVector &x, LisVector &y) const { if (!_is_assembled) throw std::logic_error("LisMatrix::matvec(): matrix not assembled."); int ierr = lis_matvec(_AA, const_cast<LisVector*>(&x)->getRawVector(), y.getRawVector()); checkLisError(ierr); }
void lis_matvec_f(LIS_MATRIX_F *A, LIS_VECTOR_F *x, LIS_VECTOR_F *y, LIS_INT *ierr) { LIS_DEBUG_FUNC_IN; *ierr = lis_matvec((LIS_MATRIX)LIS_V2P(A),(LIS_VECTOR)LIS_V2P(x),(LIS_VECTOR)LIS_V2P(y)); LIS_DEBUG_FUNC_OUT; return; }
LIS_INT lis_solve_kernel(LIS_MATRIX A, LIS_VECTOR b, LIS_VECTOR x, LIS_SOLVER solver, LIS_PRECON precon) { LIS_INT nsolver, precon_type, maxiter; LIS_INT err; LIS_SCALAR *residual; LIS_VECTOR xx; LIS_INT output; LIS_INT scale; LIS_INT conv_cond; LIS_INT precision,is_use_at,storage,block; LIS_INT i,n,np; double p_c_times, p_i_times,itimes; LIS_SCALAR nrm2,tol,tol_w; LIS_VECTOR t; LIS_VECTOR bb; LIS_MATRIX AA,B; LIS_MATRIX At; char buf[64]; LIS_DEBUG_FUNC_IN; nsolver = solver->options[LIS_OPTIONS_SOLVER]; precon_type = solver->options[LIS_OPTIONS_PRECON]; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; scale = solver->options[LIS_OPTIONS_SCALE]; precision = solver->options[LIS_OPTIONS_PRECISION]; is_use_at = solver->options[LIS_OPTIONS_USE_AT]; storage = solver->options[LIS_OPTIONS_STORAGE]; block = solver->options[LIS_OPTIONS_STORAGE_BLOCK]; conv_cond = solver->options[LIS_OPTIONS_CONV_COND]; tol = solver->params[LIS_PARAMS_RESID-LIS_OPTIONS_LEN]; tol_w = solver->params[LIS_PARAMS_RESID_WEIGHT-LIS_OPTIONS_LEN]; solver->precision = precision; if( nsolver < 1 || nsolver > LIS_SOLVERS_LEN ) { LIS_SETERR2(LIS_ERR_ILL_ARG,"Parameter LIS_OPTIONS_SOLVER is %d (Set between 1 to %d)\n",nsolver, LIS_SOLVERS_LEN); return LIS_ERR_ILL_ARG; } if( precon_type < 0 || precon_type > precon_register_type ) { LIS_SETERR2(LIS_ERR_ILL_ARG,"Parameter LIS_OPTIONS_PRECON is %d (Set between 0 to %d)\n",precon_type, precon_register_type-1); return LIS_ERR_ILL_ARG; } if( maxiter<0 ) { LIS_SETERR1(LIS_ERR_ILL_ARG,"Parameter LIS_OPTIONS_MAXITER(=%d) is less than 0\n",maxiter); return LIS_ERR_ILL_ARG; } #ifdef USE_MPI if( precon_type == LIS_PRECON_TYPE_SAAMG && solver->A->nprocs < 2) { LIS_SETERR1(LIS_ERR_ILL_ARG,"Parameter A->nprocs (=%d) is less than 2 (Set more than 1 when using parallel version of SAAMG)\n",solver->A->nprocs); return LIS_ERR_ILL_ARG; } #endif #ifdef USE_QUAD_PRECISION if( precision==LIS_PRECISION_QUAD && lis_solver_execute_quad[nsolver]==NULL ) { LIS_SETERR1(LIS_ERR_NOT_IMPLEMENTED,"Quad precision solver %s is not implemented\n",lis_solvername[nsolver]); return LIS_ERR_NOT_IMPLEMENTED; } else if( precision==LIS_PRECISION_SWITCH && lis_solver_execute_switch[nsolver]==NULL ) { LIS_SETERR1(LIS_ERR_NOT_IMPLEMENTED,"Switch solver %s is not implemented\n",lis_solvername[nsolver]); return LIS_ERR_NOT_IMPLEMENTED; } if( solver->options[LIS_OPTIONS_SWITCH_MAXITER]==-1 ) { solver->options[LIS_OPTIONS_SWITCH_MAXITER] = maxiter; } #endif err = lis_solver_check_params[nsolver](solver); if( err ) { solver->retcode = err; return err; } /* end parameter check */ solver->A = A; solver->b = b; /* create initial vector */ #ifndef USE_QUAD_PRECISION err = lis_vector_duplicate(A,&xx); #else if( precision==LIS_PRECISION_DOUBLE ) { err = lis_vector_duplicate(A,&xx); } else { err = lis_vector_duplicateex(LIS_PRECISION_QUAD,A,&xx); } #endif if( err ) { solver->retcode = err; return err; } if( solver->options[LIS_OPTIONS_INITGUESS_ZEROS] ) { if( output ) lis_printf(A->comm,"initial vector x = 0\n"); #ifndef USE_QUAD_PRECISION lis_vector_set_all(0.0,xx); #else if( precision==LIS_PRECISION_DOUBLE ) { lis_vector_set_all(0.0,xx); } else { lis_vector_set_allex_nm(0.0,xx); } #endif } else { if( output ) lis_printf(A->comm,"initial vector x = user defined\n"); #ifndef USE_QUAD_PRECISION lis_vector_copy(x,xx); #else if( precision==LIS_PRECISION_DOUBLE ) { lis_vector_copy(x,xx); } else { lis_vector_copyex_nm(x,xx); } #endif } /* create residual history vector */ if( solver->residual ) lis_free(solver->residual); residual = (LIS_SCALAR *)lis_malloc((maxiter+2)*sizeof(LIS_SCALAR),"lis_solve::residual"); if( residual==NULL ) { LIS_SETERR_MEM((maxiter+2)*sizeof(LIS_SCALAR)); lis_vector_destroy(xx); solver->retcode = err; return err; } residual[0] = 1.0; n = A->n; np = A->np; t = NULL; At = NULL; p_c_times = lis_wtime(); if( precon_type==LIS_PRECON_TYPE_IS ) { if( solver->d==NULL ) { err = lis_vector_duplicate(A,&solver->d); if( err ) { return err; } } if( !A->is_scaled ) { lis_matrix_scaling(A,b,solver->d,LIS_SCALE_JACOBI); } else if( !b->is_scaled ) { #ifdef _OPENMP #pragma omp parallel for #endif for(i=0;i<n;i++) { b->value[i] = b->value[i]*solver->d->value[i]; } } if( nsolver >= LIS_SOLVER_JACOBI && nsolver <= LIS_SOLVER_SOR ) { solver->options[LIS_OPTIONS_ISLEVEL] = 0; } } else if( nsolver >= LIS_SOLVER_JACOBI && nsolver <= LIS_SOLVER_SOR && precon_type!=LIS_PRECON_TYPE_NONE ) { if( solver->d==NULL ) { err = lis_vector_duplicate(A,&solver->d); if( err ) { return err; } } if( !A->is_scaled ) { lis_matrix_scaling(A,b,solver->d,LIS_SCALE_JACOBI); } } else if( scale ) { if( storage==LIS_MATRIX_BSR && scale==LIS_SCALE_JACOBI ) { if( A->matrix_type!=LIS_MATRIX_BSR ) { err = lis_matrix_duplicate(A,&B); if( err ) return err; lis_matrix_set_blocksize(B,block,block,NULL,NULL); lis_matrix_set_type(B,storage); err = lis_matrix_convert(A,B); if( err ) return err; lis_matrix_storage_destroy(A); lis_matrix_DLU_destroy(A); lis_matrix_diag_destroy(A->WD); if( A->l2g_map ) lis_free( A->l2g_map ); if( A->commtable ) lis_commtable_destroy( A->commtable ); if( A->ranges ) lis_free( A->ranges ); err = lis_matrix_copy_struct(B,A); if( err ) return err; lis_free(B); } err = lis_matrix_split(A); if( err ) return err; err = lis_matrix_diag_duplicate(A->D,&solver->WD); if( err ) return err; lis_matrix_diag_copy(A->D,solver->WD); lis_matrix_diag_inverse(solver->WD); lis_matrix_bscaling_bsr(A,solver->WD); lis_vector_duplicate(A,&t); lis_matrix_diag_matvec(solver->WD,b,t); lis_vector_copy(t,b); lis_vector_destroy(t); t = NULL; } else { if( solver->d==NULL ) { err = lis_vector_duplicate(A,&solver->d); if( err ) { return err; } } if( scale==LIS_SCALE_JACOBI && nsolver==LIS_SOLVER_CG ) { scale = LIS_SCALE_SYMM_DIAG; } if( !A->is_scaled ) { lis_matrix_scaling(A,b,solver->d,scale); } else if( !b->is_scaled ) { #ifdef _OPENMP #pragma omp parallel for #endif for(i=0;i<n;i++) { b->value[i] = b->value[i]*solver->d->value[i]; } } } } /* precon_type = precon->precon_type;*/ if( precon_type==LIS_PRECON_TYPE_IS ) { if( nsolver < LIS_SOLVER_JACOBI || nsolver > LIS_SOLVER_SOR ) { AA = solver->A; bb = solver->b; } else { AA = precon->A; bb = precon->Pb; } } else { AA = A; bb = b; } p_c_times = lis_wtime() - p_c_times; itimes = lis_wtime(); /* Matrix Convert */ solver->A = AA; solver->b = bb; err = lis_matrix_convert_self(solver); if( err ) { lis_vector_destroy(xx); lis_solver_work_destroy(solver); lis_free(residual); solver->retcode = err; return err; } block = solver->A->bnr; if( A->my_rank==0 ) { if( output ) printf("precision : %s\n", lis_precisionname[precision]); if( output ) printf("solver : %s %d\n", lis_solvername[nsolver],nsolver); switch( precon_type ) { case LIS_PRECON_TYPE_ILU: i = solver->options[LIS_OPTIONS_FILL]; if( A->matrix_type==LIS_MATRIX_BSR || A->matrix_type==LIS_MATRIX_VBR ) { if( output ) sprintf(buf,"Block %s(%d)",lis_preconname[precon_type],i); } else { if( output ) sprintf(buf,"%s(%d)",lis_preconname[precon_type],i); } break; default: if( output ) sprintf(buf,"%s",lis_preconname[precon_type]); break; } if( solver->options[LIS_OPTIONS_ADDS] && precon_type ) { if( output ) printf("precon : %s + additive schwarz\n", buf); } else { if( output ) printf("precon : %s\n", buf); } } switch(conv_cond) { case LIS_CONV_COND_NRM2_R: case LIS_CONV_COND_NRM2_B: if( A->my_rank==0 ) { if( output ) ("CONV_COND : ||r||_2 <= %6.1e*||r_0||_2\n", tol); } break; case LIS_CONV_COND_NRM1_B: lis_vector_nrm1(b,&nrm2); nrm2 = nrm2*tol_w + tol; if( A->my_rank==0 ) { if( output ) printf("conv_cond : ||r||_1 <= %6.1e*||b||_1 + %6.1e = %6.1e\n", tol_w,tol,nrm2); } break; } if( A->my_rank==0 ) { if( AA->matrix_type==LIS_MATRIX_BSR || AA->matrix_type==LIS_MATRIX_BSC ) { if( output ) printf("storage : %s(%d x %d)\n", lis_storagename[AA->matrix_type-1],block,block); } else { if( output ) printf("storage : %s\n", lis_storagename[AA->matrix_type-1]); } } /* create work vector */ err = lis_solver_malloc_work[nsolver](solver); if( err ) { lis_vector_destroy(xx); lis_precon_destroy(precon); solver->retcode = err; return err; } if( nsolver==LIS_SOLVER_BICG && is_use_at ) { if( output ) lis_printf(A->comm,"Use At\n"); lis_matrix_duplicate(AA,&At); lis_matrix_set_type(At,LIS_USE_AT_TYPE[AA->matrix_type]); lis_matrix_convert(AA,At); solver->At = At; } solver->x = xx; solver->xx = x; solver->precon = precon; solver->residual = residual; /* execute solver */ #ifndef USE_QUAD_PRECISION err = lis_solver_execute[nsolver](solver); #else if( precision==LIS_PRECISION_DOUBLE ) { err = lis_solver_execute[nsolver](solver); } else if( precision==LIS_PRECISION_QUAD ) { err = lis_solver_execute_quad[nsolver](solver); } else if( precision==LIS_PRECISION_SWITCH ) { err = lis_solver_execute_switch[nsolver](solver); } #endif solver->retcode = err; if( scale==LIS_SCALE_SYMM_DIAG && precon_type!=LIS_PRECON_TYPE_IS) { #ifdef _OPENMP #pragma omp parallel for #endif for(i=0;i<n;i++) { x->value[i] = xx->value[i]*solver->d->value[i]; } } else { #ifndef USE_QUAD_PRECISION lis_vector_copy(xx,x); #else if( precision==LIS_PRECISION_DOUBLE ) { lis_vector_copy(xx,x); } else { lis_vector_copyex_mn(xx,x); } #endif } itimes = lis_wtime() - itimes - solver->ptimes; p_i_times = solver->ptimes; solver->ptimes = p_c_times + p_i_times; solver->p_c_times = p_c_times; solver->p_i_times = p_i_times; solver->times = solver->ptimes + itimes; solver->itimes = itimes; lis_solver_work_destroy(solver); lis_vector_duplicate(A,&t); xx->precision = LIS_PRECISION_DEFAULT; lis_matvec(A,xx,t); lis_vector_xpay(b,-1.0,t); if( scale==LIS_SCALE_SYMM_DIAG && precon_type!=LIS_PRECON_TYPE_IS) { #ifdef _OPENMP #pragma omp parallel for #endif for(i=0;i<n;i++) { t->value[i] = t->value[i]/solver->d->value[i]; } } lis_vector_nrm2(t,&nrm2); /* solver->resid = nrm2; */ if( A->my_rank==0 ) { if( err ) { if( output ) printf("lis_solve : %s(code=%d)\n\n",lis_returncode[err],err); } else { if( output ) printf("lis_solve : normal end\n\n"); } } if( precision==LIS_PRECISION_DOUBLE ) { solver->iter2 = solver->iter; } else if( precision==LIS_PRECISION_QUAD ) { solver->iter2 = 0; } lis_vector_destroy(t); /* lis_vector_destroy(d);*/ lis_vector_destroy(xx); LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; }
LIS_INT lis_epi_quad(LIS_ESOLVER esolver) { LIS_MATRIX A; LIS_VECTOR x; LIS_SCALAR evalue; LIS_INT emaxiter; LIS_REAL tol; LIS_INT iter,output; LIS_INT nprocs,my_rank; LIS_REAL nrm2,resid; LIS_QUAD_PTR qdot_xz; LIS_VECTOR z,q; double times, ptimes; LIS_DEBUG_FUNC_IN; emaxiter = esolver->options[LIS_EOPTIONS_MAXITER]; tol = esolver->params[LIS_EPARAMS_RESID - LIS_EOPTIONS_LEN]; output = esolver->options[LIS_EOPTIONS_OUTPUT]; A = esolver->A; x = esolver->x; if (esolver->options[LIS_EOPTIONS_INITGUESS_ONES] ) { lis_vector_set_all(1.0,x); } z = esolver->work[0]; q = esolver->work[1]; LIS_QUAD_SCALAR_MALLOC(qdot_xz,0,1); iter=0; while (iter<emaxiter) { iter = iter+1; /* x = x / ||x||_2 */ lis_vector_nrm2(x, &nrm2); lis_vector_scale(1/nrm2, x); /* z = A * x */ lis_matvec(A,x,z); /* evalue = <x,z> */ lis_vector_dotex_mmm(x, z, &qdot_xz); lis_quad_minus((LIS_QUAD *)qdot_xz.hi); /* resid = ||z - evalue * x||_2 / |evalue| */ lis_vector_axpyzex_mmmm(qdot_xz,x,z,q); lis_quad_minus((LIS_QUAD *)qdot_xz.hi); lis_vector_nrm2(q, &resid); evalue = qdot_xz.hi[0]; resid = fabs(resid / evalue); /* x = z */ lis_vector_copy(z, x); /* convergence check */ if( output ) { if( output & LIS_EPRINT_MEM ) esolver->residual[iter] = resid; if( output & LIS_EPRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,resid); } if( tol >= resid ) { esolver->retcode = LIS_SUCCESS; esolver->iter = iter; esolver->resid = resid; esolver->evalue[0] = evalue; LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } } esolver->retcode = LIS_MAXITER; esolver->iter = iter; esolver->resid = resid; esolver->evalue[0] = evalue; LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT main(LIS_INT argc, char* argv[]) { LIS_MATRIX A; LIS_VECTOR x,b,u; LIS_SOLVER solver; LIS_INT k,n,gn,ii,jj; LIS_INT is,ie; LIS_INT nprocs,my_rank; int int_nprocs,int_my_rank; LIS_INT nsol; LIS_INT err,iter,iter_double,iter_quad; double time,itime,ptime,p_c_time,p_i_time; LIS_REAL resid; char solvername[128]; LIS_INT *ptr,*index; LIS_SCALAR *value,gamma; LIS_DEBUG_FUNC_IN; lis_initialize(&argc, &argv); #ifdef USE_MPI MPI_Comm_size(MPI_COMM_WORLD,&int_nprocs); MPI_Comm_rank(MPI_COMM_WORLD,&int_my_rank); nprocs = int_nprocs; my_rank = int_my_rank; #else nprocs = 1; my_rank = 0; #endif if( argc < 3 ) { if( my_rank==0 ) { printf("Usage: %s n gamma [options]\n", argv[0]); } CHKERR(1); } gn = atoi(argv[1]); gamma = atof(argv[2]); if( gn<=0 ) { #ifdef _LONGLONG if( my_rank==0 ) printf("n=%lld <=0 \n",gn); #else if( my_rank==0 ) printf("n=%d <=0 \n",gn); #endif CHKERR(1); } if( my_rank==0 ) { printf("\n"); #ifdef _LONGLONG printf("number of processes = %lld\n",nprocs); #else printf("number of processes = %d\n",nprocs); #endif } #ifdef _OPENMP if( my_rank==0 ) { #ifdef _LONGLONG printf("max number of threads = %lld\n",omp_get_num_procs()); printf("number of threads = %lld\n",omp_get_max_threads()); #else printf("max number of threads = %d\n",omp_get_num_procs()); printf("number of threads = %d\n",omp_get_max_threads()); #endif } #endif if(my_rank==0) { #ifdef _LONGLONG printf("n = %lld, gamma = %f\n\n",gn,gamma); #else printf("n = %d, gamma = %f\n\n",gn,gamma); #endif } /* create matrix and vectors */ err = lis_matrix_create(LIS_COMM_WORLD,&A); CHKERR(err); err = lis_matrix_set_size(A,0,gn); CHKERR(err); err = lis_matrix_get_size(A,&n,&gn); CHKERR(err); err = lis_matrix_malloc_csr(n,3*n,&ptr,&index,&value); CHKERR(err); err = lis_matrix_get_range(A,&is,&ie); CHKERR(err); k = 0; ptr[0] = 0; for(ii=is;ii<ie;ii++) { if( ii>1 ) { jj = ii - 2; index[k] = jj; value[k++] = gamma;} if( ii<gn-1 ) { jj = ii + 1; index[k] = jj; value[k++] = 1.0;} index[k] = ii; value[k++] = 2.0; ptr[ii-is+1] = k; } err = lis_matrix_set_csr(ptr[ie-is],ptr,index,value,A); CHKERR(err); err = lis_matrix_assemble(A); CHKERR(err); err = lis_vector_duplicate(A,&u); CHKERR(err); err = lis_vector_duplicate(u,&b); CHKERR(err); err = lis_vector_duplicate(u,&x); CHKERR(err); err = lis_vector_set_all(1.0,u); lis_matvec(A,u,b); err = lis_solver_create(&solver); CHKERR(err); lis_solver_set_option("-print mem",solver); lis_solver_set_optionC(solver); err = lis_solve(A,b,x,solver); CHKERR(err); lis_solver_get_iterex(solver,&iter,&iter_double,&iter_quad); lis_solver_get_timeex(solver,&time,&itime,&ptime,&p_c_time,&p_i_time); lis_solver_get_residualnorm(solver,&resid); lis_solver_get_solver(solver,&nsol); lis_solver_get_solvername(nsol,solvername); if( my_rank==0 ) { #ifdef _LONGLONG #ifdef _LONG__DOUBLE printf("%s: number of iterations = %lld \n",solvername, iter); #else printf("%s: number of iterations = %lld (double = %lld, quad = %lld)\n",solvername,iter, iter_double, iter_quad); #endif #else #ifdef _LONG__DOUBLE printf("%s: number of iterations = %d \n",solvername, iter); #else printf("%s: number of iterations = %d (double = %d, quad = %d)\n",solvername,iter, iter_double, iter_quad); #endif #endif printf("%s: elapsed time = %e sec.\n",solvername,time); printf("%s: preconditioner = %e sec.\n",solvername, ptime); printf("%s: matrix creation = %e sec.\n",solvername, p_c_time); printf("%s: linear solver = %e sec.\n",solvername, itime); #ifdef _LONG__DOUBLE printf("%s: relative residual = %Le\n\n",solvername,resid); #else printf("%s: relative residual = %e\n\n",solvername,resid); #endif } lis_solver_destroy(solver); lis_matrix_destroy(A); lis_vector_destroy(b); lis_vector_destroy(x); lis_vector_destroy(u); lis_finalize(); LIS_DEBUG_FUNC_OUT; return 0; }
LIS_INT lis_bicrsafe_quad(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR x; LIS_VECTOR r, rtld, artld, mr, amr, p, ap, map; LIS_VECTOR y, my, u, au, z; LIS_QUAD_PTR alpha, beta, rho, rho_old; LIS_QUAD_PTR qsi, eta, one; LIS_QUAD_PTR tmp, tmpdot[5]; LIS_REAL bnrm2, nrm2, tol; LIS_INT iter,maxiter,output,conv; double time,ptime; LIS_DEBUG_FUNC_IN; A = solver->A; x = solver->x; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; conv = solver->options[LIS_OPTIONS_CONV_COND]; ptime = 0.0; rtld = solver->work[0]; r = solver->work[1]; mr = solver->work[2]; amr = solver->work[3]; p = solver->work[4]; ap = solver->work[5]; map = solver->work[6]; my = solver->work[7]; y = solver->work[8]; u = solver->work[9]; z = solver->work[10]; au = solver->work[11]; artld = solver->work[12]; LIS_QUAD_SCALAR_MALLOC(alpha,0,1); LIS_QUAD_SCALAR_MALLOC(beta,1,1); LIS_QUAD_SCALAR_MALLOC(rho,2,1); LIS_QUAD_SCALAR_MALLOC(rho_old,3,1); LIS_QUAD_SCALAR_MALLOC(qsi,4,1); LIS_QUAD_SCALAR_MALLOC(eta,5,1); LIS_QUAD_SCALAR_MALLOC(tmp,6,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[0],7,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[1],8,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[2],9,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[3],10,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[4],11,1); LIS_QUAD_SCALAR_MALLOC(one,13,1); /* Initial Residual */ if( lis_solver_get_initial_residual(solver,NULL,NULL,r,&bnrm2) ) { LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } tol = solver->tol; lis_solver_set_shadowresidual(solver,r,rtld); lis_matvect(A,rtld,artld); time = lis_wtime(); lis_psolve(solver, r, mr); ptime += lis_wtime()-time; lis_matvec(A,mr,amr); lis_vector_dotex_mmm(rtld,amr,&rho_old); lis_vector_copyex_mm(amr,ap); lis_vector_copyex_mm(mr,p); one.hi[0] = -1.0; one.lo[0] = 0.0; for( iter=1; iter<=maxiter; iter++ ) { /* map = M^-1 * ap */ time = lis_wtime(); lis_psolve(solver, ap, map); ptime += lis_wtime()-time; /* tmpdot[0] = <artld,map> */ /* alpha = rho_old / tmpdot[0] */ lis_vector_dotex_mmm(artld,map,&tmpdot[0]); lis_quad_div((LIS_QUAD *)alpha.hi,(LIS_QUAD *)rho_old.hi,(LIS_QUAD *)tmpdot[0].hi); /* tmpdot[0] = <y,y> */ /* tmpdot[1] = <amr,r> */ /* tmpdot[2] = <y,r> */ /* tmpdot[3] = <amr,y> */ /* tmpdot[4] = <amr,amr> */ lis_vector_dotex_mmm(y,y,&tmpdot[0]); lis_vector_dotex_mmm(amr,r,&tmpdot[1]); lis_vector_dotex_mmm(y,r,&tmpdot[2]); lis_vector_dotex_mmm(amr,y,&tmpdot[3]); lis_vector_dotex_mmm(amr,amr,&tmpdot[4]); if(iter==1) { lis_quad_div((LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmpdot[1].hi,(LIS_QUAD *)tmpdot[4].hi); eta.hi[0] = 0.0; eta.lo[0] = 0.0; } else { lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)tmpdot[4].hi,(LIS_QUAD *)tmpdot[0].hi); lis_quad_sqr((LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmpdot[3].hi); lis_quad_sub((LIS_QUAD *)tmp.hi,(LIS_QUAD *)tmp.hi,(LIS_QUAD *)qsi.hi); lis_quad_mul((LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmpdot[0].hi,(LIS_QUAD *)tmpdot[1].hi); lis_quad_mul((LIS_QUAD *)eta.hi,(LIS_QUAD *)tmpdot[2].hi,(LIS_QUAD *)tmpdot[3].hi); lis_quad_sub((LIS_QUAD *)qsi.hi,(LIS_QUAD *)qsi.hi,(LIS_QUAD *)eta.hi); lis_quad_div((LIS_QUAD *)qsi.hi,(LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmp.hi); lis_quad_mul((LIS_QUAD *)eta.hi,(LIS_QUAD *)tmpdot[4].hi,(LIS_QUAD *)tmpdot[2].hi); lis_quad_mul((LIS_QUAD *)tmpdot[0].hi,(LIS_QUAD *)tmpdot[3].hi,(LIS_QUAD *)tmpdot[1].hi); lis_quad_sub((LIS_QUAD *)eta.hi,(LIS_QUAD *)eta.hi,(LIS_QUAD *)tmpdot[0].hi); lis_quad_div((LIS_QUAD *)eta.hi,(LIS_QUAD *)eta.hi,(LIS_QUAD *)tmp.hi); } /* u = qsi*map + eta*my + eta*beta*u */ /* au = A * u */ lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)eta.hi,(LIS_QUAD *)beta.hi); lis_vector_scaleex_mm(tmp,u); lis_vector_axpyex_mmm(qsi,map,u); lis_vector_axpyex_mmm(eta,my,u); lis_matvec(A,u,au); /* z = qsi*mr + eta*z - alpha*u */ lis_vector_scaleex_mm(eta,z); lis_vector_axpyex_mmm(qsi,mr,z); lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyex_mmm(alpha,u,z); /* y = qsi*amr + eta*y - alpha*au */ /* my = M^-1 * y */ lis_vector_scaleex_mm(eta,y); lis_vector_axpyex_mmm(qsi,amr,y); lis_vector_axpyex_mmm(alpha,au,y); time = lis_wtime(); lis_psolve(solver, y, my); ptime += lis_wtime()-time; /* x = x + alpha*p + z */ lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyex_mmm(alpha,p,x); lis_quad_minus((LIS_QUAD *)one.hi); lis_vector_axpyex_mmm(one,z,x); /* r = r - alpha*ap - y */ lis_quad_minus((LIS_QUAD *)alpha.hi); lis_quad_minus((LIS_QUAD *)one.hi); lis_vector_axpyex_mmm(alpha,ap,r); lis_vector_axpyex_mmm(one,y,r); /* convergence check */ lis_solver_get_residual[conv](r,solver,&nrm2); if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol >= nrm2 ) { solver->retcode = LIS_SUCCESS; solver->iter = iter; solver->resid = nrm2; solver->ptime = ptime; LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } /* mr = mr - alpha*map - my */ /* amr = A * mr */ /* rho = <rtld,amr> */ lis_vector_axpyex_mmm(alpha,map,mr); lis_vector_axpyex_mmm(one,my,mr); lis_matvec(A,mr,amr); lis_vector_dotex_mmm(rtld,amr,&rho); if( rho.hi[0]==0.0 && rho.lo[0]==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* beta = (rho / rho_old) * (alpha / qsi) */ lis_quad_minus((LIS_QUAD *)alpha.hi); lis_quad_div((LIS_QUAD *)beta.hi,(LIS_QUAD *)rho.hi,(LIS_QUAD *)rho_old.hi); lis_quad_div((LIS_QUAD *)tmp.hi,(LIS_QUAD *)alpha.hi,(LIS_QUAD *)qsi.hi); lis_quad_mul((LIS_QUAD *)beta.hi,(LIS_QUAD *)beta.hi,(LIS_QUAD *)tmp.hi); /* p = mr + beta*(p - u) */ /* ap = amr + beta*(ap - au) */ lis_vector_axpyex_mmm(one,u,p); lis_vector_xpayex_mmm(mr,beta,p); lis_vector_axpyex_mmm(one,au,ap); lis_vector_xpayex_mmm(amr,beta,ap); rho_old.hi[0] = rho.hi[0]; rho_old.lo[0] = rho.lo[0]; } solver->retcode = LIS_MAXITER; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_orthomin_quad(LIS_SOLVER solver) { LIS_Comm comm; LIS_MATRIX A; LIS_PRECON M; LIS_VECTOR x; LIS_VECTOR r, rtld, *p, *ap, *aptld; LIS_QUAD *dotsave; LIS_QUAD_PTR alpha, beta, tmp, one; LIS_REAL bnrm2, nrm2, tol; LIS_INT iter,maxiter,output,conv; double time,ptime; LIS_INT m,l,lmax,ip,ip0; LIS_DEBUG_FUNC_IN; comm = LIS_COMM_WORLD; A = solver->A; M = solver->precon; x = solver->x; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; m = solver->options[LIS_OPTIONS_RESTART]; conv = solver->options[LIS_OPTIONS_CONV_COND]; ptime = 0.0; LIS_QUAD_SCALAR_MALLOC(alpha,0,1); LIS_QUAD_SCALAR_MALLOC(beta,1,1); LIS_QUAD_SCALAR_MALLOC(tmp,3,1); LIS_QUAD_SCALAR_MALLOC(one,4,1); r = solver->work[0]; rtld = solver->work[1]; p = &solver->work[2]; ap = &solver->work[ (m+1)+2]; aptld = &solver->work[2*(m+1)+2]; one.hi[0] = 1.0; one.lo[0] = 0.0; dotsave = (LIS_QUAD *)lis_malloc( sizeof(LIS_QUAD) * (m+1),"lis_orthomin_quad::dotsave" ); /* Initial Residual */ if( lis_solver_get_initial_residual(solver,M,r,rtld,&bnrm2) ) { LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } tol = solver->tol; iter=1; while( iter<=maxiter ) { ip = (iter-1) % (m+1); /* p[ip] = rtld */ lis_vector_copyex_mm(rtld,p[ip]); /* ap[ip] = A*p[ip] */ /* aptld[ip] = M^-1 ap[ip] */ lis_matvec(A,p[ip],ap[ip]); time = lis_wtime(); lis_psolve(solver, ap[ip], aptld[ip]); ptime += lis_wtime()-time; lmax = _min(m,iter-1); for(l=1;l<=lmax;l++) { ip0 = (ip+m+1-l) % (m+1); /* beta = -<Ar[ip],Ap[ip0]> / <Ap[ip0],Ap[ip0]> */ lis_vector_dotex_mmm(aptld[ip],aptld[ip0],&beta); lis_quad_mul((LIS_QUAD *)beta.hi,(LIS_QUAD *)beta.hi,&dotsave[l-1]); lis_quad_minus((LIS_QUAD *)beta.hi); lis_vector_axpyex_mmm(beta,p[ip0] ,p[ip]); lis_vector_axpyex_mmm(beta,ap[ip0] ,ap[ip]); lis_vector_axpyex_mmm(beta,aptld[ip0],aptld[ip]); } for(l=m-1;l>0;l--) { dotsave[l] = dotsave[l-1]; } lis_vector_dotex_mmm(aptld[ip],aptld[ip],&tmp); dotsave[0].hi = tmp.hi[0]; dotsave[0].lo = tmp.lo[0]; /* test breakdown */ if( tmp.hi[0]==0.0 && tmp.lo[0]==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter; solver->resid = nrm2; lis_free(dotsave); LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } lis_quad_div(&dotsave[0],(LIS_QUAD *)one.hi,&dotsave[0]); /* alpha = <rtld,Aptld[ip]> */ lis_vector_dotex_mmm(rtld,aptld[ip],&alpha); lis_quad_mul((LIS_QUAD *)alpha.hi,(LIS_QUAD *)alpha.hi,&dotsave[0]); lis_vector_axpyex_mmm( alpha,p[ip],x); lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyex_mmm(alpha,ap[ip],r); lis_vector_axpyex_mmm(alpha,aptld[ip],rtld); lis_quad_minus((LIS_QUAD *)alpha.hi); /* convergence check */ lis_solver_get_residual[conv](r,solver,&nrm2); if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT ) lis_print_rhistory(comm,iter,nrm2); } if( tol > nrm2 ) { solver->retcode = LIS_SUCCESS; solver->iter = iter; solver->resid = nrm2; solver->ptime = ptime; lis_free(dotsave); LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } iter++; } solver->retcode = LIS_MAXITER; solver->iter = iter; solver->resid = nrm2; lis_free(dotsave); LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_fgmres_quad(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR b,x; LIS_VECTOR r,s,*z,*v; LIS_QUAD *h; LIS_QUAD_PTR aa,bb,rr,a2,b2,t,one,tmp; LIS_REAL bnrm2,nrm2,tol; LIS_INT iter,maxiter,n,output; double time,ptime; LIS_REAL rnorm; LIS_INT i,j,k,m; LIS_INT ii,i1,iiv,i1v,iih,jj; LIS_INT h_dim; LIS_INT cs,sn; LIS_DEBUG_FUNC_IN; A = solver->A; b = solver->b; x = solver->x; n = A->n; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; m = solver->options[LIS_OPTIONS_RESTART]; h_dim = m+1; ptime = 0.0; s = solver->work[0]; r = solver->work[1]; z = &solver->work[2]; v = &solver->work[m+2]; h = (LIS_QUAD *)lis_malloc( sizeof(LIS_QUAD)*(h_dim+1)*(h_dim+2),"lis_fgmres_quad::h" ); cs = (m+1)*h_dim; sn = (m+2)*h_dim; LIS_QUAD_SCALAR_MALLOC(aa,0,1); LIS_QUAD_SCALAR_MALLOC(bb,1,1); LIS_QUAD_SCALAR_MALLOC(rr,2,1); LIS_QUAD_SCALAR_MALLOC(a2,3,1); LIS_QUAD_SCALAR_MALLOC(b2,4,1); LIS_QUAD_SCALAR_MALLOC(t,5,1); LIS_QUAD_SCALAR_MALLOC(tmp,6,1); LIS_QUAD_SCALAR_MALLOC(one,7,1); one.hi[0] = 1.0; one.lo[0] = 0.0; /* Initial Residual */ if( lis_solver_get_initial_residual(solver,NULL,NULL,v[0],&bnrm2) ) { lis_free(h); LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } tol = solver->tol; rnorm = 1.0/bnrm2; iter=0; while( iter<maxiter ) { /* first column of V */ /* v = r / ||r||_2 */ lis_vector_scaleex_nm(bnrm2,v[0]); /* s = ||r||_2 e_1 */ lis_vector_set_allex_nm(0.0,s); s->value[0] = rnorm; s->value_lo[0] = 0.0; i = 0; do { iter++; i++; ii = i-1; i1 = i; iiv = i-1; i1v = i; iih = (i-1)*h_dim; /* z = M^-1 * v */ time = lis_wtime(); lis_psolve(solver,v[iiv],z[iiv]); ptime += lis_wtime()-time; /* w = A * z */ lis_matvec(A,z[iiv], v[i1v]); for(k=0;k<i;k++) { /* h[k,i] = <w,v[k]> */ /* w = w - h[k,i] * v[k] */ lis_vector_dotex_mmm(v[i1v],v[k],&t); h[k+iih].hi = t.hi[0]; h[k+iih].lo = t.lo[0]; lis_quad_minus((LIS_QUAD *)t.hi); lis_vector_axpyex_mmm(t,v[k],v[i1v]); } /* h[i+1,i] = ||w|| */ /* v[i+1] = w / h[i+1,i] */ lis_vector_nrm2ex_mm(v[i1v],&t); h[i1+iih].hi = t.hi[0]; h[i1+iih].lo = t.lo[0]; lis_quad_div((LIS_QUAD *)tmp.hi,(LIS_QUAD *)one.hi,(LIS_QUAD *)t.hi); lis_vector_scaleex_mm(tmp,v[i1v]); for(k=1;k<=ii;k++) { jj = k-1; t.hi[0] = h[jj+iih].hi; t.lo[0] = h[jj+iih].lo; lis_quad_mul((LIS_QUAD *)aa.hi,(LIS_QUAD *)&h[jj+cs],(LIS_QUAD *)t.hi); lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[jj+sn],(LIS_QUAD *)&h[k+iih]); lis_quad_add((LIS_QUAD *)aa.hi,(LIS_QUAD *)aa.hi,(LIS_QUAD *)tmp.hi); lis_quad_mul((LIS_QUAD *)bb.hi,(LIS_QUAD *)&h[jj+sn],(LIS_QUAD *)t.hi); lis_quad_minus((LIS_QUAD *)bb.hi); lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[jj+cs],(LIS_QUAD *)&h[k+iih]); lis_quad_add((LIS_QUAD *)bb.hi,(LIS_QUAD *)bb.hi,(LIS_QUAD *)tmp.hi); h[jj+iih].hi = aa.hi[0]; h[jj+iih].lo = aa.lo[0]; h[k+iih].hi = bb.hi[0]; h[k+iih].lo = bb.lo[0]; } aa.hi[0] = h[ii+iih].hi; aa.lo[0] = h[ii+iih].lo; bb.hi[0] = h[i1+iih].hi; bb.lo[0] = h[i1+iih].lo; lis_quad_sqr((LIS_QUAD *)a2.hi,(LIS_QUAD *)aa.hi); lis_quad_sqr((LIS_QUAD *)b2.hi,(LIS_QUAD *)bb.hi); lis_quad_add((LIS_QUAD *)rr.hi,(LIS_QUAD *)a2.hi,(LIS_QUAD *)b2.hi); lis_quad_sqrt((LIS_QUAD *)rr.hi,(LIS_QUAD *)rr.hi); if( rr.hi[0]==0.0 ) { rr.hi[0]=1.0e-17; rr.lo[0]=0.0; } lis_quad_div((LIS_QUAD *)&h[ii+cs],(LIS_QUAD *)aa.hi,(LIS_QUAD *)rr.hi); lis_quad_div((LIS_QUAD *)&h[ii+sn],(LIS_QUAD *)bb.hi,(LIS_QUAD *)rr.hi); tmp.hi[0] = s->value[ii]; tmp.lo[0] = s->value_lo[ii]; lis_quad_mul((LIS_QUAD *)aa.hi,(LIS_QUAD *)&h[ii+sn],(LIS_QUAD *)tmp.hi); lis_quad_mul((LIS_QUAD *)bb.hi,(LIS_QUAD *)&h[ii+cs],(LIS_QUAD *)tmp.hi); lis_quad_minus((LIS_QUAD *)aa.hi); s->value[i1] = aa.hi[0]; s->value_lo[i1] = aa.lo[0]; s->value[ii] = bb.hi[0]; s->value_lo[ii] = bb.lo[0]; lis_quad_mul((LIS_QUAD *)aa.hi,(LIS_QUAD *)&h[ii+cs],(LIS_QUAD *)&h[ii+iih]); lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[ii+sn],(LIS_QUAD *)&h[i1+iih]); lis_quad_add((LIS_QUAD *)aa.hi,(LIS_QUAD *)aa.hi,(LIS_QUAD *)tmp.hi); h[ii+iih].hi = aa.hi[0]; h[ii+iih].lo = aa.lo[0]; /* convergence check */ nrm2 = fabs(s->value[i1]); if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol >= nrm2 ) break; } while( i<m && iter <maxiter ); /* Solve H * Y = S for upper Hessenberg matrix H */ tmp.hi[0] = s->value[ii]; tmp.lo[0] = s->value_lo[ii]; lis_quad_div((LIS_QUAD *)tmp.hi,(LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[ii+iih]); s->value[ii] = tmp.hi[0]; s->value_lo[ii] = tmp.lo[0]; for(k=1;k<=ii;k++) { jj = ii-k; t.hi[0] = s->value[jj]; t.lo[0] = s->value_lo[jj]; for(j=jj+1;j<=ii;j++) { tmp.hi[0] = s->value[j]; tmp.lo[0] = s->value_lo[j]; lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[jj+j*h_dim]); lis_quad_sub((LIS_QUAD *)t.hi,(LIS_QUAD *)t.hi,(LIS_QUAD *)tmp.hi); } lis_quad_div((LIS_QUAD *)tmp.hi,(LIS_QUAD *)t.hi,(LIS_QUAD *)&h[jj+jj*h_dim]); s->value[jj] = tmp.hi[0]; s->value_lo[jj] = tmp.lo[0]; } /* x = x + y * z */ for(j=0;j<=ii;j++) { aa.hi[0] = s->value[j]; aa.lo[0] = s->value_lo[j]; lis_vector_axpyex_mmm(aa,z[j],x); } if( tol >= nrm2 ) { solver->retcode = LIS_SUCCESS; solver->iter = iter; solver->resid = nrm2; solver->ptime = ptime; lis_free(h); LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } lis_matvec(A,x,v[0]); lis_vector_xpay(b,-1.0,v[0]); memset(v[0]->value_lo,0,n*sizeof(LIS_SCALAR)); lis_vector_nrm2(v[0],&rnorm); bnrm2 = 1.0/rnorm; } solver->retcode = LIS_MAXITER; solver->iter = iter+1; solver->resid = nrm2; lis_free(h); LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_gmres_switch(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR b,x; LIS_VECTOR r,s,z,*v; LIS_QUAD *h; LIS_SCALAR *hd; LIS_QUAD_PTR aa,bb,rr,a2,b2,t,one,tmp; LIS_QUAD_PTR rnorm; LIS_REAL bnrm2,nrm2,tol,tol2; LIS_INT iter,maxiter,n,output; LIS_INT iter2,maxiter2; double time,ptime; LIS_INT i,j,k,m; LIS_INT ii,i1,iiv,i1v,iih,jj; LIS_INT h_dim; LIS_INT cs,sn; LIS_DEBUG_FUNC_IN; A = solver->A; b = solver->b; x = solver->x; n = A->n; maxiter = solver->options[LIS_OPTIONS_MAXITER]; maxiter2 = solver->options[LIS_OPTIONS_SWITCH_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; tol = solver->params[LIS_PARAMS_RESID-LIS_OPTIONS_LEN]; tol2 = solver->params[LIS_PARAMS_SWITCH_RESID-LIS_OPTIONS_LEN]; m = solver->options[LIS_OPTIONS_RESTART]; h_dim = m+1; ptime = 0.0; s = solver->work[0]; r = solver->work[1]; z = solver->work[2]; v = &solver->work[3]; LIS_QUAD_SCALAR_MALLOC(aa,0,1); LIS_QUAD_SCALAR_MALLOC(bb,1,1); LIS_QUAD_SCALAR_MALLOC(rr,2,1); LIS_QUAD_SCALAR_MALLOC(a2,3,1); LIS_QUAD_SCALAR_MALLOC(b2,4,1); LIS_QUAD_SCALAR_MALLOC(t,5,1); LIS_QUAD_SCALAR_MALLOC(tmp,6,1); LIS_QUAD_SCALAR_MALLOC(one,7,1); LIS_QUAD_SCALAR_MALLOC(rnorm,8,1); h = (LIS_QUAD *)lis_malloc( sizeof(LIS_QUAD)*(h_dim+1)*(h_dim+2),"lis_gmres_switch::h" ); hd = (LIS_SCALAR *)h; cs = (m+1)*h_dim; sn = (m+2)*h_dim; one.hi[0] = 1.0; one.lo[0] = 0.0; z->precision = LIS_PRECISION_DEFAULT; /* r = M^-1 * (b - A * x) */ lis_matvec(A,x,z); lis_vector_xpay(b,-1.0,z); lis_psolve(solver,z,v[0]); /* Initial Residual */ if( lis_solver_get_initial_residual(solver,NULL,NULL,v[0],&bnrm2) ) { lis_free(h); LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } tol2 = solver->tol_switch; iter=0; while( iter<maxiter2 ) { /* first column of V */ /* v = r / ||r||_2 */ lis_vector_nrm2(v[0],&rnorm.hi[0]); lis_vector_scale(1.0/rnorm.hi[0],v[0]); /* s = ||r||_2 e_1 */ lis_vector_set_all(0,s); s->value[0] = rnorm.hi[0]; i = 0; do { iter++; i++; ii = i-1; i1 = i; iiv = i-1; i1v = i; iih = (i-1)*h_dim; /* z = M^-1 * v */ time = lis_wtime(); lis_psolve(solver,v[iiv],z); ptime += lis_wtime()-time; /* w = A * z */ lis_matvec(A,z, v[i1v]); for(k=0;k<i;k++) { /* h[k,i] = <w,v[k]> */ /* w = w - h[k,i] * v[k] */ lis_vector_dot(v[i1v],v[k],&t.hi[0]); hd[k+iih] = t.hi[0]; lis_vector_axpy(-t.hi[0],v[k],v[i1v]); } /* h[i+1,i] = ||w|| */ /* v[i+1] = w / h[i+1,i] */ lis_vector_nrm2(v[i1v],&t.hi[0]); hd[i1+iih] = t.hi[0]; lis_vector_scale(1.0/t.hi[0],v[i1v]); for(k=1;k<=ii;k++) { jj = k-1; t.hi[0] = hd[jj+iih]; aa.hi[0] = hd[jj+cs]*t.hi[0]; aa.hi[0] += hd[jj+sn]*hd[k+iih]; bb.hi[0] = -hd[jj+sn]*t.hi[0]; bb.hi[0] += hd[jj+cs]*hd[k+iih]; hd[jj+iih] = aa.hi[0]; hd[k+iih] = bb.hi[0]; } aa.hi[0] = hd[ii+iih]; bb.hi[0] = hd[i1+iih]; a2.hi[0] = aa.hi[0]*aa.hi[0]; b2.hi[0] = bb.hi[0]*bb.hi[0]; rr.hi[0] = sqrt(a2.hi[0]+b2.hi[0]); if( rr.hi[0]==0.0 ) rr.hi[0]=1.0e-17; hd[ii+cs] = aa.hi[0]/rr.hi[0]; hd[ii+sn] = bb.hi[0]/rr.hi[0]; s->value[i1] = -hd[ii+sn]*s->value[ii]; s->value[ii] = hd[ii+cs]*s->value[ii]; aa.hi[0] = hd[ii+cs]*hd[ii+iih]; aa.hi[0] += hd[ii+sn]*hd[i1+iih]; hd[ii+iih] = aa.hi[0]; /* convergence check */ nrm2 = fabs(s->value[i1])*bnrm2; if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol2 >= nrm2 ) break; } while( i<m && iter <maxiter2 ); /* Solve H * Y = S for upper Hessenberg matrix H */ s->value[ii] = s->value[ii]/hd[ii+iih]; for(k=1;k<=ii;k++) { jj = ii-k; t.hi[0] = s->value[jj]; for(j=jj+1;j<=ii;j++) { t.hi[0] -= hd[jj+j*h_dim]*s->value[j]; } s->value[jj] = t.hi[0]/hd[jj+jj*h_dim]; } /* z = z + y * v */ for(k=0;k<n;k++) { z->value[k] = s->value[0]*v[0]->value[k]; } for(j=1;j<=ii;j++) { lis_vector_axpy(s->value[j],v[j],z); } /* r = M^-1 * z */ time = lis_wtime(); lis_psolve(solver,z,r); ptime += lis_wtime()-time; /* x = x + r */ lis_vector_axpy(1,r,x); if( tol2 >= nrm2 ) { solver->iter = iter; solver->iter2 = iter; solver->ptime = ptime; break; } for(j=1;j<=i;j++) { jj = i1-j+1; s->value[jj-1] = -hd[jj-1+sn]*s->value[jj]; s->value[jj] = hd[jj-1+cs]*s->value[jj]; } for(j=0;j<=i1;j++) { t.hi[0] = s->value[j]; if( j==0 ) t.hi[0] = t.hi[0]-1.0; lis_vector_axpy(t.hi[0],v[j],v[0]); } } /* Initial Residual */ z->precision = LIS_PRECISION_QUAD; solver->options[LIS_OPTIONS_INITGUESS_ZEROS] = LIS_FALSE; lis_vector_copyex_mn(x,solver->xx); lis_solver_get_initial_residual(solver,NULL,NULL,v[0],&bnrm2); tol = solver->tol; iter2=iter; while( iter2<maxiter ) { /* first column of V */ /* v = r / ||r||_2 */ lis_vector_nrm2ex_mm(v[0],&rnorm); lis_quad_div((LIS_QUAD *)tmp.hi,(LIS_QUAD *)one.hi,(LIS_QUAD *)rnorm.hi); lis_vector_scaleex_mm(tmp,v[0]); /* s = ||r||_2 e_1 */ lis_vector_set_allex_nm(0.0,s); s->value[0] = rnorm.hi[0]; s->value_lo[0] = rnorm.lo[0]; i = 0; do { iter2++; i++; ii = i-1; i1 = i; iiv = i-1; i1v = i; iih = (i-1)*h_dim; /* z = M^-1 * v */ time = lis_wtime(); lis_psolve(solver,v[iiv],z); ptime += lis_wtime()-time; /* w = A * z */ lis_matvec(A,z, v[i1v]); for(k=0;k<i;k++) { /* h[k,i] = <w,v[k]> */ /* w = w - h[k,i] * v[k] */ lis_vector_dotex_mmm(v[i1v],v[k],&t); h[k+iih].hi = t.hi[0]; h[k+iih].lo = t.lo[0]; lis_quad_minus((LIS_QUAD *)t.hi); lis_vector_axpyex_mmm(t,v[k],v[i1v]); } /* h[i+1,i] = ||w|| */ /* v[i+1] = w / h[i+1,i] */ lis_vector_nrm2ex_mm(v[i1v],&t); h[i1+iih].hi = t.hi[0]; h[i1+iih].lo = t.lo[0]; lis_quad_div((LIS_QUAD *)tmp.hi,(LIS_QUAD *)one.hi,(LIS_QUAD *)t.hi); lis_vector_scaleex_mm(tmp,v[i1v]); for(k=1;k<=ii;k++) { jj = k-1; t.hi[0] = h[jj+iih].hi; t.lo[0] = h[jj+iih].lo; lis_quad_mul((LIS_QUAD *)aa.hi,(LIS_QUAD *)&h[jj+cs],(LIS_QUAD *)t.hi); lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[jj+sn],(LIS_QUAD *)&h[k+iih]); lis_quad_add((LIS_QUAD *)aa.hi,(LIS_QUAD *)aa.hi,(LIS_QUAD *)tmp.hi); lis_quad_mul((LIS_QUAD *)bb.hi,(LIS_QUAD *)&h[jj+sn],(LIS_QUAD *)t.hi); lis_quad_minus((LIS_QUAD *)bb.hi); lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[jj+cs],(LIS_QUAD *)&h[k+iih]); lis_quad_add((LIS_QUAD *)bb.hi,(LIS_QUAD *)bb.hi,(LIS_QUAD *)tmp.hi); h[jj+iih].hi = aa.hi[0]; h[jj+iih].lo = aa.lo[0]; h[k+iih].hi = bb.hi[0]; h[k+iih].lo = bb.lo[0]; } aa.hi[0] = h[ii+iih].hi; aa.lo[0] = h[ii+iih].lo; bb.hi[0] = h[i1+iih].hi; bb.lo[0] = h[i1+iih].lo; lis_quad_sqr((LIS_QUAD *)a2.hi,(LIS_QUAD *)aa.hi); lis_quad_sqr((LIS_QUAD *)b2.hi,(LIS_QUAD *)bb.hi); lis_quad_add((LIS_QUAD *)rr.hi,(LIS_QUAD *)a2.hi,(LIS_QUAD *)b2.hi); lis_quad_sqrt((LIS_QUAD *)rr.hi,(LIS_QUAD *)rr.hi); lis_quad_div((LIS_QUAD *)&h[ii+cs],(LIS_QUAD *)aa.hi,(LIS_QUAD *)rr.hi); lis_quad_div((LIS_QUAD *)&h[ii+sn],(LIS_QUAD *)bb.hi,(LIS_QUAD *)rr.hi); tmp.hi[0] = s->value[ii]; tmp.lo[0] = s->value_lo[ii]; lis_quad_mul((LIS_QUAD *)aa.hi,(LIS_QUAD *)&h[ii+sn],(LIS_QUAD *)tmp.hi); lis_quad_mul((LIS_QUAD *)bb.hi,(LIS_QUAD *)&h[ii+cs],(LIS_QUAD *)tmp.hi); lis_quad_minus((LIS_QUAD *)aa.hi); s->value[i1] = aa.hi[0]; s->value_lo[i1] = aa.lo[0]; s->value[ii] = bb.hi[0]; s->value_lo[ii] = bb.lo[0]; lis_quad_mul((LIS_QUAD *)aa.hi,(LIS_QUAD *)&h[ii+cs],(LIS_QUAD *)&h[ii+iih]); lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[ii+sn],(LIS_QUAD *)&h[i1+iih]); lis_quad_add((LIS_QUAD *)aa.hi,(LIS_QUAD *)aa.hi,(LIS_QUAD *)tmp.hi); h[ii+iih].hi = aa.hi[0]; h[ii+iih].lo = aa.lo[0]; /* convergence check */ nrm2 = fabs(s->value[i1])*bnrm2; if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter2] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol >= nrm2 ) break; } while( i<m && iter2 <maxiter ); /* Solve H * Y = S for upper Hessenberg matrix H */ tmp.hi[0] = s->value[ii]; tmp.lo[0] = s->value_lo[ii]; lis_quad_div((LIS_QUAD *)tmp.hi,(LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[ii+iih]); s->value[ii] = tmp.hi[0]; s->value_lo[ii] = tmp.lo[0]; for(k=1;k<=ii;k++) { jj = ii-k; t.hi[0] = s->value[jj]; t.lo[0] = s->value_lo[jj]; for(j=jj+1;j<=ii;j++) { tmp.hi[0] = s->value[j]; tmp.lo[0] = s->value_lo[j]; lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[jj+j*h_dim]); lis_quad_sub((LIS_QUAD *)t.hi,(LIS_QUAD *)t.hi,(LIS_QUAD *)tmp.hi); } lis_quad_div((LIS_QUAD *)tmp.hi,(LIS_QUAD *)t.hi,(LIS_QUAD *)&h[jj+jj*h_dim]); s->value[jj] = tmp.hi[0]; s->value_lo[jj] = tmp.lo[0]; } /* z = z + y * v */ for(k=0;k<n;k++) { aa.hi[0] = s->value[0]; aa.lo[0] = s->value_lo[0]; bb.hi[0] = v[0]->value[k]; bb.lo[0] = v[0]->value_lo[k]; lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)aa.hi,(LIS_QUAD *)bb.hi); z->value[k] = tmp.hi[0]; z->value_lo[k] = tmp.lo[0]; } for(j=1;j<=ii;j++) { aa.hi[0] = s->value[j]; aa.lo[0] = s->value_lo[j]; lis_vector_axpyex_mmm(aa,v[j],z); } /* r = M^-1 * z */ time = lis_wtime(); lis_psolve(solver,z,r); ptime += lis_wtime()-time; /* x = x + r */ lis_vector_axpyex_mmm(one,r,x); if( tol >= nrm2 ) { solver->retcode = LIS_SUCCESS; solver->iter = iter2; solver->iter2 = iter; solver->resid = nrm2; solver->ptime = ptime; lis_free(h); LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } for(j=1;j<=i;j++) { jj = i1-j+1; tmp.hi[0] = s->value[jj]; tmp.lo[0] = s->value_lo[jj]; lis_quad_mul((LIS_QUAD *)aa.hi,(LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[jj-1+sn]); lis_quad_mul((LIS_QUAD *)bb.hi,(LIS_QUAD *)tmp.hi,(LIS_QUAD *)&h[jj-1+cs]); lis_quad_minus((LIS_QUAD *)aa.hi); s->value[jj-1] = aa.hi[0]; s->value_lo[jj-1] = aa.lo[0]; s->value[jj] = bb.hi[0]; s->value_lo[jj] = bb.lo[0]; } for(j=0;j<=i1;j++) { t.hi[0] = s->value[j]; t.lo[0] = s->value_lo[j]; if( j==0 ) { lis_quad_sub((LIS_QUAD *)t.hi,(LIS_QUAD *)t.hi,(LIS_QUAD *)one.hi); } lis_vector_axpyex_mmm(t,v[j],v[0]); } } solver->retcode = LIS_MAXITER; solver->iter = iter2+1; solver->iter2 = iter; solver->resid = nrm2; lis_free(h); LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT main(LIS_INT argc, char* argv[]) { LIS_MATRIX A,A0; LIS_VECTOR b,x; LIS_INT nprocs,my_rank; int int_nprocs,int_my_rank; LIS_INT nthreads, maxthreads; LIS_INT nnz; LIS_INT i,n,np; LIS_INT block; LIS_INT is,ie; LIS_INT err,iter,matrix_type; double time,time2,nnzs,nnzap,nnzt; LIS_SCALAR val; double commtime,comptime,flops; char path[1024]; FILE *file; LIS_DEBUG_FUNC_IN; lis_initialize(&argc, &argv); #ifdef USE_MPI MPI_Comm_size(MPI_COMM_WORLD,&int_nprocs); MPI_Comm_rank(MPI_COMM_WORLD,&int_my_rank); nprocs = int_nprocs; my_rank = int_my_rank; #else nprocs = 1; my_rank = 0; #endif if( argc < 3 ) { if( my_rank==0 ) { printf("Usage: %s matrix_filename_list iter [block] \n", argv[0]); } lis_finalize(); exit(0); } file = fopen(argv[1], "r"); if( file==NULL ) CHKERR(1); iter = atoi(argv[2]); if (argv[3] == NULL) { block = 2; } else { block = atoi(argv[3]); } if( iter<=0 ) { #ifdef _LONG__LONG printf("iter=%lld <= 0\n",iter); #else printf("iter=%d <= 0\n",iter); #endif CHKERR(1); } if( my_rank==0 ) { printf("\n"); #ifdef _LONG__LONG printf("number of processes = %lld\n",nprocs); #else printf("number of processes = %d\n",nprocs); #endif } #ifdef _OPENMP if( my_rank==0 ) { nthreads = omp_get_num_procs(); maxthreads = omp_get_max_threads(); #ifdef _LONG__LONG printf("max number of threads = %lld\n", nthreads); printf("number of threads = %lld\n", maxthreads); #else printf("max number of threads = %d\n", nthreads); printf("number of threads = %d\n", maxthreads); #endif } #else nthreads = 1; maxthreads = 1; #endif /* create matrix and vectors */ while( fscanf(file, "%s\n", path)==1 ) { if( my_rank==0 ) { printf("matrix_filename = %s\n", path); } lis_matrix_create(LIS_COMM_WORLD,&A0); err = lis_input(A0,NULL,NULL,path); if( err ) CHKERR(err); n = A0->n; nnz = A0->nnz; np = A0->np-n; #ifdef USE_MPI MPI_Allreduce(&nnz,&i,1,LIS_MPI_INT,MPI_SUM,A0->comm); nnzap = (double)i / (double)nprocs; nnzt = ((double)nnz -nnzap)*((double)nnz -nnzap); nnz = i; MPI_Allreduce(&nnzt,&nnzs,1,MPI_DOUBLE,MPI_SUM,A0->comm); nnzs = (nnzs / (double)nprocs)/nnzap; MPI_Allreduce(&np,&i,1,LIS_MPI_INT,MPI_SUM,A0->comm); np = i; #endif if( my_rank==0 ) { #ifdef _LONG__LONG printf("block size of BSR and BSC = %lld x %lld\n",block,block); printf("number of iterations = %lld\n\n",iter); #else printf("block size of BSR and BSC = %d x %d\n",block,block); printf("number of iterations = %d\n\n",iter); #endif } err = lis_vector_duplicate(A0,&x); if( err ) CHKERR(err); err = lis_vector_duplicate(A0,&b); if( err ) CHKERR(err); lis_matrix_get_range(A0,&is,&ie); for(i=0;i<n;i++) { err = lis_vector_set_value(LIS_INS_VALUE,i+is,1.0,x); } /* MPI version of VBR is not implemented. DNS is also excluded to reduce memory usage. */ for (matrix_type=1;matrix_type<11;matrix_type++) { if ( nprocs>1 && matrix_type==9 ) continue; lis_matrix_duplicate(A0,&A); lis_matrix_set_type(A,matrix_type); err = lis_matrix_convert(A0,A); if( err ) CHKERR(err); if( my_rank==0 ) { if( A->matrix_type==LIS_MATRIX_BSR || A->matrix_type==LIS_MATRIX_BSC ) { A->bnr = block; A->bnc = block; } } comptime = 0.0; commtime = 0.0; for(i=0;i<iter;i++) { #ifdef USE_MPI MPI_Barrier(A->comm); time = lis_wtime(); lis_send_recv(A->commtable,x->value); commtime += lis_wtime() - time; #endif time2 = lis_wtime(); lis_matvec(A,x,b); comptime += lis_wtime() - time2; } lis_vector_nrm2(b,&val); if( my_rank==0 ) { flops = 2.0*nnz*iter*1.0e-6 / comptime; #ifdef USE_MPI #ifdef _LONG__DOUBLE #ifdef _LONG__LONG printf("matrix_type = %2lld (%s), computation = %e sec, %8.3f MFLOPS, communication = %e sec, communication/computation = %3.3f %%, 2-norm = %Le\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,commtime,commtime/comptime*100,val); #else printf("matrix_type = %2d (%s), computation = %e sec, %8.3f MFLOPS, communication = %e sec, communication/computation = %3.3f %%, 2-norm = %Le\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,commtime,commtime/comptime*100,val); #endif #else #ifdef _LONG__LONG printf("matrix_type = %2lld (%s), computation = %e sec, %8.3f MFLOPS, communication = %e sec, communication/computation = %3.3f %%, 2-norm = %e\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,commtime,commtime/comptime*100,val); #else printf("matrix_type = %2d (%s), computation = %e sec, %8.3f MFLOPS, communication = %e sec, communication/computation = %3.3f %%, 2-norm = %e\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,commtime,commtime/comptime*100,val); #endif #endif #else #ifdef _LONG__DOUBLE #ifdef _LONG__LONG printf("matrix_type = %2lld (%s), computation = %e sec, %8.3f MFLOPS, 2-norm = %Le\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,val); #else printf("matrix_type = %2d (%s), computation = %e sec, %8.3f MFLOPS, 2-norm = %Le\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,val); #endif #else #ifdef _LONG__LONG printf("matrix_type = %2lld (%s), computation = %e sec, %8.3f MFLOPS, 2-norm = %e\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,val); #else printf("matrix_type = %2d (%s), computation = %e sec, %8.3f MFLOPS, 2-norm = %e\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,val); #endif #endif #endif } lis_matrix_destroy(A); } lis_matrix_destroy(A0); lis_vector_destroy(b); lis_vector_destroy(x); } fclose(file); lis_finalize(); LIS_DEBUG_FUNC_OUT; return 0; }
LIS_INT lis_ecr(LIS_ESOLVER esolver) { LIS_MATRIX A; LIS_VECTOR x; LIS_SCALAR evalue; LIS_INT emaxiter; LIS_REAL tol; LIS_INT iter,i,j,output; LIS_INT nprocs,my_rank; LIS_REAL nrm2,resid; LIS_SCALAR lshift; LIS_VECTOR r,p,Ax,Ar,Ap; LIS_SCALAR alpha, beta; LIS_SCALAR rAp, rp, ApAp, pAp, pp, ArAp, pAr; double times,itimes,ptimes,p_c_times,p_i_times; A = esolver->A; x = esolver->x; emaxiter = esolver->options[LIS_EOPTIONS_MAXITER]; tol = esolver->params[LIS_EPARAMS_RESID - LIS_EOPTIONS_LEN]; output = esolver->options[LIS_EOPTIONS_OUTPUT]; lshift = esolver->lshift; if( A->my_rank==0 ) printf("local shift = %e\n", lshift); if (lshift != 0) lis_matrix_shift_diagonal(A, lshift); r = esolver->work[0]; p = esolver->work[1]; Ax = esolver->work[2]; Ar = esolver->work[3]; Ap = esolver->work[4]; lis_vector_set_all(1.0,x); lis_vector_nrm2(x,&nrm2); lis_vector_scale(1/nrm2,x); lis_matvec(A,x,Ax); lis_vector_dot(x,Ax,&evalue); lis_vector_axpyz(-evalue,x,Ax,r); lis_vector_scale(-1.0,r); lis_vector_copy(r,p); lis_matvec(A,p,Ap); iter=0; while (iter<emaxiter) { iter = iter + 1; lis_vector_dot(r,Ap,&rAp); lis_vector_dot(r,p,&rp); lis_vector_dot(Ap,Ap,&ApAp); lis_vector_dot(p,Ap,&pAp); lis_vector_dot(p,p,&pp); alpha = (rAp - evalue * rp) / (ApAp - evalue * (2.0 * pAp - evalue * pp)); lis_vector_axpy(alpha,p,x); lis_matvec(A,x,Ax); lis_vector_dot(x,Ax,&evalue); lis_vector_nrm2(x, &nrm2); evalue = evalue / (nrm2 * nrm2); lis_vector_axpyz(-evalue,x,Ax,r); lis_vector_scale(-1.0,r); lis_matvec(A,r,Ar); lis_vector_dot(Ar,Ap,&ArAp); lis_vector_dot(p,Ar,&pAr); lis_vector_dot(r,Ap,&rAp); lis_vector_dot(r,p,&rp); beta = - (ArAp - evalue * ((pAr + rAp) - evalue * rp))/ (ApAp - evalue * (2.0 * pAp - evalue * pp)); lis_vector_xpay(r,beta,p); lis_vector_nrm2(r,&nrm2); resid = fabs(nrm2 / (evalue)); if( output ) { if( output & LIS_EPRINT_MEM ) esolver->residual[iter] = resid; if( output & LIS_EPRINT_OUT && A->my_rank==0 ) printf("iter: %5d residual = %e\n", iter, resid); } if (resid<tol) break; } esolver->iter = iter; esolver->resid = resid; esolver->evalue[0] = evalue; if (lshift != 0) lis_matrix_shift_diagonal(A, -lshift); if (resid<tol) { esolver->retcode = LIS_SUCCESS; return LIS_SUCCESS; } else { esolver->retcode = LIS_MAXITER; return LIS_MAXITER; } }
LIS_INT lis_epi(LIS_ESOLVER esolver) { LIS_Comm comm; LIS_MATRIX A; LIS_VECTOR v,y,q; LIS_SCALAR theta; LIS_INT emaxiter; LIS_REAL tol; LIS_INT iter,output; LIS_SCALAR oshift,ishift; LIS_REAL nrm2,resid; LIS_DEBUG_FUNC_IN; comm = LIS_COMM_WORLD; emaxiter = esolver->options[LIS_EOPTIONS_MAXITER]; tol = esolver->params[LIS_EPARAMS_RESID - LIS_EOPTIONS_LEN]; output = esolver->options[LIS_EOPTIONS_OUTPUT]; #ifdef _COMPLEX oshift = esolver->params[LIS_EPARAMS_SHIFT - LIS_EOPTIONS_LEN] + esolver->params[LIS_EPARAMS_SHIFT_IM - LIS_EOPTIONS_LEN] * _Complex_I; #else oshift = esolver->params[LIS_EPARAMS_SHIFT - LIS_EOPTIONS_LEN]; #endif A = esolver->A; v = esolver->x; if (esolver->options[LIS_EOPTIONS_INITGUESS_ONES] ) { lis_vector_set_all(1.0,v); } y = esolver->work[0]; q = esolver->work[1]; if ( esolver->ishift != 0.0 ) oshift = ishift; if ( oshift != 0.0 ) lis_matrix_shift_diagonal(A, oshift); if( output ) { #ifdef _COMPLEX lis_printf(comm,"shift : (%e, %e)\n", (double)creal(oshift), (double)cimag(oshift)); #else lis_printf(comm,"shift : %e\n", (double)oshift); #endif } iter=0; while (iter<emaxiter) { iter = iter+1; /* v = v / ||v||_2 */ lis_vector_nrm2(v, &nrm2); lis_vector_scale(1.0/nrm2, v); /* y = A * v */ lis_matvec(A,v,y); /* theta = <v,y> */ lis_vector_dot(v, y, &theta); /* resid = ||y - theta * v||_2 / |theta| */ lis_vector_axpyz(-theta, v, y, q); lis_vector_nrm2(q, &resid); resid = resid / fabs(theta); /* v = y */ lis_vector_copy(y, v); /* convergence check */ if( output ) { if( output & LIS_EPRINT_MEM ) esolver->rhistory[iter] = resid; if( output & LIS_EPRINT_OUT ) lis_print_rhistory(comm,iter,resid); } if( tol >= resid ) { esolver->retcode = LIS_SUCCESS; esolver->iter[0] = iter; esolver->resid[0] = resid; esolver->evalue[0] = theta + oshift; lis_vector_nrm2(v, &nrm2); lis_vector_scale(1.0/nrm2, v); if ( oshift != 0.0 ) lis_matrix_shift_diagonal(A, -oshift); LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } } esolver->retcode = LIS_MAXITER; esolver->iter[0] = iter; esolver->resid[0] = resid; esolver->evalue[0] = theta + oshift; lis_vector_nrm2(v, &nrm2); lis_vector_scale(1.0/nrm2, v); if ( oshift != 0.0 ) lis_matrix_shift_diagonal(A, -oshift); LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_egpi(LIS_ESOLVER esolver) { LIS_Comm comm; LIS_MATRIX A,B; LIS_VECTOR w,v,y,q; LIS_SCALAR eta,theta; LIS_INT emaxiter; LIS_REAL tol; LIS_INT iter,iter2,output; LIS_SCALAR oshift,ishift; LIS_REAL nrm2,resid; LIS_SOLVER solver; double time,itime,ptime,p_c_time,p_i_time; LIS_INT err; LIS_PRECON precon; LIS_INT nsol, precon_type; char solvername[128], preconname[128]; LIS_DEBUG_FUNC_IN; comm = LIS_COMM_WORLD; emaxiter = esolver->options[LIS_EOPTIONS_MAXITER]; tol = esolver->params[LIS_EPARAMS_RESID - LIS_EOPTIONS_LEN]; output = esolver->options[LIS_EOPTIONS_OUTPUT]; #ifdef _COMPLEX oshift = esolver->params[LIS_EPARAMS_SHIFT - LIS_EOPTIONS_LEN] + esolver->params[LIS_EPARAMS_SHIFT_IM - LIS_EOPTIONS_LEN] * _Complex_I; #else oshift = esolver->params[LIS_EPARAMS_SHIFT - LIS_EOPTIONS_LEN]; #endif A = esolver->A; B = esolver->B; v = esolver->x; if (esolver->options[LIS_EOPTIONS_INITGUESS_ONES] ) { lis_vector_set_all(1.0,v); } w = esolver->work[0]; y = esolver->work[1]; q = esolver->work[2]; if ( esolver->ishift != 0.0 ) oshift = ishift; if ( oshift != 0.0 ) lis_matrix_shift_matrix(A, B, oshift); if( output ) { #ifdef _COMPLEX lis_printf(comm,"shift : (%e, %e)\n", (double)creal(oshift), (double)cimag(oshift)); #else lis_printf(comm,"shift : %e\n", (double)oshift); #endif } lis_solver_create(&solver); lis_solver_set_option("-i bicg -p none",solver); err = lis_solver_set_optionC(solver); CHKERR(err); lis_solver_get_solver(solver, &nsol); lis_solver_get_precon(solver, &precon_type); lis_solver_get_solvername(nsol, solvername); lis_solver_get_preconname(precon_type, preconname); if( output ) { lis_printf(comm,"linear solver : %s\n", solvername); lis_printf(comm,"preconditioner : %s\n", preconname); } /* create preconditioner */ solver->A = B; err = lis_precon_create(solver, &precon); if( err ) { lis_solver_work_destroy(solver); solver->retcode = err; return err; } iter=0; while (iter<emaxiter) { iter = iter+1; /* v = v / ||v||_2 */ lis_vector_nrm2(v, &nrm2); lis_vector_scale(1.0/nrm2, v); /* w = A * v */ lis_matvec(A, v, w); /* v = v / <v,w>^1/2, w = w / <v,w>^1/2 */ lis_vector_dot(v, w, &eta); eta = sqrt(eta); lis_vector_scale(1.0/eta, v); lis_vector_scale(1.0/eta, w); /* y = B^-1 * w */ err = lis_solve_kernel(B, w, y, solver, precon); if( err ) { lis_solver_work_destroy(solver); solver->retcode = err; return err; } lis_solver_get_iter(solver, &iter2); /* theta = <w,y> */ lis_vector_dot(w, y, &theta); /* resid = ||y - theta * v||_2 / |theta| */ lis_vector_axpyz(-theta, v, y, q); lis_vector_nrm2(q, &resid); resid = resid / fabs(theta); /* v = y */ lis_vector_copy(y, v); /* convergence check */ lis_solver_get_timeex(solver,&time,&itime,&ptime,&p_c_time,&p_i_time); esolver->ptime += solver->ptime; esolver->itime += solver->itime; esolver->p_c_time += solver->p_c_time; esolver->p_i_time += solver->p_i_time; if( output ) { if( output & LIS_EPRINT_MEM ) esolver->rhistory[iter] = resid; if( output & LIS_EPRINT_OUT ) lis_print_rhistory(comm,iter,resid); } if( tol >= resid ) { esolver->retcode = LIS_SUCCESS; esolver->iter[0] = iter; esolver->resid[0] = resid; esolver->evalue[0] = theta + oshift; lis_vector_nrm2(v, &nrm2); lis_vector_scale(1.0/nrm2, v); if ( oshift != 0.0 ) lis_matrix_shift_matrix(A, B, -oshift); lis_precon_destroy(precon); lis_solver_destroy(solver); LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } } lis_precon_destroy(precon); esolver->retcode = LIS_MAXITER; esolver->iter[0] = iter; esolver->resid[0] = resid; esolver->evalue[0] = theta + oshift; lis_vector_nrm2(v, &nrm2); lis_vector_scale(1.0/nrm2, v); if ( oshift != 0.0 ) lis_matrix_shift_matrix(A, B, -oshift); lis_solver_destroy(solver); LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_bicgsafe_switch(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR x; LIS_VECTOR r, rtld, rhat, p, ptld, phat; LIS_VECTOR t, ttld, that, t0, t0hat; LIS_VECTOR y, w, u, z; LIS_QUAD_PTR alpha, beta, rho, rho_old; LIS_QUAD_PTR qsi, eta, one; LIS_QUAD_PTR tmp, tmpdot[5]; LIS_REAL bnrm2, nrm2, tol, tol2; LIS_INT iter,maxiter,output,conv; LIS_INT iter2,maxiter2; double time,ptime; LIS_DEBUG_FUNC_IN; A = solver->A; x = solver->x; maxiter = solver->options[LIS_OPTIONS_MAXITER]; maxiter2 = solver->options[LIS_OPTIONS_SWITCH_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; conv = solver->options[LIS_OPTIONS_CONV_COND]; tol = solver->params[LIS_PARAMS_RESID-LIS_OPTIONS_LEN]; tol2 = solver->params[LIS_PARAMS_SWITCH_RESID-LIS_OPTIONS_LEN]; ptime = 0.0; rtld = solver->work[0]; r = solver->work[1]; rhat = solver->work[2]; p = solver->work[3]; ptld = solver->work[4]; phat = solver->work[5]; t = solver->work[6]; ttld = solver->work[7]; that = solver->work[8]; t0 = solver->work[9]; t0hat = solver->work[10]; y = solver->work[11]; w = solver->work[12]; u = solver->work[13]; z = solver->work[14]; LIS_QUAD_SCALAR_MALLOC(alpha,0,1); LIS_QUAD_SCALAR_MALLOC(beta,1,1); LIS_QUAD_SCALAR_MALLOC(rho,2,1); LIS_QUAD_SCALAR_MALLOC(rho_old,3,1); LIS_QUAD_SCALAR_MALLOC(qsi,4,1); LIS_QUAD_SCALAR_MALLOC(eta,5,1); LIS_QUAD_SCALAR_MALLOC(tmp,6,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[0],7,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[1],8,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[2],9,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[3],10,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[4],11,1); LIS_QUAD_SCALAR_MALLOC(one,13,1); rho_old.hi[0] = 1.0; rho_old.lo[0] = 0.0; alpha.hi[0] = 1.0; alpha.lo[0] = 0.0; qsi.hi[0] = 1.0; qsi.lo[0] = 0.0; one.hi[0] = -1.0; one.lo[0] = 0.0; /* Initial Residual */ if( lis_solver_get_initial_residual(solver,NULL,NULL,r,&bnrm2) ) { LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } tol2 = solver->tol_switch; lis_solver_set_shadowresidual(solver,r,rtld); lis_vector_set_allex_nm(0.0, ttld); lis_vector_set_allex_nm(0.0, ptld); lis_vector_set_allex_nm(0.0, p); lis_vector_set_allex_nm(0.0, u); lis_vector_set_allex_nm(0.0, t); lis_vector_set_allex_nm(0.0, t0); for( iter=1; iter<=maxiter2; iter++ ) { /* rho = <rtld,r> */ lis_vector_dot(rtld,r,&rho.hi[0]); /* test breakdown */ if( rho.hi[0]==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter; solver->iter2 = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* beta = (rho / rho_old) * (alpha / qsi) */ beta.hi[0] = (rho.hi[0] / rho_old.hi[0]) * (alpha.hi[0] / qsi.hi[0]); /* w = ttld + beta*ptld */ lis_vector_axpyz(beta.hi[0],ptld,ttld,w); /* rhat = M^-1 * r */ time = lis_wtime(); lis_psolve(solver, r, rhat); ptime += lis_wtime()-time; /* p = rhat + beta*(p - u) */ lis_vector_axpy(-1,u,p); lis_vector_xpay(rhat,beta.hi[0],p); /* ptld = A * p */ lis_matvec(A,p,ptld); /* tmpdot[0] = <rtld,ptld> */ lis_vector_dot(rtld,ptld,&tmpdot[0].hi[0]); /* test breakdown */ /* */ /* alpha = rho / tmpdot[0] */ alpha.hi[0] = rho.hi[0] / tmpdot[0].hi[0]; /* y = t - r + alpha*(-w + ptld) */ lis_vector_axpyz(-1,w,ptld,y); lis_vector_xpay(t,alpha.hi[0],y); lis_vector_axpy(-1,r,y); /* t = r - alpha*ptld */ lis_vector_axpyz(-alpha.hi[0],ptld,r,t); /* that = M^-1 * t */ /* phat = M^-1 * ptld */ /* t0hat = M^-1 * t0 */ time = lis_wtime(); lis_psolve(solver, t, that); lis_psolve(solver, ptld, phat); lis_psolve(solver, t0, t0hat); ptime += lis_wtime()-time; /* ttld = A * that */ lis_matvec(A,that,ttld); /* tmpdot[0] = <y,y> */ /* tmpdot[1] = <ttld,t> */ /* tmpdot[2] = <y,t> */ /* tmpdot[3] = <ttld,y> */ /* tmpdot[4] = <ttld,ttld> */ lis_vector_dot(y,y,&tmpdot[0].hi[0]); lis_vector_dot(ttld,t,&tmpdot[1].hi[0]); lis_vector_dot(y,t,&tmpdot[2].hi[0]); lis_vector_dot(ttld,y,&tmpdot[3].hi[0]); lis_vector_dot(ttld,ttld,&tmpdot[4].hi[0]); if(iter==1) { qsi.hi[0] = tmpdot[1].hi[0] / tmpdot[4].hi[0]; eta.hi[0] = 0.0; } else { tmp.hi[0] = tmpdot[4].hi[0]*tmpdot[0].hi[0] - tmpdot[3].hi[0]*tmpdot[3].hi[0]; qsi.hi[0] = (tmpdot[0].hi[0]*tmpdot[1].hi[0] - tmpdot[2].hi[0]*tmpdot[3].hi[0]) / tmp.hi[0]; eta.hi[0] = (tmpdot[4].hi[0]*tmpdot[2].hi[0] - tmpdot[3].hi[0]*tmpdot[1].hi[0]) / tmp.hi[0]; } /* u = qsi*phat + eta*(t0hat - rhat + beta*u) */ lis_vector_xpay(t0hat,beta.hi[0],u); lis_vector_axpy(-1,rhat,u); lis_vector_scale(eta.hi[0],u); lis_vector_axpy(qsi.hi[0],phat,u); /* z = qsi*rhat + eta*z - alpha*u */ lis_vector_scale(eta.hi[0],z); lis_vector_axpy(qsi.hi[0],rhat,z); lis_vector_axpy(-alpha.hi[0],u,z); /* x = x + alpha*p + z */ lis_vector_axpy(alpha.hi[0],p,x); lis_vector_axpy(1,z,x); /* r = t - eta*y - qsi*ttld */ lis_vector_axpyz(-eta.hi[0],y,t,r); lis_vector_axpy(-qsi.hi[0],ttld,r); /* convergence check */ lis_solver_get_residual[conv](r,solver,&nrm2); if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol2 >= nrm2 ) { solver->iter = iter; solver->iter2 = iter; solver->ptime = ptime; break; } lis_vector_copy(t,t0); rho_old.hi[0] = rho.hi[0]; } r->precision = LIS_PRECISION_QUAD; p->precision = LIS_PRECISION_QUAD; t->precision = LIS_PRECISION_QUAD; t0->precision = LIS_PRECISION_QUAD; ptld->precision = LIS_PRECISION_QUAD; that->precision = LIS_PRECISION_QUAD; solver->options[LIS_OPTIONS_INITGUESS_ZEROS] = LIS_FALSE; lis_vector_copyex_mn(x,solver->xx); rho_old.hi[0] = 1.0; alpha.hi[0] = 1.0; qsi.hi[0] = 1.0; one.hi[0] = -1.0; /* Initial Residual */ lis_solver_get_initial_residual(solver,NULL,NULL,r,&bnrm2); tol = solver->tol; lis_solver_set_shadowresidual(solver,r,rtld); lis_vector_set_allex_nm(0.0, ttld); lis_vector_set_allex_nm(0.0, ptld); lis_vector_set_allex_nm(0.0, p); lis_vector_set_allex_nm(0.0, u); lis_vector_set_allex_nm(0.0, t); lis_vector_set_allex_nm(0.0, t0); for( iter2=iter+1; iter2<=maxiter; iter2++ ) { /* rho = <rtld,r> */ lis_vector_dotex_mmm(rtld,r,&rho); /* test breakdown */ if( rho.hi[0]==0.0 && rho.lo[0]==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter2; solver->iter2 = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* beta = (rho / rho_old) * (alpha / qsi) */ lis_quad_div((LIS_QUAD *)beta.hi,(LIS_QUAD *)rho.hi,(LIS_QUAD *)rho_old.hi); lis_quad_div((LIS_QUAD *)tmp.hi,(LIS_QUAD *)alpha.hi,(LIS_QUAD *)qsi.hi); lis_quad_mul((LIS_QUAD *)beta.hi,(LIS_QUAD *)beta.hi,(LIS_QUAD *)tmp.hi); /* w = ttld + beta*ptld */ lis_vector_axpyzex_mmmm(beta,ptld,ttld,w); /* rhat = M^-1 * r */ time = lis_wtime(); lis_psolve(solver, r, rhat); ptime += lis_wtime()-time; /* p = rhat + beta*(p - u) */ lis_vector_axpyex_mmm(one,u,p); lis_vector_xpayex_mmm(rhat,beta,p); /* ptld = A * p */ lis_matvec(A,p,ptld); /* tmpdot[0] = <rtld,ptld> */ lis_vector_dotex_mmm(rtld,ptld,&tmpdot[0]); /* test breakdown */ /* */ /* alpha = rho / tmpdot[0] */ lis_quad_div((LIS_QUAD *)alpha.hi,(LIS_QUAD *)rho.hi,(LIS_QUAD *)tmpdot[0].hi); /* y = t - r + alpha*(-w + ptld) */ lis_vector_axpyzex_mmmm(one,w,ptld,y); lis_vector_xpayex_mmm(t,alpha,y); lis_vector_axpyex_mmm(one,r,y); /* t = r - alpha*ptld */ lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyzex_mmmm(alpha,ptld,r,t); /* that = M^-1 * t */ /* phat = M^-1 * ptld */ /* t0hat = M^-1 * t0 */ time = lis_wtime(); lis_psolve(solver, t, that); lis_psolve(solver, ptld, phat); lis_psolve(solver, t0, t0hat); ptime += lis_wtime()-time; /* ttld = A * that */ lis_matvec(A,that,ttld); /* tmpdot[0] = <y,y> */ /* tmpdot[1] = <ttld,t> */ /* tmpdot[2] = <y,t> */ /* tmpdot[3] = <ttld,y> */ /* tmpdot[4] = <ttld,ttld> */ lis_vector_dotex_mmm(y,y,&tmpdot[0]); lis_vector_dotex_mmm(ttld,t,&tmpdot[1]); lis_vector_dotex_mmm(y,t,&tmpdot[2]); lis_vector_dotex_mmm(ttld,y,&tmpdot[3]); lis_vector_dotex_mmm(ttld,ttld,&tmpdot[4]); if(iter==1) { lis_quad_div((LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmpdot[1].hi,(LIS_QUAD *)tmpdot[4].hi); eta.hi[0] = 0.0; eta.lo[0] = 0.0; } else { lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)tmpdot[4].hi,(LIS_QUAD *)tmpdot[0].hi); lis_quad_sqr((LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmpdot[3].hi); lis_quad_sub((LIS_QUAD *)tmp.hi,(LIS_QUAD *)tmp.hi,(LIS_QUAD *)qsi.hi); lis_quad_mul((LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmpdot[0].hi,(LIS_QUAD *)tmpdot[1].hi); lis_quad_mul((LIS_QUAD *)eta.hi,(LIS_QUAD *)tmpdot[2].hi,(LIS_QUAD *)tmpdot[3].hi); lis_quad_sub((LIS_QUAD *)qsi.hi,(LIS_QUAD *)qsi.hi,(LIS_QUAD *)eta.hi); lis_quad_div((LIS_QUAD *)qsi.hi,(LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmp.hi); lis_quad_mul((LIS_QUAD *)eta.hi,(LIS_QUAD *)tmpdot[4].hi,(LIS_QUAD *)tmpdot[2].hi); lis_quad_mul((LIS_QUAD *)tmpdot[0].hi,(LIS_QUAD *)tmpdot[3].hi,(LIS_QUAD *)tmpdot[1].hi); lis_quad_sub((LIS_QUAD *)eta.hi,(LIS_QUAD *)eta.hi,(LIS_QUAD *)tmpdot[0].hi); lis_quad_div((LIS_QUAD *)eta.hi,(LIS_QUAD *)eta.hi,(LIS_QUAD *)tmp.hi); } /* u = qsi*phat + eta*(t0hat - rhat + beta*u) */ lis_vector_xpayex_mmm(t0hat,beta,u); lis_vector_axpyex_mmm(one,rhat,u); lis_vector_scaleex_mm(eta,u); lis_vector_axpyex_mmm(qsi,phat,u); /* z = qsi*rhat + eta*z - alpha*u */ lis_vector_scaleex_mm(eta,z); lis_vector_axpyex_mmm(qsi,rhat,z); lis_vector_axpyex_mmm(alpha,u,z); /* x = x + alpha*p + z */ lis_quad_minus((LIS_QUAD *)alpha.hi); lis_quad_minus((LIS_QUAD *)one.hi); lis_vector_axpyex_mmm(alpha,p,x); lis_vector_axpyex_mmm(one,z,x); lis_quad_minus((LIS_QUAD *)one.hi); /* r = t - eta*y - qsi*ttld */ lis_quad_minus((LIS_QUAD *)eta.hi); lis_quad_minus((LIS_QUAD *)qsi.hi); lis_vector_axpyzex_mmmm(eta,y,t,r); lis_vector_axpyex_mmm(qsi,ttld,r); lis_quad_minus((LIS_QUAD *)eta.hi); lis_quad_minus((LIS_QUAD *)qsi.hi); /* convergence check */ lis_solver_get_residual[conv](r,solver,&nrm2); if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter2] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol > nrm2 ) { solver->retcode = LIS_SUCCESS; solver->iter = iter2; solver->iter2 = iter; solver->resid = nrm2; solver->ptime = ptime; LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } lis_vector_copyex_mm(t,t0); rho_old.hi[0] = rho.hi[0]; rho_old.lo[0] = rho.lo[0]; } solver->retcode = LIS_MAXITER; solver->iter = iter; solver->iter2 = iter2; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_bicgsafe_quad(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR x; LIS_VECTOR r, rtld, rhat, p, ptld; LIS_VECTOR t, ttld; LIS_VECTOR y, v, u, utld, z; LIS_QUAD_PTR alpha, beta, rho, rho_old; LIS_QUAD_PTR qsi, eta; LIS_QUAD_PTR tmp, tmpdot[5],one; LIS_REAL bnrm2, nrm2, tol; LIS_INT iter,maxiter,output,conv; double time,ptime; LIS_DEBUG_FUNC_IN; A = solver->A; x = solver->x; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; conv = solver->options[LIS_OPTIONS_CONV_COND]; ptime = 0.0; rtld = solver->work[0]; r = solver->work[1]; rhat = solver->work[2]; p = solver->work[3]; ptld = solver->work[4]; t = solver->work[5]; ttld = solver->work[6]; y = solver->work[7]; v = solver->work[8]; u = solver->work[9]; z = solver->work[10]; utld = solver->work[11]; LIS_QUAD_SCALAR_MALLOC(alpha,0,1); LIS_QUAD_SCALAR_MALLOC(beta,1,1); LIS_QUAD_SCALAR_MALLOC(rho,2,1); LIS_QUAD_SCALAR_MALLOC(rho_old,3,1); LIS_QUAD_SCALAR_MALLOC(qsi,4,1); LIS_QUAD_SCALAR_MALLOC(eta,5,1); LIS_QUAD_SCALAR_MALLOC(tmp,6,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[0],7,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[1],8,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[2],9,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[3],10,1); LIS_QUAD_SCALAR_MALLOC(tmpdot[4],11,1); LIS_QUAD_SCALAR_MALLOC(one,13,1); rho_old.hi[0] = 1.0; rho_old.lo[0] = 0.0; alpha.hi[0] = 1.0; alpha.lo[0] = 0.0; qsi.hi[0] = 1.0; qsi.lo[0] = 0.0; one.hi[0] = -1.0; one.lo[0] = 0.0; /* Initial Residual */ if( lis_solver_get_initial_residual(solver,NULL,NULL,r,&bnrm2) ) { LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } tol = solver->tol; lis_solver_set_shadowresidual(solver,r,rtld); lis_vector_set_allex_nm(0.0,p); lis_vector_set_allex_nm(0.0,u); lis_vector_set_allex_nm(0.0,ptld); lis_vector_set_allex_nm(0.0,utld); for( iter=1; iter<=maxiter; iter++ ) { /* rho = <rtld,r> */ lis_vector_dotex_mmm(rtld,r,&rho); /* test breakdown */ if( rho.hi[0]==0.0 && rho.lo[0]==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* beta = (rho / rho_old) * (alpha / qsi) */ lis_quad_div((LIS_QUAD *)beta.hi,(LIS_QUAD *)rho.hi,(LIS_QUAD *)rho_old.hi); lis_quad_div((LIS_QUAD *)tmp.hi,(LIS_QUAD *)alpha.hi,(LIS_QUAD *)qsi.hi); lis_quad_mul((LIS_QUAD *)beta.hi,(LIS_QUAD *)beta.hi,(LIS_QUAD *)tmp.hi); /* rhat = M^-1 * r */ /* v = A * rhat */ time = lis_wtime(); lis_psolve(solver, r, rhat); ptime += lis_wtime()-time; lis_matvec(A,rhat,v); /* p = rhat + beta*(p - u) */ lis_vector_axpyex_mmm(one,u,p); lis_vector_xpayex_mmm(rhat,beta,p); /* ptld = v + beta*(ptld - utld) */ lis_vector_axpyex_mmm(one,utld,ptld); lis_vector_xpayex_mmm(v,beta,ptld); /* tmpdot[0] = <rtld,ptld> */ lis_vector_dotex_mmm(rtld,ptld,&tmpdot[0]); /* test breakdown */ /* */ /* alpha = rho / tmpdot[0] */ lis_quad_div((LIS_QUAD *)alpha.hi,(LIS_QUAD *)rho.hi,(LIS_QUAD *)tmpdot[0].hi); /* tmpdot[0] = <y,y> */ /* tmpdot[1] = <v,r> */ /* tmpdot[2] = <y,r> */ /* tmpdot[3] = <v,y> */ /* tmpdot[4] = <v,v> */ lis_vector_dotex_mmm(y,y,&tmpdot[0]); lis_vector_dotex_mmm(v,r,&tmpdot[1]); lis_vector_dotex_mmm(y,r,&tmpdot[2]); lis_vector_dotex_mmm(v,y,&tmpdot[3]); lis_vector_dotex_mmm(v,v,&tmpdot[4]); if(iter==1) { lis_quad_div((LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmpdot[1].hi,(LIS_QUAD *)tmpdot[4].hi); eta.hi[0] = 0.0; eta.lo[0] = 0.0; } else { lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)tmpdot[4].hi,(LIS_QUAD *)tmpdot[0].hi); lis_quad_sqr((LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmpdot[3].hi); lis_quad_sub((LIS_QUAD *)tmp.hi,(LIS_QUAD *)tmp.hi,(LIS_QUAD *)qsi.hi); lis_quad_mul((LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmpdot[0].hi,(LIS_QUAD *)tmpdot[1].hi); lis_quad_mul((LIS_QUAD *)eta.hi,(LIS_QUAD *)tmpdot[2].hi,(LIS_QUAD *)tmpdot[3].hi); lis_quad_sub((LIS_QUAD *)qsi.hi,(LIS_QUAD *)qsi.hi,(LIS_QUAD *)eta.hi); lis_quad_div((LIS_QUAD *)qsi.hi,(LIS_QUAD *)qsi.hi,(LIS_QUAD *)tmp.hi); lis_quad_mul((LIS_QUAD *)eta.hi,(LIS_QUAD *)tmpdot[4].hi,(LIS_QUAD *)tmpdot[2].hi); lis_quad_mul((LIS_QUAD *)tmpdot[0].hi,(LIS_QUAD *)tmpdot[3].hi,(LIS_QUAD *)tmpdot[1].hi); lis_quad_sub((LIS_QUAD *)eta.hi,(LIS_QUAD *)eta.hi,(LIS_QUAD *)tmpdot[0].hi); lis_quad_div((LIS_QUAD *)eta.hi,(LIS_QUAD *)eta.hi,(LIS_QUAD *)tmp.hi); } /* t = qsi*ptld + eta*y */ lis_vector_copyex_mm(y,t); lis_vector_scaleex_mm(eta,t); lis_vector_axpyex_mmm(qsi,ptld,t); /* ttld = M^-1 * t */ time = lis_wtime(); lis_psolve(solver, t, ttld); ptime += lis_wtime()-time; /* u = ttld + eta*beta*u */ /* utld = A * u */ lis_quad_mul((LIS_QUAD *)tmp.hi,(LIS_QUAD *)eta.hi,(LIS_QUAD *)beta.hi); lis_vector_xpayex_mmm(ttld,tmp,u); lis_matvec(A,u,utld); /* z = qsi*rhat + eta*z - alpha*u */ lis_vector_scaleex_mm(eta,z); lis_vector_axpyex_mmm(qsi,rhat,z); lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyex_mmm(alpha,u,z); /* y = qsi*v + eta*y - alpha*utld */ lis_vector_scaleex_mm(eta,y); lis_vector_axpyex_mmm(qsi,v,y); lis_vector_axpyex_mmm(alpha,utld,y); lis_quad_minus((LIS_QUAD *)alpha.hi); /* x = x + alpha*p + z */ lis_vector_axpyex_mmm(alpha,p,x); lis_quad_minus((LIS_QUAD *)one.hi); lis_vector_axpyex_mmm(one,z,x); lis_quad_minus((LIS_QUAD *)one.hi); /* r = r - alpha*ptld - y */ lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyex_mmm(alpha,ptld,r); lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyex_mmm(one,y,r); /* convergence check */ lis_solver_get_residual[conv](r,solver,&nrm2); if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol > nrm2 ) { solver->retcode = LIS_SUCCESS; solver->iter = iter; solver->resid = nrm2; solver->ptime = ptime; LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } rho_old.hi[0] = rho.hi[0]; rho_old.lo[0] = rho.lo[0]; } solver->retcode = LIS_MAXITER; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_bicgsafe(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR x; LIS_VECTOR r, rtld, mr, amr, t, mt, p, ap; LIS_VECTOR y, u, au, z; LIS_SCALAR alpha, beta; LIS_REAL rho, rho_old; LIS_SCALAR qsi, eta; LIS_SCALAR tmp, tmpdot[5]; LIS_REAL bnrm2, nrm2, tol; LIS_INT iter,maxiter,output,conv; double time,ptime; LIS_DEBUG_FUNC_IN; A = solver->A; x = solver->x; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; conv = solver->options[LIS_OPTIONS_CONV_COND]; ptime = 0.0; rtld = solver->work[0]; r = solver->work[1]; mr = solver->work[2]; amr = solver->work[3]; p = solver->work[4]; ap = solver->work[5]; t = solver->work[6]; mt = solver->work[7]; y = solver->work[8]; u = solver->work[9]; z = solver->work[10]; au = solver->work[11]; /* Initial Residual */ if( lis_solver_get_initial_residual(solver,NULL,NULL,r,&bnrm2) ) { LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } tol = solver->tol; lis_solver_set_shadowresidual(solver,r,rtld); time = lis_wtime(); lis_psolve(solver, r, mr); ptime += lis_wtime()-time; lis_matvec(A,mr,amr); lis_vector_dot(rtld,r,&rho_old); lis_vector_copy(amr,ap); lis_vector_copy(mr,p); beta = 0.0; for( iter=1; iter<=maxiter; iter++ ) { /* tmpdot[0] = <rtld,ap> */ /* alpha = rho_old / tmpdot[0] */ lis_vector_dot(rtld,ap,&tmpdot[0]); alpha = rho_old / tmpdot[0]; /* tmpdot[0] = <y,y> */ /* tmpdot[1] = <amr,r> */ /* tmpdot[2] = <y,r> */ /* tmpdot[3] = <amr,y> */ /* tmpdot[4] = <amr,amr> */ lis_vector_dot(y,y,&tmpdot[0]); lis_vector_dot(amr,r,&tmpdot[1]); lis_vector_dot(y,r,&tmpdot[2]); lis_vector_dot(amr,y,&tmpdot[3]); lis_vector_dot(amr,amr,&tmpdot[4]); if(iter==1) { qsi = tmpdot[1] / tmpdot[4]; eta = 0.0; } else { tmp = tmpdot[4]*tmpdot[0] - tmpdot[3]*tmpdot[3]; qsi = (tmpdot[0]*tmpdot[1] - tmpdot[2]*tmpdot[3]) / tmp; eta = (tmpdot[4]*tmpdot[2] - tmpdot[3]*tmpdot[1]) / tmp; } /* t = qsi*ap + eta*y */ lis_vector_copy(y,t); lis_vector_scale(eta,t); lis_vector_axpy(qsi,ap,t); /* mt = M^-1 * t */ time = lis_wtime(); lis_psolve(solver, t, mt); ptime += lis_wtime()-time; /* u = mt + eta*beta*u */ /* au = A * u */ lis_vector_xpay(mt,eta*beta,u); lis_matvec(A,u,au); /* z = qsi*mr + eta*z - alpha*u */ lis_vector_scale(eta,z); lis_vector_axpy(qsi,mr,z); lis_vector_axpy(-alpha,u,z); /* y = qsi*amr + eta*y - alpha*au */ lis_vector_scale(eta,y); lis_vector_axpy(qsi,amr,y); lis_vector_axpy(-alpha,au,y); /* x = x + alpha*p + z */ lis_vector_axpy(alpha,p,x); lis_vector_axpy(1.0,z,x); /* r = r - alpha*ap - y */ lis_vector_axpy(-alpha,ap,r); lis_vector_axpy(-1.0,y,r); /* convergence check */ lis_solver_get_residual[conv](r,solver,&nrm2); if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol >= nrm2 ) { solver->retcode = LIS_SUCCESS; solver->iter = iter; solver->resid = nrm2; solver->ptime = ptime; LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } /* rho = <rtld,r> */ lis_vector_dot(rtld,r,&rho); if( rho==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* beta = (rho / rho_old) * (alpha / qsi) */ beta = (rho / rho_old) * (alpha / qsi); /* mr = M^-1 * r */ /* amr = A * mr */ time = lis_wtime(); lis_psolve(solver, r, mr); ptime += lis_wtime()-time; lis_matvec(A,mr,amr); /* p = mr + beta*(p - u) */ /* ap = amr + beta*(ap - au) */ lis_vector_axpy(-1.0,u,p); lis_vector_xpay(mr,beta,p); lis_vector_axpy(-1.0,au,ap); lis_vector_xpay(amr,beta,ap); rho_old = rho; } solver->retcode = LIS_MAXITER; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_solver_get_initial_residual(LIS_SOLVER solver, LIS_PRECON M, LIS_VECTOR t, LIS_VECTOR r, LIS_SCALAR *bnrm2) { LIS_INT output,conv; #ifdef USE_QUAD_PRECISION LIS_INT i; #endif LIS_MATRIX A; LIS_VECTOR x,b,p,xx; LIS_SCALAR nrm2; LIS_REAL tol,tol_w,tol_switch; LIS_DEBUG_FUNC_IN; A = solver->A; b = solver->b; x = solver->x; xx = solver->xx; output = solver->options[LIS_OPTIONS_OUTPUT]; conv = solver->options[LIS_OPTIONS_CONV_COND]; tol = solver->params[LIS_PARAMS_RESID-LIS_OPTIONS_LEN]; tol_w = solver->params[LIS_PARAMS_RESID_WEIGHT-LIS_OPTIONS_LEN]; tol_switch = solver->params[LIS_PARAMS_SWITCH_RESID-LIS_OPTIONS_LEN]; /* Initial Residual */ if( M==NULL ) { p = r; } else { p = t; } if( !solver->options[LIS_OPTIONS_INITGUESS_ZEROS] ) { #ifndef USE_QUAD_PRECISION lis_matvec(A,x,p); /* p = Ax */ lis_vector_xpay(b,-1,p); /* p = b - p */ #else if( solver->precision==LIS_PRECISION_DOUBLE ) { lis_matvec(A,x,p); /* p = Ax */ lis_vector_xpay(b,-1,p); /* p = b - p */ } else { lis_matvec(A,xx,p); /* p = Ax */ lis_vector_xpay(b,-1,p); /* p = b - p */ #ifdef _OPENMP #pragma omp parallel for private(i) #endif for(i=0;i<A->n;i++) { p->value_lo[i] = 0.0; } } #endif } else { #ifndef USE_QUAD_PRECISION lis_vector_copy(b,p); #else if( solver->precision==LIS_PRECISION_DOUBLE ) { lis_vector_copy(b,p); } else { lis_vector_copyex_nm(b,p); } #endif } switch(conv) { case LIS_CONV_COND_NRM2_R: lis_vector_nrm2(p,&nrm2); *bnrm2 = nrm2; solver->tol = tol; solver->tol_switch = tol_switch; break; case LIS_CONV_COND_NRM2_B: lis_vector_nrm2(p,&nrm2); lis_vector_nrm2(b,bnrm2); solver->tol = tol; solver->tol_switch = tol_switch; break; case LIS_CONV_COND_NRM1_B: lis_vector_nrm1(p,&nrm2); lis_vector_nrm1(b,bnrm2); solver->tol = *bnrm2*tol_w + tol; solver->tol_switch = *bnrm2*tol_w + tol_switch; break; } if( *bnrm2 == 0.0 ) { *bnrm2 = 1.0; } else { *bnrm2 = 1.0 / *bnrm2; } solver->bnrm = *bnrm2; nrm2 = nrm2 * *bnrm2; if( output && (r->precision==LIS_PRECISION_QUAD && solver->precision!=LIS_PRECISION_SWITCH) ) { if( output & LIS_PRINT_MEM ) solver->residual[0] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) printf("iter: %5d residual = %e\n", 0, nrm2); } if( nrm2 <= solver->params[LIS_PARAMS_RESID-LIS_OPTIONS_LEN] ) { solver->retcode = LIS_SUCCESS; solver->iter = 1; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_FAILS; } if( M!=NULL ) { /* r = M^-1 * p */ lis_psolve(solver, p, r); } LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; }
LIS_INT lis_jacobi(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR b,x; LIS_VECTOR d,r,t,s; LIS_REAL bnrm2,nrm2,tol; LIS_INT iter,maxiter,output; double time,ptime; LIS_DEBUG_FUNC_IN; A = solver->A; b = solver->b; x = solver->x; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; tol = solver->params[LIS_PARAMS_RESID-LIS_OPTIONS_LEN]; ptime = 0.0; r = solver->work[0]; t = solver->work[1]; s = solver->work[2]; d = solver->work[3]; lis_vector_nrm2(b,&bnrm2); bnrm2 = 1.0 / bnrm2; lis_matrix_get_diagonal(A,d); lis_vector_reciprocal(d); for( iter=1; iter<=maxiter; iter++ ) { /* x += D^{-1}(b - Ax) */ time = lis_wtime(); lis_psolve(solver,x,s); ptime += lis_wtime() - time; lis_matvec(A,s,t); /* lis_matvec(A,x,t);*/ lis_vector_axpyz(-1,t,b,r); lis_vector_nrm2(r,&nrm2); lis_vector_pmul(r,d,r); lis_vector_axpy(1,r,x); /* convergence check */ nrm2 = nrm2 * bnrm2; if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol >= nrm2 ) { time = lis_wtime(); lis_psolve(solver,x,s); ptime += lis_wtime() - time; lis_vector_copy(s,x); solver->retcode = LIS_SUCCESS; solver->iter = iter; solver->resid = nrm2; solver->ptime = ptime; LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } } lis_psolve(solver,x,s); lis_vector_copy(s,x); solver->retcode = LIS_MAXITER; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT main(LIS_INT argc, char* argv[]) { LIS_MATRIX A0,A; LIS_VECTOR x,b,u; LIS_SOLVER solver; LIS_INT m,n,nn,nnz; LIS_INT i,j,ii,jj,ctr; LIS_INT is,ie; LIS_INT nprocs,my_rank; int int_nprocs,int_my_rank; LIS_INT nsol; LIS_INT err,iter,mtype,iter_double,iter_quad; double time,itime,ptime,p_c_time,p_i_time; LIS_REAL resid; char solvername[128]; LIS_INT *ptr,*index; LIS_SCALAR *value; LIS_DEBUG_FUNC_IN; lis_initialize(&argc, &argv); #ifdef USE_MPI MPI_Comm_size(MPI_COMM_WORLD,&int_nprocs); MPI_Comm_rank(MPI_COMM_WORLD,&int_my_rank); nprocs = int_nprocs; my_rank = int_my_rank; #else nprocs = 1; my_rank = 0; #endif if( argc < 6 ) { if( my_rank==0 ) { printf("Usage: %s m n matrix_type solution_filename rhistory_filename [options]\n", argv[0]); } CHKERR(1); } m = atoi(argv[1]); n = atoi(argv[2]); mtype = atoi(argv[3]); if( m<=0 || n<=0 ) { #ifdef _LONGLONG if( my_rank==0 ) printf("m=%lld <=0 or n=%lld <=0\n",m,n); #else if( my_rank==0 ) printf("m=%d <=0 or n=%d <=0\n",m,n); #endif CHKERR(1); } if( my_rank==0 ) { printf("\n"); #ifdef _LONGLONG printf("number of processes = %lld\n",nprocs); #else printf("number of processes = %d\n",nprocs); #endif } #ifdef _OPENMP if( my_rank==0 ) { #ifdef _LONGLONG printf("max number of threads = %lld\n",omp_get_num_procs()); printf("number of threads = %lld\n",omp_get_max_threads()); #else printf("max number of threads = %d\n",omp_get_num_procs()); printf("number of threads = %d\n",omp_get_max_threads()); #endif } #endif /* create matrix and vectors */ nn = m*n; err = lis_matrix_create(LIS_COMM_WORLD,&A); err = lis_matrix_set_size(A,0,nn); CHKERR(err); ptr = (LIS_INT *)malloc((A->n+1)*sizeof(LIS_INT)); if( ptr==NULL ) CHKERR(1); index = (LIS_INT *)malloc(5*A->n*sizeof(LIS_INT)); if( index==NULL ) CHKERR(1); value = (LIS_SCALAR *)malloc(5*A->n*sizeof(LIS_SCALAR)); if( value==NULL ) CHKERR(1); lis_matrix_get_range(A,&is,&ie); ctr = 0; for(ii=is;ii<ie;ii++) { i = ii/m; j = ii - i*m; if( i>0 ) { jj = ii - m; index[ctr] = jj; value[ctr++] = -1.0;} if( i<n-1 ) { jj = ii + m; index[ctr] = jj; value[ctr++] = -1.0;} if( j>0 ) { jj = ii - 1; index[ctr] = jj; value[ctr++] = -1.0;} if( j<m-1 ) { jj = ii + 1; index[ctr] = jj; value[ctr++] = -1.0;} index[ctr] = ii; value[ctr++] = 4.0; ptr[ii-is+1] = ctr; } ptr[0] = 0; err = lis_matrix_set_csr(ptr[ie-is],ptr,index,value,A); CHKERR(err); err = lis_matrix_assemble(A); CHKERR(err); nnz = A->nnz; #ifdef USE_MPI MPI_Allreduce(&nnz,&i,1,LIS_MPI_INT,MPI_SUM,A->comm); nnz = i; #endif #ifdef _LONGLONG if( my_rank==0 ) printf("matrix size = %lld x %lld (%lld nonzero entries)\n\n",nn,nn,nnz); #else if( my_rank==0 ) printf("matrix size = %d x %d (%d nonzero entries)\n\n",nn,nn,nnz); #endif err = lis_matrix_duplicate(A,&A0); CHKERR(err); lis_matrix_set_type(A0,mtype); err = lis_matrix_convert(A,A0); CHKERR(err); lis_matrix_destroy(A); A = A0; err = lis_vector_duplicate(A,&u); CHKERR(err); err = lis_vector_duplicate(A,&b); CHKERR(err); err = lis_vector_duplicate(A,&x); CHKERR(err); err = lis_vector_set_all(1.0,u); lis_matvec(A,u,b); err = lis_solver_create(&solver); CHKERR(err); lis_solver_set_option("-print mem",solver); lis_solver_set_optionC(solver); err = lis_solve(A,b,x,solver); CHKERR(err); lis_solver_get_iterex(solver,&iter,&iter_double,&iter_quad); lis_solver_get_timeex(solver,&time,&itime,&ptime,&p_c_time,&p_i_time); lis_solver_get_residualnorm(solver,&resid); lis_solver_get_solver(solver,&nsol); lis_solver_get_solvername(nsol,solvername); if( my_rank==0 ) { #ifdef _LONGLONG #ifdef _LONG__DOUBLE printf("%s: number of iterations = %lld \n",solvername, iter); #else printf("%s: number of iterations = %lld (double = %lld, quad = %lld)\n",solvername,iter, iter_double, iter_quad); #endif #else #ifdef _LONG__DOUBLE printf("%s: number of iterations = %d \n",solvername, iter); #else printf("%s: number of iterations = %d (double = %d, quad = %d)\n",solvername,iter, iter_double, iter_quad); #endif #endif printf("%s: elapsed time = %e sec.\n",solvername,time); printf("%s: preconditioner = %e sec.\n",solvername, ptime); printf("%s: matrix creation = %e sec.\n",solvername, p_c_time); printf("%s: linear solver = %e sec.\n",solvername, itime); #ifdef _LONG__DOUBLE printf("%s: relative residual = %Le\n\n",solvername,resid); #else printf("%s: relative residual = %e\n\n",solvername,resid); #endif } /* write solution */ lis_output_vector(x,LIS_FMT_MM,argv[4]); /* write residual history */ lis_solver_output_rhistory(solver, argv[5]); lis_solver_destroy(solver); lis_matrix_destroy(A); lis_vector_destroy(b); lis_vector_destroy(x); lis_vector_destroy(u); lis_finalize(); LIS_DEBUG_FUNC_OUT; return 0; }
LIS_INT lis_cgs(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR x; LIS_VECTOR r,rtld, p,phat, q, qhat, u, uhat, vhat; LIS_SCALAR alpha, beta, rho, rho_old, tmpdot1; LIS_REAL bnrm2, nrm2, tol; LIS_INT iter,maxiter,output,conv; double time,ptime; LIS_DEBUG_FUNC_IN; A = solver->A; x = solver->x; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; conv = solver->options[LIS_OPTIONS_CONV_COND]; ptime = 0.0; r = solver->work[0]; rtld = solver->work[1]; p = solver->work[2]; phat = solver->work[3]; q = solver->work[4]; qhat = solver->work[5]; u = solver->work[5]; uhat = solver->work[6]; vhat = solver->work[6]; alpha = (LIS_SCALAR)1.0; rho_old = (LIS_SCALAR)1.0; /* Initial Residual */ if( lis_solver_get_initial_residual(solver,NULL,NULL,r,&bnrm2) ) { LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } tol = solver->tol; lis_solver_set_shadowresidual(solver,r,rtld); lis_vector_set_all(0,q); lis_vector_set_all(0,p); for( iter=1; iter<=maxiter; iter++ ) { /* rho = <rtld,r> */ lis_vector_dot(rtld,r,&rho); /* test breakdown */ if( rho==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* beta = (rho / rho_old) */ beta = (rho / rho_old); /* u = r + beta*q */ lis_vector_axpyz(beta,q,r,u); /* p = u + beta*(q + beta*p) */ lis_vector_xpay(q,beta,p); lis_vector_xpay(u,beta,p); /* phat = M^-1 * p */ time = lis_wtime(); lis_psolve(solver, p, phat); ptime += lis_wtime()-time; /* v = A * phat */ lis_matvec(A,phat,vhat); /* tmpdot1 = <rtld,vhat> */ lis_vector_dot(rtld,vhat,&tmpdot1); /* test breakdown */ if( tmpdot1==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* alpha = rho / tmpdot1 */ alpha = rho / tmpdot1; /* q = u - alpha*vhat */ lis_vector_axpyz(-alpha,vhat,u,q); /* phat = u + q */ /* uhat = M^-1 * (u + q) */ lis_vector_axpyz(1,u,q,phat); time = lis_wtime(); lis_psolve(solver, phat, uhat); ptime += lis_wtime()-time; /* x = x + alpha*uhat */ lis_vector_axpy(alpha,uhat,x); /* qhat = A * uhat */ lis_matvec(A,uhat,qhat); /* r = r - alpha*qhat */ lis_vector_axpy(-alpha,qhat,r); /* convergence check */ lis_solver_get_residual[conv](r,solver,&nrm2); if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol >= nrm2 ) { solver->retcode = LIS_SUCCESS; solver->iter = iter; solver->resid = nrm2; solver->ptime = ptime; LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } rho_old = rho; } solver->retcode = LIS_MAXITER; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_gmres(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR b,x; LIS_VECTOR r,s,z,*v; LIS_SCALAR *h; LIS_SCALAR aa,bb,rr,a2,b2,t; LIS_REAL tnrm2; LIS_REAL bnrm2,nrm2,tol; LIS_INT iter,maxiter,n,output; double time,ptime; LIS_REAL rnorm; LIS_INT i,j,k,m; LIS_INT ii,i1,iiv,i1v,iih,jj; LIS_INT h_dim; LIS_INT cs,sn; LIS_DEBUG_FUNC_IN; A = solver->A; b = solver->b; x = solver->x; n = A->n; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; m = solver->options[LIS_OPTIONS_RESTART]; h_dim = m+1; ptime = 0.0; s = solver->work[0]; r = solver->work[1]; z = solver->work[2]; v = &solver->work[3]; h = (LIS_SCALAR *)lis_malloc( sizeof(LIS_SCALAR)*(h_dim+1)*(h_dim+2),"lis_gmres::h" ); cs = (m+1)*h_dim; sn = (m+2)*h_dim; /* r = M^-1 * (b - A * x) */ lis_matvec(A,x,z); lis_vector_xpay(b,-1.0,z); lis_psolve(solver,z,v[0]); /* Initial Residual */ if( lis_solver_get_initial_residual(solver,NULL,NULL,v[0],&bnrm2) ) { lis_free(h); LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } tol = solver->tol; iter=0; while( iter<maxiter ) { /* first column of V */ /* v = r / ||r||_2 */ lis_vector_nrm2(v[0],&rnorm); lis_vector_scale(1.0/rnorm,v[0]); /* s = ||r||_2 e_1 */ lis_vector_set_all(0,s); s->value[0] = rnorm; i = 0; do { iter++; i++; ii = i-1; i1 = i; iiv = i-1; i1v = i; iih = (i-1)*h_dim; /* z = M^-1 * v */ time = lis_wtime(); lis_psolve(solver,v[iiv],z); ptime += lis_wtime()-time; /* w = A * z */ lis_matvec(A,z,v[i1v]); for(k=0;k<i;k++) { /* h[k,i] = <w,v[k]> */ /* w = w - h[k,i] * v[k] */ lis_vector_dot(v[i1v],v[k],&t); h[k+iih] = t; lis_vector_axpy(-t,v[k],v[i1v]); } /* h[i+1,i] = ||w|| */ /* v[i+1] = w / h[i+1,i] */ lis_vector_nrm2(v[i1v],&tnrm2); h[i1+iih] = tnrm2; lis_vector_scale(1.0/tnrm2,v[i1v]); for(k=1;k<=ii;k++) { jj = k-1; t = h[jj+iih]; aa = h[jj+cs]*t; aa += h[jj+sn]*h[k+iih]; bb = -h[jj+sn]*t; bb += h[jj+cs]*h[k+iih]; h[jj+iih] = aa; h[k+iih] = bb; } aa = h[ii+iih]; bb = h[i1+iih]; a2 = aa*aa; b2 = bb*bb; rr = sqrt(a2+b2); if( rr==0.0 ) rr=1.0e-17; h[ii+cs] = aa/rr; h[ii+sn] = bb/rr; s->value[i1] = -h[ii+sn]*s->value[ii]; s->value[ii] = h[ii+cs]*s->value[ii]; aa = h[ii+cs]*h[ii+iih]; aa += h[ii+sn]*h[i1+iih]; h[ii+iih] = aa; /* convergence check */ nrm2 = sabs(s->value[i1])*bnrm2; if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol >= nrm2 ) break; } while( i<m && iter <maxiter ); /* Solve H * Y = S for upper Hessenberg matrix H */ s->value[ii] = s->value[ii]/h[ii+iih]; for(k=1;k<=ii;k++) { jj = ii-k; t = s->value[jj]; for(j=jj+1;j<=ii;j++) { t -= h[jj+j*h_dim]*s->value[j]; } s->value[jj] = t/h[jj+jj*h_dim]; } /* z = z + y * v */ #ifdef _OPENMP #pragma omp parallel for private(k) #endif for(k=0;k<n;k++) { z->value[k] = s->value[0]*v[0]->value[k]; } for(j=1;j<=ii;j++) { lis_vector_axpy(s->value[j],v[j],z); } /* r = M^-1 * z */ time = lis_wtime(); lis_psolve(solver,z,r); ptime += lis_wtime()-time; /* x = x + r */ lis_vector_axpy(1,r,x); if( tol >= nrm2 ) { solver->retcode = LIS_SUCCESS; solver->iter = iter; solver->resid = nrm2; solver->ptime = ptime; lis_free(h); LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } for(j=1;j<=i;j++) { jj = i1-j+1; s->value[jj-1] = -h[jj-1+sn]*s->value[jj]; s->value[jj] = h[jj-1+cs]*s->value[jj]; } for(j=0;j<=i1;j++) { t = s->value[j]; if( j==0 ) t = t-1.0; lis_vector_axpy(t,v[j],v[0]); } } solver->retcode = LIS_MAXITER; solver->iter = iter+1; solver->resid = nrm2; lis_free(h); LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_crs_quad(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR x; LIS_VECTOR r,rtld, p, q, u, z, ap, map, uq, auq; LIS_QUAD_PTR alpha, beta, rho, rho_old, tmpdot1, one; LIS_REAL bnrm2, nrm2, tol; LIS_INT iter,maxiter,output,conv; double time,ptime; LIS_DEBUG_FUNC_IN; A = solver->A; x = solver->x; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; conv = solver->options[LIS_OPTIONS_CONV_COND]; ptime = 0.0; r = solver->work[0]; rtld = solver->work[1]; p = solver->work[2]; z = solver->work[3]; u = solver->work[3]; uq = solver->work[3]; q = solver->work[4]; ap = solver->work[4]; map = solver->work[5]; auq = solver->work[5]; LIS_QUAD_SCALAR_MALLOC(alpha,0,1); LIS_QUAD_SCALAR_MALLOC(beta,1,1); LIS_QUAD_SCALAR_MALLOC(rho,2,1); LIS_QUAD_SCALAR_MALLOC(rho_old,3,1); LIS_QUAD_SCALAR_MALLOC(tmpdot1,4,1); LIS_QUAD_SCALAR_MALLOC(one,6,1); /* Initial Residual */ if( lis_solver_get_initial_residual(solver,NULL,NULL,r,&bnrm2) ) { LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } tol = solver->tol; lis_solver_set_shadowresidual(solver,r,p); lis_matvect(A,p,rtld); lis_vector_set_allex_nm(0.0,q); lis_vector_set_allex_nm(0.0,p); rho_old.hi[0] = 1.0; rho_old.lo[0] = 0.0; one.hi[0] = 1.0; one.lo[0] = 0.0; for( iter=1; iter<=maxiter; iter++ ) { /* z = M^-1 * r */ /* rho = <rtld,z> */ time = lis_wtime(); lis_psolve(solver, r, z); ptime += lis_wtime()-time; lis_vector_dotex_mmm(rtld,z,&rho); /* test breakdown */ if( rho.hi[0]==0.0 && rho.lo[0]==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* beta = rho / rho_old */ /* u = z + beta*q */ /* p = u + beta*(q + beta*p) */ /* ap = A * p */ /* map = M^-1 * ap */ /* tmpdot1 = <rtld,map> */ lis_quad_div((LIS_QUAD *)beta.hi,(LIS_QUAD *)rho.hi,(LIS_QUAD *)rho_old.hi); lis_vector_axpyzex_mmmm(beta,q,z,u); lis_vector_xpayex_mmm(q,beta,p); lis_vector_xpayex_mmm(u,beta,p); lis_matvec(A,p,ap); time = lis_wtime(); lis_psolve(solver, ap, map); ptime += lis_wtime()-time; lis_vector_dotex_mmm(rtld,map,&tmpdot1); /* test breakdown */ if( tmpdot1.hi[0]==0.0 && tmpdot1.lo[0]==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* alpha = rho / tmpdot1 */ /* q = u - alpha*map */ /* uq = u + q */ /* auq = A * uq */ /* x = x + alpha*uq */ /* r = r - alpha*auq */ lis_quad_div((LIS_QUAD *)alpha.hi,(LIS_QUAD *)rho.hi,(LIS_QUAD *)tmpdot1.hi); lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyzex_mmmm(alpha,map,u,q); lis_vector_axpyzex_mmmm(one,u,q,uq); lis_matvec(A,uq,auq); lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyex_mmm(alpha,uq,x); lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyex_mmm(alpha,auq,r); /* convergence check */ lis_solver_get_residual[conv](r,solver,&nrm2); if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol >= nrm2 ) { solver->retcode = LIS_SUCCESS; solver->iter = iter; solver->resid = nrm2; solver->ptime = ptime; LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } rho_old.hi[0] = rho.hi[0]; rho_old.lo[0] = rho.lo[0]; } solver->retcode = LIS_MAXITER; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_esi_quad(LIS_ESOLVER esolver) { LIS_MATRIX A; LIS_VECTOR x, Ax; LIS_SCALAR xAx, xx, mu, lshift; LIS_INT ss; LIS_INT emaxiter; LIS_REAL tol; LIS_INT i,j,k; LIS_SCALAR evalue,dotvr; LIS_INT iter,giter,output,niesolver; LIS_INT nprocs,my_rank; LIS_REAL nrm2,dot,resid,resid0; LIS_QUAD_PTR qdot_vv, qdot_vr; LIS_VECTOR *v,r,q; LIS_SOLVER solver; LIS_PRECON precon; double times,itimes,ptimes,p_c_times,p_i_times; LIS_INT err; LIS_INT nsol, precon_type; char solvername[128], preconname[128]; LIS_DEBUG_FUNC_IN; A = esolver->A; x = esolver->x; ss = esolver->options[LIS_EOPTIONS_SUBSPACE]; emaxiter = esolver->options[LIS_EOPTIONS_MAXITER]; tol = esolver->params[LIS_EPARAMS_RESID - LIS_EOPTIONS_LEN]; lshift = esolver->lshift; output = esolver->options[LIS_EOPTIONS_OUTPUT]; niesolver = esolver->options[LIS_EOPTIONS_INNER_ESOLVER]; r = esolver->work[0]; q = esolver->work[1]; v = &esolver->work[2]; Ax = esolver->work[3]; LIS_QUAD_SCALAR_MALLOC(qdot_vv,0,1); LIS_QUAD_SCALAR_MALLOC(qdot_vr,1,1); lis_vector_set_all(1.0,r); lis_vector_nrm2(r, &nrm2); lis_vector_scale(1/nrm2,r); switch ( niesolver ) { case LIS_ESOLVER_II: lis_solver_create(&solver); lis_solver_set_option("-i bicg -p ilu -precision quad",solver); lis_solver_set_optionC(solver); lis_solver_get_solver(solver, &nsol); lis_solver_get_precon(solver, &precon_type); lis_get_solvername(nsol, solvername); lis_get_preconname(precon_type, preconname); printf("solver : %s %d\n", solvername, nsol); printf("precon : %s %d\n", preconname, precon_type); if( A->my_rank==0 ) printf("local shift = %e\n", lshift); if (lshift != 0) lis_matrix_shift_diagonal(A, lshift); break; case LIS_ESOLVER_AII: lis_solver_create(&solver); lis_solver_set_option("-i bicg -p ilu -precision quad",solver); lis_solver_set_optionC(solver); lis_solver_get_solver(solver, &nsol); lis_solver_get_precon(solver, &precon_type); lis_get_solvername(nsol, solvername); lis_get_preconname(precon_type, preconname); printf("solver : %s %d\n", solvername, nsol); printf("precon : %s %d\n", preconname, precon_type); if( A->my_rank==0 ) printf("local shift = %e\n", lshift); if (lshift != 0) lis_matrix_shift_diagonal(A, lshift); lis_vector_set_all(1.0,q); lis_solve(A, q, x, solver); lis_precon_create(solver, &precon); solver->precon = precon; break; case LIS_ESOLVER_RQI: lis_solver_create(&solver); lis_solver_set_option("-p ilu -precision quad -maxiter 10",solver); lis_solver_set_optionC(solver); lis_solver_get_solver(solver, &nsol); lis_solver_get_precon(solver, &precon_type); lis_get_solvername(nsol, solvername); lis_get_preconname(precon_type, preconname); printf("solver : %s %d\n", solvername, nsol); printf("precon : %s %d\n", preconname, precon_type); if( A->my_rank==0 ) printf("local shift = %e\n", lshift); if (lshift != 0) lis_matrix_shift_diagonal(A, lshift); break; } giter=0; j=0; while (j<ss) { lis_vector_duplicate(A,&esolver->evector[j]); j = j+1; lis_vector_copy(r, v[j]); if (niesolver==LIS_ESOLVER_II || niesolver==LIS_ESOLVER_RQI) { /* create preconditioner */ solver->A = A; err = lis_precon_create(solver, &precon); if( err ) { lis_solver_work_destroy(solver); solver->retcode = err; return err; } } if (niesolver==LIS_ESOLVER_RQI) { lis_vector_nrm2(x, &nrm2); lis_vector_scale(1/nrm2, x); lis_matvec(A, x, Ax); lis_vector_dot(x, Ax, &xAx); lis_vector_dot(x, x, &xx); mu = xAx / xx; } iter = 0; while (iter<emaxiter) { /* diagonalization */ iter = iter+1; giter = giter+1; for (k=1;k<j;k++) { lis_vector_dotex_mmm(v[j], v[k], &qdot_vv); lis_quad_minus((LIS_QUAD *)qdot_vv.hi); lis_vector_axpyex_mmm(qdot_vv,v[k],v[j]); } switch( niesolver ) { case LIS_ESOLVER_PI: lis_matvec(A,v[j],r); break; case LIS_ESOLVER_II: lis_solve_kernel(A, v[j], r, solver, precon); break; case LIS_ESOLVER_AII: lis_psolve(solver, v[j], r); break; case LIS_ESOLVER_RQI: lis_vector_nrm2(v[j], &nrm2); lis_vector_scale(1/nrm2, v[j]); lis_matrix_shift_diagonal(A, -mu); lis_solve_kernel(A, v[j], r, solver, precon); lis_matrix_shift_diagonal(A, mu); break; } if ( j==1 && ( niesolver==LIS_ESOLVER_II || niesolver==LIS_ESOLVER_AII || niesolver==LIS_ESOLVER_RQI )) { lis_solver_get_timeex(solver,×,&itimes,&ptimes,&p_c_times,&p_i_times); esolver->ptimes += solver->ptimes; esolver->itimes += solver->itimes; esolver->p_c_times += solver->p_c_times; esolver->p_i_times += solver->p_i_times; } lis_vector_nrm2(r, &nrm2); lis_vector_dotex_mmm(v[j], r, &qdot_vr); lis_quad_minus((LIS_QUAD *)qdot_vr.hi); lis_vector_axpyzex_mmmm(qdot_vr,v[j],r,q); lis_quad_minus((LIS_QUAD *)qdot_vr.hi); dotvr = qdot_vr.hi[0]; mu = mu + 1/dotvr; lis_vector_nrm2(q, &resid); resid = fabs(resid / dotvr); lis_vector_scale(1/nrm2,r); lis_vector_copy(r, v[j]); if ( j==1 ) { if( output & LIS_PRINT_MEM ) esolver->residual[iter] = resid; if( output & LIS_PRINT_OUT ) printf("iter: %5d residual = %e\n", iter, resid); esolver->iter = iter; esolver->resid = resid; } if (tol>resid) break; } if (niesolver==LIS_ESOLVER_II || niesolver==LIS_ESOLVER_RQI) { lis_precon_destroy(precon); } switch ( niesolver ) { case LIS_ESOLVER_PI: esolver->evalue[j-1] = dotvr; break; case LIS_ESOLVER_II: esolver->evalue[j-1] = 1/dotvr; break; case LIS_ESOLVER_AII: esolver->evalue[j-1] = 1/dotvr; break; case LIS_ESOLVER_RQI: esolver->evalue[j-1] = mu; break; } lis_vector_copy(v[j], esolver->evector[j-1]); if (A->my_rank==0 && ss>1) { #ifdef _LONGLONG printf("Subspace: mode number = %lld\n", j-1); #else printf("Subspace: mode number = %d\n", j-1); #endif printf("Subspace: eigenvalue = %e\n", esolver->evalue[j-1]); #ifdef _LONGLONG printf("Subspace: number of iterations = %lld\n",iter); #else printf("Subspace: number of iterations = %d\n",iter); #endif printf("Subspace: relative residual 2-norm = %e\n",resid); } } lis_vector_copy(esolver->evector[esolver->options[LIS_EOPTIONS_MODE]], esolver->x); switch ( niesolver ) { case LIS_ESOLVER_II: if (lshift != 0) lis_matrix_shift_diagonal(A, -lshift); lis_solver_destroy(solver); break; case LIS_ESOLVER_AII: if (lshift != 0) lis_matrix_shift_diagonal(A, -lshift); lis_precon_destroy(precon); lis_solver_destroy(solver); break; case LIS_ESOLVER_RQI: if (lshift != 0) lis_matrix_shift_diagonal(A, -lshift); lis_solver_destroy(solver); break; } LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; }
LIS_INT lis_gs(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR b,x; LIS_VECTOR r,t,s; LIS_REAL bnrm2, nrm2, tol; LIS_INT iter,maxiter,output; double time,ptime; LIS_INT err; LIS_DEBUG_FUNC_IN; A = solver->A; b = solver->b; x = solver->x; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; tol = solver->params[LIS_PARAMS_RESID-LIS_OPTIONS_LEN]; ptime = 0.0; r = solver->work[0]; t = solver->work[1]; s = solver->work[2]; lis_vector_nrm2(b,&bnrm2); bnrm2 = 1.0 / bnrm2; err = lis_matrix_split(A); if( err ) return err; if( A->use_wd!=LIS_SOLVER_GS ) { if( !A->WD ) { err = lis_matrix_diag_duplicate(A->D,&A->WD); if( err ) return err; } lis_matrix_diag_copy(A->D,A->WD); lis_matrix_diag_inverse(A->WD); A->use_wd = LIS_SOLVER_GS; } for( iter=1; iter<=maxiter; iter++ ) { /* x += (D-L)^{-1}(b - Ax) */ time = lis_wtime(); lis_psolve(solver,x,s); ptime += lis_wtime() - time; lis_matvec(A,s,t); /* lis_matvec(A,x,t);*/ lis_vector_axpyz(-1,t,b,r); lis_vector_nrm2(r,&nrm2); lis_matrix_solve(A,r,t,LIS_MATRIX_LOWER); lis_vector_axpy(1,t,x); /* convergence check */ nrm2 = nrm2 * bnrm2; if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol >= nrm2 ) { time = lis_wtime(); lis_psolve(solver,x,s); ptime += lis_wtime() - time; lis_vector_copy(s,x); solver->retcode = LIS_SUCCESS; solver->iter = iter; solver->resid = nrm2; solver->ptime = ptime; LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } } lis_psolve(solver,x,s); lis_vector_copy(s,x); solver->retcode = LIS_MAXITER; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT lis_cgs_switch(LIS_SOLVER solver) { LIS_MATRIX A; LIS_VECTOR x; LIS_VECTOR r,rtld, p,phat, q, qhat, u, uhat, vhat; LIS_QUAD_PTR alpha, beta, rho, rho_old, tmpdot1, one; LIS_REAL bnrm2, nrm2, tol, tol2; LIS_INT iter,maxiter,output,conv; LIS_INT iter2,maxiter2; double time,ptime; LIS_DEBUG_FUNC_IN; A = solver->A; x = solver->x; maxiter = solver->options[LIS_OPTIONS_MAXITER]; maxiter2 = solver->options[LIS_OPTIONS_SWITCH_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; conv = solver->options[LIS_OPTIONS_CONV_COND]; tol = solver->params[LIS_PARAMS_RESID-LIS_OPTIONS_LEN]; tol2 = solver->params[LIS_PARAMS_SWITCH_RESID-LIS_OPTIONS_LEN]; ptime = 0.0; r = solver->work[0]; rtld = solver->work[1]; p = solver->work[2]; phat = solver->work[3]; q = solver->work[4]; qhat = solver->work[5]; u = solver->work[5]; uhat = solver->work[6]; vhat = solver->work[6]; LIS_QUAD_SCALAR_MALLOC(alpha,0,1); LIS_QUAD_SCALAR_MALLOC(beta,1,1); LIS_QUAD_SCALAR_MALLOC(rho,2,1); LIS_QUAD_SCALAR_MALLOC(rho_old,3,1); LIS_QUAD_SCALAR_MALLOC(tmpdot1,4,1); LIS_QUAD_SCALAR_MALLOC(one,6,1); rho_old.hi[0] = 1.0; rho_old.lo[0] = 0.0; alpha.hi[0] = 1.0; alpha.lo[0] = 0.0; one.hi[0] = 1.0; one.lo[0] = 0.0; /* Initial Residual */ if( lis_solver_get_initial_residual(solver,NULL,NULL,r,&bnrm2) ) { LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } tol2 = solver->tol_switch; lis_solver_set_shadowresidual(solver,r,rtld); lis_vector_set_allex_nm(0.0, q); lis_vector_set_allex_nm(0.0, p); uhat->precision = LIS_PRECISION_DEFAULT; p->precision = LIS_PRECISION_DEFAULT; phat->precision = LIS_PRECISION_DEFAULT; for( iter=1; iter<=maxiter2; iter++ ) { /* rho = <rtld,r> */ lis_vector_dot(rtld,r,&rho.hi[0]); /* test breakdown */ if( rho.hi[0]==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter; solver->iter2 = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* beta = (rho / rho_old) */ beta.hi[0] = (rho.hi[0] / rho_old.hi[0]); /* u = r + beta*q */ lis_vector_axpyz(beta.hi[0],q,r,u); /* p = u + beta*(q + beta*p) */ lis_vector_xpay(q,beta.hi[0],p); lis_vector_xpay(u,beta.hi[0],p); /* phat = M^-1 * p */ time = lis_wtime(); lis_psolve(solver, p, phat); ptime += lis_wtime()-time; /* v = A * phat */ lis_matvec(A,phat,vhat); /* tmpdot1 = <rtld,vhat> */ lis_vector_dot(rtld,vhat,&tmpdot1.hi[0]); /* test breakdown */ if( tmpdot1.hi[0]==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter; solver->iter2 = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* alpha = rho / tmpdot1 */ alpha.hi[0] = rho.hi[0] / tmpdot1.hi[0]; /* q = u - alpha*vhat */ lis_vector_axpyz(-alpha.hi[0],vhat,u,q); /* phat = u + q */ /* uhat = M^-1 * (u + q) */ lis_vector_axpyz(1.0,u,q,phat); time = lis_wtime(); lis_psolve(solver, phat, uhat); ptime += lis_wtime()-time; /* x = x + alpha*uhat */ lis_vector_axpy(alpha.hi[0],uhat,x); /* qhat = A * uhat */ lis_matvec(A,uhat,qhat); /* r = r - alpha*qhat */ lis_vector_axpy(-alpha.hi[0],qhat,r); /* convergence check */ lis_solver_get_residual[conv](r,solver,&nrm2); if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( nrm2 <= tol2 ) { solver->iter = iter; solver->iter2 = iter; solver->ptime = ptime; break; } rho_old.hi[0] = rho.hi[0]; } uhat->precision = LIS_PRECISION_QUAD; p->precision = LIS_PRECISION_QUAD; phat->precision = LIS_PRECISION_QUAD; solver->options[LIS_OPTIONS_INITGUESS_ZEROS] = LIS_FALSE; lis_vector_copyex_mn(x,solver->xx); rho_old.hi[0] = 1.0; lis_solver_get_initial_residual(solver,NULL,NULL,r,&bnrm2); tol = solver->tol; lis_solver_set_shadowresidual(solver,r,rtld); lis_vector_set_allex_nm(0.0, q); lis_vector_set_allex_nm(0.0, p); for( iter2=iter+1; iter2<=maxiter; iter2++ ) { /* rho = <rtld,r> */ lis_vector_dotex_mmm(rtld,r,&rho); /* test breakdown */ if( rho.hi[0]==0.0 && rho.lo[0]==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter2; solver->iter2 = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* beta = (rho / rho_old) */ lis_quad_div((LIS_QUAD *)beta.hi,(LIS_QUAD *)rho.hi,(LIS_QUAD *)rho_old.hi); /* u = r + beta*q */ lis_vector_axpyzex_mmmm(beta,q,r,u); /* p = u + beta*(q + beta*p) */ lis_vector_xpayex_mmm(q,beta,p); lis_vector_xpayex_mmm(u,beta,p); /* phat = M^-1 * p */ time = lis_wtime(); lis_psolve(solver, p, phat); ptime += lis_wtime()-time; /* v = A * phat */ lis_matvec(A,phat,vhat); /* tmpdot1 = <rtld,vhat> */ lis_vector_dotex_mmm(rtld,vhat,&tmpdot1); /* test breakdown */ if( tmpdot1.hi[0]==0.0 && tmpdot1.lo[0]==0.0 ) { solver->retcode = LIS_BREAKDOWN; solver->iter = iter2; solver->iter2 = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_BREAKDOWN; } /* alpha = rho / tmpdot1 */ lis_quad_div((LIS_QUAD *)alpha.hi,(LIS_QUAD *)rho.hi,(LIS_QUAD *)tmpdot1.hi); /* q = u - alpha*vhat */ lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyzex_mmmm(alpha,vhat,u,q); /* phat = u + q */ /* uhat = M^-1 * (u + q) */ lis_vector_axpyzex_mmmm(one,u,q,phat); time = lis_wtime(); lis_psolve(solver, phat, uhat); ptime += lis_wtime()-time; /* x = x + alpha*uhat */ lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyex_mmm(alpha,uhat,x); /* qhat = A * uhat */ lis_matvec(A,uhat,qhat); /* r = r - alpha*qhat */ lis_quad_minus((LIS_QUAD *)alpha.hi); lis_vector_axpyex_mmm(alpha,qhat,r); /* convergence check */ lis_solver_get_residual[conv](r,solver,&nrm2); if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter2] = nrm2; if( output & LIS_PRINT_OUT && A->my_rank==0 ) lis_print_rhistory(iter,nrm2); } if( tol > nrm2 ) { solver->retcode = LIS_SUCCESS; solver->iter = iter2; solver->iter2 = iter; solver->resid = nrm2; solver->ptime = ptime; LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } rho_old.hi[0] = rho.hi[0]; rho_old.lo[0] = rho.lo[0]; } solver->retcode = LIS_MAXITER; solver->iter = iter2; solver->iter2 = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT main(LIS_INT argc, char* argv[]) { LIS_MATRIX A; LIS_VECTOR b,x,u; LIS_SOLVER solver; LIS_INT my_rank; #ifdef USE_MPI int int_nprocs,int_my_rank; #endif LIS_INT err,i,n,gn,is,ie,iter; n = 12; lis_initialize(&argc, &argv); #ifdef USE_MPI MPI_Comm_size(MPI_COMM_WORLD,&int_nprocs); MPI_Comm_rank(MPI_COMM_WORLD,&int_my_rank); my_rank = int_my_rank; #else my_rank = 0; #endif lis_matrix_create(LIS_COMM_WORLD,&A); err = lis_matrix_set_size(A,0,n); CHKERR(err); lis_matrix_get_size(A,&n,&gn); lis_matrix_get_range(A,&is,&ie); for(i=is;i<ie;i++) { if( i>0 ) lis_matrix_set_value(LIS_INS_VALUE,i,i-1,-1.0,A); if( i<gn-1 ) lis_matrix_set_value(LIS_INS_VALUE,i,i+1,-1.0,A); lis_matrix_set_value(LIS_INS_VALUE,i,i,2.0,A); } lis_matrix_set_type(A,LIS_MATRIX_CSR); lis_matrix_assemble(A); lis_vector_duplicate(A,&u); lis_vector_duplicate(A,&b); lis_vector_duplicate(A,&x); lis_vector_set_all(1.0,u); lis_matvec(A,u,b); lis_solver_create(&solver); lis_solver_set_option("-print mem",solver); lis_solver_set_optionC(solver); lis_solve(A,b,x,solver); lis_solver_get_iter(solver,&iter); if (my_rank==0) { #ifdef _LONG__LONG printf("number of iterations = %lld\n",iter); #else printf("number of iterations = %d\n",iter); #endif printf("\n"); } lis_vector_print(x); lis_matrix_destroy(A); lis_vector_destroy(b); lis_vector_destroy(x); lis_vector_destroy(u); lis_solver_destroy(solver); lis_finalize(); return 0; }
LIS_INT main(LIS_INT argc, char* argv[]) { LIS_MATRIX A0,A,B; LIS_VECTOR x,b,u; LIS_SOLVER solver; LIS_INT nprocs,my_rank; int int_nprocs,int_my_rank; LIS_INT nsol,rhs,len,i,j,k,jj,kk,p,nrow_p,l,n; LIS_INT err,iter,iter_double,iter_quad; LIS_INT *iw,*nrow,*index,*ptr; LIS_SCALAR *s,t,*value; double times,itimes,ptimes,p_c_times,p_i_times; LIS_REAL resid; char solvername[128]; LIS_DEBUG_FUNC_IN; lis_initialize(&argc, &argv); #ifdef USE_MPI MPI_Comm_size(MPI_COMM_WORLD,&int_nprocs); MPI_Comm_rank(MPI_COMM_WORLD,&int_my_rank); nprocs = int_nprocs; my_rank = int_my_rank; #else nprocs = 1; my_rank = 0; #endif if( argc < 5 ) { if( my_rank==0 ) { printf("Usage: %s matrix_filename rhs_setting solution_filename residual_filename [options]\n", argv[0]); } CHKERR(1); } len = (LIS_INT)strlen(argv[2]); if( len==1 ) { if( argv[2][0]=='0' || argv[2][0]=='1' || argv[2][0]=='2' ) { rhs = atoi(argv[2]); } else { rhs = -1; } } else { rhs = -1; } if( my_rank==0 ) { printf("\n"); #ifdef _LONGLONG printf("number of processes = %lld\n",nprocs); #else printf("number of processes = %d\n",nprocs); #endif } #ifdef _OPENMP if( my_rank==0 ) { #ifdef _LONGLONG printf("max number of threads = %lld\n",omp_get_num_procs()); printf("number of threads = %lld\n",omp_get_max_threads()); #else printf("max number of threads = %d\n",omp_get_num_procs()); printf("number of threads = %d\n",omp_get_max_threads()); #endif } #endif /* read matrix and vectors from file */ err = lis_matrix_create(LIS_COMM_WORLD,&A); CHKERR(err); err = lis_vector_create(LIS_COMM_WORLD,&b); CHKERR(err); err = lis_vector_create(LIS_COMM_WORLD,&x); CHKERR(err); err = lis_input(A,b,x,argv[1]); CHKERR(err); err = lis_matrix_duplicate(A,&A0); CHKERR(err); lis_matrix_set_type(A0,LIS_MATRIX_CSR); err = lis_matrix_convert(A,A0); CHKERR(err); lis_matrix_destroy(A); A = A0; err = lis_vector_duplicate(A,&u); CHKERR(err); if( lis_vector_is_null(b) ) { lis_vector_destroy(b); lis_vector_duplicate(A,&b); CHKERR(err); if( rhs==0 ) { CHKERR(1); } else if( rhs==1 ) { err = lis_vector_set_all(1.0,b); } else { err = lis_vector_set_all(1.0,u); lis_matvec(A,u,b); } } if( rhs==-1 ) { lis_input_vector(b,argv[2]); } if( lis_vector_is_null(x) ) { lis_vector_destroy(x); err = lis_vector_duplicate(A,&x); CHKERR(err); } err = lis_solver_create(&solver); CHKERR(err); lis_solver_set_option("-print mem",solver); lis_solver_set_optionC(solver); err = lis_solve(A,b,x,solver); CHKERR(err); lis_solver_get_itersex(solver,&iter,&iter_double,&iter_quad); lis_solver_get_timeex(solver,×,&itimes,&ptimes,&p_c_times,&p_i_times); lis_solver_get_residualnorm(solver,&resid); lis_solver_get_solver(solver,&nsol); lis_solver_get_solvername(nsol,solvername); /* write results */ if( my_rank==0 ) { #ifdef _LONGLONG #ifdef _LONG__DOUBLE printf("%s: number of iterations = %lld \n",solvername, iter); #else printf("%s: number of iterations = %lld (double = %lld, quad = %lld)\n",solvername,iter, iter_double, iter_quad); #endif #else #ifdef _LONG__DOUBLE printf("%s: number of iterations = %d \n",solvername, iter); #else printf("%s: number of iterations = %d (double = %d, quad = %d)\n",solvername,iter, iter_double, iter_quad); #endif #endif printf("%s: elapsed time = %e sec.\n",solvername,times); printf("%s: preconditioner = %e sec.\n",solvername, ptimes); printf("%s: matrix creation = %e sec.\n",solvername, p_c_times); printf("%s: linear solver = %e sec.\n",solvername, itimes); #ifdef _LONG__DOUBLE printf("%s: relative residual 2-norm = %Le\n\n",solvername,resid); #else printf("%s: relative residual 2-norm = %e\n\n",solvername,resid); #endif } /* write solution */ lis_output_vector(x,LIS_FMT_MM,argv[3]); /* write residual */ lis_solver_output_rhistory(solver, argv[4]); lis_solver_destroy(solver); lis_vector_destroy(x); lis_vector_destroy(u); lis_vector_destroy(b); lis_matrix_destroy(A); lis_finalize(); LIS_DEBUG_FUNC_OUT; return 0; }
LIS_INT lis_psolve_adds(LIS_SOLVER solver, LIS_VECTOR B, LIS_VECTOR X) { LIS_INT i,k,n,np,iter,ptype; LIS_SCALAR *b,*x,*w,*r,*rl; LIS_VECTOR W,R; LIS_PRECON precon; LIS_QUAD_DECLAR; LIS_DEBUG_FUNC_IN; precon = solver->precon; n = precon->A->n; np = precon->A->np; W = precon->work[0]; R = precon->work[1]; b = B->value; x = X->value; w = W->value; r = R->value; rl = R->value_lo; iter = solver->options[LIS_OPTIONS_ADDS_ITER]; ptype = solver->options[LIS_OPTIONS_PRECON]; #ifdef USE_QUAD_PRECISION if( solver->precision==LIS_PRECISION_DEFAULT ) { #endif lis_vector_set_all(0.0,X); lis_vector_copy(B,R); for(k=0;k<iter+1;k++) { for(i=n;i<np;i++) { r[i] = 0.0; } lis_psolve_xxx[ptype](solver,R,W); #ifdef _OPENMP #pragma omp parallel for private(i) #endif for(i=0;i<n;i++) { x[i] += w[i]; } if(k!=iter) { lis_matvec(precon->A,X,R); #ifdef _OPENMP #pragma omp parallel for private(i) #endif for(i=0;i<n;i++) { r[i] = b[i] - r[i]; } } } #ifdef USE_QUAD_PRECISION } else { lis_vector_set_allex_nm(0.0,X); lis_vector_copyex_mm(B,R); for(k=0;k<iter+1;k++) { for(i=n;i<np;i++) { r[i] = 0.0; rl[i] = 0.0; } lis_psolve_xxx[ptype](solver,R,W); for(i=0;i<n;i++) { #ifndef USE_SSE2 LIS_QUAD_ADD(X->value[i],X->value_lo[i],X->value[i],X->value_lo[i],W->value[i],W->value_lo[i]); #else LIS_QUAD_ADD_SSE2(X->value[i],X->value_lo[i],X->value[i],X->value_lo[i],W->value[i],W->value_lo[i]); #endif /* x[i] += w[i];*/ } if(k==iter) break; lis_matvec(precon->A,X,R); for(i=0;i<n;i++) { #ifndef USE_SSE2 LIS_QUAD_ADD(R->value[i],R->value_lo[i],B->value[i],B->value_lo[i],-R->value[i],-R->value_lo[i]); #else LIS_QUAD_ADD_SSE2(R->value[i],R->value_lo[i],B->value[i],B->value_lo[i],-R->value[i],-R->value_lo[i]); #endif /* r[i] = b[i] - r[i];*/ } } } #endif LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; }
LIS_INT lis_minres(LIS_SOLVER solver) { LIS_Comm comm; LIS_MATRIX A; LIS_VECTOR b,x; LIS_VECTOR v1,v2,v3,v4,w0,w1,w2; LIS_REAL nrm2,tol; LIS_SCALAR alpha; LIS_REAL beta2,beta3; LIS_SCALAR gamma1,gamma2,gamma3; LIS_SCALAR delta,eta; LIS_SCALAR sigma1,sigma2,sigma3; LIS_SCALAR rho1,rho2,rho3; LIS_REAL r0_euc,r_euc; LIS_INT iter,maxiter,output; double time,ptime; LIS_DEBUG_FUNC_IN; comm = LIS_COMM_WORLD; A = solver->A; b = solver->b; x = solver->x; tol = solver->params[LIS_PARAMS_RESID-LIS_OPTIONS_LEN]; maxiter = solver->options[LIS_OPTIONS_MAXITER]; output = solver->options[LIS_OPTIONS_OUTPUT]; ptime = 0.0; v1 = solver->work[0]; v2 = solver->work[1]; v3 = solver->work[2]; v4 = solver->work[3]; w0 = solver->work[4]; w1 = solver->work[5]; w2 = solver->work[6]; /* Lanczos algorithm */ lis_matvec(A,x,v2); lis_vector_xpay(b,-1.0,v2); time = lis_wtime(); lis_psolve(solver,v2,v3); ptime += lis_wtime()-time; lis_vector_copy(v3,v2); /* Compute elements of Hermitian tridiagonal matrix */ lis_vector_nrm2(v2,&r_euc); eta = beta2 = r0_euc = r_euc; gamma2 = gamma1 = 1.0; sigma2 = sigma1 = 0.0; lis_vector_set_all(0.0,v1); lis_vector_set_all(0.0,w0); lis_vector_set_all(0.0,w1); nrm2 = r_euc / r0_euc; for(iter=1;iter<=maxiter;iter++) { /* Lanczos algorithm */ lis_vector_scale(1.0 / beta2,v2); lis_matvec(A,v2,v3); time = lis_wtime(); lis_psolve(solver,v3,v4); ptime += lis_wtime()-time; lis_vector_dot(v2,v4,&alpha); lis_vector_axpy(-alpha,v2,v4); lis_vector_axpy(-beta2,v1,v4); lis_vector_nrm2(v4,&beta3); /* Compute elements of Hermitian tridiagonal matrix */ delta = gamma2 * alpha - gamma1 * sigma2 * beta2; rho1 = sqrt(delta * delta + beta3 * beta3); rho2 = sigma2 * alpha + gamma1 * gamma2 * beta2; rho3 = sigma1 * beta2; gamma3 = delta / rho1; sigma3 = beta3 / rho1; lis_vector_axpyz(-rho3,w0,v2,w2); lis_vector_axpy(-rho2,w1,w2); lis_vector_scale(1.0 / rho1,w2); lis_vector_axpy(gamma3 * eta,w2,x); /* convergence check */ r_euc *= fabs(sigma3); nrm2 = r_euc / r0_euc; if( output ) { if( output & LIS_PRINT_MEM ) solver->rhistory[iter] = nrm2; if( output & LIS_PRINT_OUT ) lis_print_rhistory(comm,iter,nrm2); } if( nrm2 <= tol ) { solver->retcode = LIS_SUCCESS; solver->iter = iter; solver->resid = nrm2; solver->ptime = ptime; LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; } eta *= -sigma3; lis_vector_copy(v2,v1); lis_vector_copy(v4,v2); lis_vector_copy(w1,w0); lis_vector_copy(w2,w1); beta2 = beta3; gamma1 = gamma2; gamma2 = gamma3; sigma1 = sigma2; sigma2 = sigma3; } lis_vector_destroy(v1); lis_vector_destroy(v2); lis_vector_destroy(v3); lis_vector_destroy(v4); lis_vector_destroy(w0); lis_vector_destroy(w1); lis_vector_destroy(w2); solver->retcode = LIS_MAXITER; solver->iter = iter; solver->resid = nrm2; LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }
LIS_INT main(LIS_INT argc, char* argv[]) { LIS_MATRIX A,A0; LIS_VECTOR b,x; LIS_SCALAR *value; LIS_INT nprocs,my_rank; int int_nprocs,int_my_rank; LIS_INT nthreads,maxthreads; LIS_INT gn,nnz,np; LIS_INT i,j,k,si,sj,sk,ii,jj,ctr; LIS_INT l,m,n,nn; LIS_INT is,ie; LIS_INT err,iter,matrix_type,storage,ss,se; LIS_INT *ptr,*index; double time,time2,nnzs,nnzap,nnzt; LIS_SCALAR val; double commtime,comptime,flops; LIS_DEBUG_FUNC_IN; lis_initialize(&argc, &argv); #ifdef USE_MPI MPI_Comm_size(MPI_COMM_WORLD,&int_nprocs); MPI_Comm_rank(MPI_COMM_WORLD,&int_my_rank); nprocs = int_nprocs; my_rank = int_my_rank; #else nprocs = 1; my_rank = 0; #endif if( argc < 5 ) { if( my_rank==0 ) { printf("Usage: %s l m n iter [matrix_type]\n", argv[0]); } CHKERR(1); } l = atoi(argv[1]); m = atoi(argv[2]); n = atoi(argv[3]); iter = atoi(argv[4]); if (argv[5] == NULL) { storage = 0; } else { storage = atoi(argv[5]); } if( iter<=0 ) { #ifdef _LONG__LONG if( my_rank==0 ) printf("iter=%lld <= 0\n",iter); #else if( my_rank==0 ) printf("iter=%d <= 0\n",iter); #endif CHKERR(1); } if( l<=0 || m<=0 || n<=0 ) { #ifdef _LONG__LONG if( my_rank==0 ) printf("l=%lld <=0, m=%lld <=0 or n=%lld <=0\n",l,m,n); #else if( my_rank==0 ) printf("l=%d <=0, m=%d <=0 or n=%d <=0\n",l,m,n); #endif CHKERR(1); } if( storage<0 || storage>11 ) { #ifdef _LONG__LONG if( my_rank==0 ) printf("matrix_type=%lld < 0 or matrix_type=%lld > 11\n",storage,storage); #else if( my_rank==0 ) printf("matrix_type=%d < 0 or matrix_type=%d > 11\n",storage,storage); #endif CHKERR(1); } if( my_rank==0 ) { printf("\n"); #ifdef _LONG__LONG printf("number of processes = %lld\n",nprocs); #else printf("number of processes = %d\n",nprocs); #endif } #ifdef _OPENMP nthreads = omp_get_num_procs(); maxthreads = omp_get_max_threads(); if( my_rank==0 ) { #ifdef _LONG__LONG printf("max number of threads = %lld\n", nthreads); printf("number of threads = %lld\n", maxthreads); #else printf("max number of threads = %d\n", nthreads); printf("number of threads = %d\n", maxthreads); #endif } #else nthreads = 1; maxthreads = 1; #endif /* create matrix and vectors */ nn = l*m*n; err = lis_matrix_create(LIS_COMM_WORLD,&A0); err = lis_matrix_set_size(A0,0,nn); CHKERR(err); ptr = (LIS_INT *)malloc((A0->n+1)*sizeof(LIS_INT)); if( ptr==NULL ) CHKERR(1); index = (LIS_INT *)malloc(27*A0->n*sizeof(LIS_INT)); if( index==NULL ) CHKERR(1); value = (LIS_SCALAR *)malloc(27*A0->n*sizeof(LIS_SCALAR)); if( value==NULL ) CHKERR(1); lis_matrix_get_range(A0,&is,&ie); ctr = 0; for(ii=is;ii<ie;ii++) { i = ii/(m*n); j = (ii - i*m*n)/n; k = ii - i*m*n - j*n; for(si=-1;si<=1;si++) { if( i+si>-1 && i+si<l ) { for(sj=-1;sj<=1;sj++) { if( j+sj>-1 && j+sj<m ) { for(sk=-1;sk<=1;sk++) { if( k+sk>-1 && k+sk<n ) { jj = ii + si*m*n + sj*n + sk; index[ctr] = jj; if( jj==ii ) { value[ctr++] = 26.0;} else { value[ctr++] = -1.0;} } } } } } } ptr[ii-is+1] = ctr; } ptr[0] = 0; err = lis_matrix_set_csr(ptr[ie-is],ptr,index,value,A0); CHKERR(err); err = lis_matrix_assemble(A0); CHKERR(err); n = A0->n; gn = A0->gn; nnz = A0->nnz; np = A0->np-n; #ifdef USE_MPI MPI_Allreduce(&nnz,&i,1,LIS_MPI_INT,MPI_SUM,A0->comm); nnzap = (double)i / (double)nprocs; nnzt = ((double)nnz -nnzap)*((double)nnz -nnzap); nnz = i; MPI_Allreduce(&nnzt,&nnzs,1,MPI_DOUBLE,MPI_SUM,A0->comm); nnzs = (nnzs / (double)nprocs)/nnzap; MPI_Allreduce(&np,&i,1,LIS_MPI_INT,MPI_SUM,A0->comm); np = i; #endif if( my_rank==0 ) { #ifdef _LONG__LONG printf("matrix size = %lld x %lld (%lld nonzero entries)\n",gn,gn,nnz); printf("number of iterations = %lld\n\n",iter); #else printf("matrix size = %d x %d (%d nonzero entries)\n",gn,gn,nnz); printf("number of iterations = %d\n\n",iter); #endif } err = lis_vector_duplicate(A0,&x); if( err ) CHKERR(err); err = lis_vector_duplicate(A0,&b); if( err ) CHKERR(err); lis_matrix_get_range(A0,&is,&ie); for(i=0;i<n;i++) { err = lis_vector_set_value(LIS_INS_VALUE,i+is,1.0,x); } for(i=0;i<n;i++) { lis_sort_id(A0->ptr[i],A0->ptr[i+1]-1,A0->index,A0->value); } /* MPI version of VBR is not implemented. DNS is also excluded to reduce memory usage. */ if (storage==0) { ss = 1; se = 11; } else { ss = storage; se = storage+1; } for (matrix_type=ss;matrix_type<se;matrix_type++) { if ( nprocs>1 && matrix_type==9 ) continue; lis_matrix_duplicate(A0,&A); lis_matrix_set_type(A,matrix_type); err = lis_matrix_convert(A0,A); if( err ) CHKERR(err); comptime = 0.0; commtime = 0.0; for(i=0;i<iter;i++) { #ifdef USE_MPI MPI_Barrier(A->comm); time = lis_wtime(); lis_send_recv(A->commtable,x->value); commtime += lis_wtime() - time; #endif time2 = lis_wtime(); lis_matvec(A,x,b); comptime += lis_wtime() - time2; } lis_vector_nrm2(b,&val); if( my_rank==0 ) { flops = 2.0*nnz*iter*1.0e-6 / comptime; #ifdef USE_MPI #ifdef _LONG__DOUBLE #ifdef _LONG__LONG printf("matrix_type = %2lld (%s), computation = %e sec, %8.3f MFLOPS, communication = %e sec, communication/computation = %3.3f %%, 2-norm = %Le\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,commtime,commtime/comptime*100,val); #else printf("matrix_type = %2d (%s), computation = %e sec, %8.3f MFLOPS, communication = %e sec, communication/computation = %3.3f %%, 2-norm = %Le\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,commtime,commtime/comptime*100,val); #endif #else #ifdef _LONG__LONG printf("matrix_type = %2lld (%s), computation = %e sec, %8.3f MFLOPS, communication = %e sec, communication/computation = %3.3f %%, 2-norm = %e\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,commtime,commtime/comptime*100,val); #else printf("matrix_type = %2d (%s), computation = %e sec, %8.3f MFLOPS, communication = %e sec, communication/computation = %3.3f %%, 2-norm = %e\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,commtime,commtime/comptime*100,val); #endif #endif #else #ifdef _LONG__DOUBLE #ifdef _LONG__LONG printf("matrix_type = %2lld (%s), computation = %e sec, %8.3f MFLOPS, 2-norm = %Le\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,val); #else printf("matrix_type = %2d (%s), computation = %e sec, %8.3f MFLOPS, 2-norm = %Le\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,val); #endif #else #ifdef _LONG__LONG printf("matrix_type = %2lld (%s), computation = %e sec, %8.3f MFLOPS, 2-norm = %e\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,val); #else printf("matrix_type = %2d (%s), computation = %e sec, %8.3f MFLOPS, 2-norm = %e\n",matrix_type,lis_storagename2[matrix_type-1],comptime,flops,val); #endif #endif #endif } lis_matrix_destroy(A); } lis_matrix_destroy(A0); lis_vector_destroy(b); lis_vector_destroy(x); lis_finalize(); LIS_DEBUG_FUNC_OUT; return 0; }