LIS_INT lis_solve(LIS_MATRIX A, LIS_VECTOR b, LIS_VECTOR x, LIS_SOLVER solver) { LIS_INT err; LIS_PRECON precon; LIS_DEBUG_FUNC_IN; solver->A = A; /* create preconditioner */ if( solver->options[LIS_OPTIONS_PRECON] < 0 || solver->options[LIS_OPTIONS_PRECON] > LIS_PRECONNAME_MAX ) { LIS_SETERR2(LIS_ERR_ILL_ARG,"Parameter LIS_OPTIONS_PRECON is %d (Set between 0 to %d)\n",solver->options[LIS_OPTIONS_PRECON], LIS_PRECONNAME_MAX); return LIS_ERR_ILL_ARG; } err = lis_precon_create(solver, &precon); if( err ) { lis_solver_work_destroy(solver); solver->retcode = err; return err; } /* Core Kernel of lis_solve() */ lis_solve_kernel(A, b, x, solver, precon); lis_precon_destroy(precon); LIS_DEBUG_FUNC_OUT; return LIS_SUCCESS; }
void lis_solve_kernel_f(LIS_MATRIX_F *A, LIS_VECTOR_F b, LIS_VECTOR_F x, LIS_SOLVER_F *solver, LIS_PRECON *precon, LIS_INT *ierr) { LIS_DEBUG_FUNC_IN; *ierr = lis_solve_kernel((LIS_MATRIX)LIS_V2P(A), (LIS_VECTOR)LIS_V2P(b), (LIS_VECTOR)LIS_V2P(x), (LIS_SOLVER)LIS_V2P(solver), (LIS_PRECON)LIS_V2P(precon)); if( *ierr ) return; LIS_DEBUG_FUNC_OUT; return; }
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_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_eii_quad(LIS_ESOLVER esolver) { LIS_MATRIX A; LIS_VECTOR x; LIS_SCALAR evalue, ievalue; LIS_SCALAR lshift; LIS_INT emaxiter; LIS_REAL tol; LIS_INT iter,iter2,output; LIS_REAL nrm2,resid; LIS_QUAD_PTR qdot_xz; LIS_VECTOR z,q; 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; emaxiter = esolver->options[LIS_EOPTIONS_MAXITER]; tol = esolver->params[LIS_EPARAMS_RESID - LIS_EOPTIONS_LEN]; lshift = esolver->lshift; 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); } evalue = 1.0; z = esolver->work[0]; q = esolver->work[1]; LIS_QUAD_SCALAR_MALLOC(qdot_xz,0,1); iter=0; ievalue = 1/(evalue); #ifdef _LONG__DOUBLE if( output & (A->my_rank==0) ) printf("local shift : %Le\n", lshift); #else if( output & (A->my_rank==0) ) printf("local shift : %e\n", lshift); #endif if (lshift != 0) lis_matrix_shift_diagonal(A, lshift); lis_solver_create(&solver); lis_solver_set_option("-i bicg -p none -precision quad",solver); lis_solver_set_optionC(solver); 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 & (A->my_rank==0) ) printf("linear solver : %s\n", solvername); if( output & (A->my_rank==0) ) printf("preconditioner : %s\n", preconname); /* create preconditioner */ solver->A = A; err = lis_precon_create(solver, &precon); if( err ) { lis_solver_work_destroy(solver); solver->retcode = err; return err; } while (iter<emaxiter) { iter = iter+1; /* x = x / ||x||_2 */ lis_vector_nrm2(x, &nrm2); lis_vector_scale(1/nrm2, x); /* z = (A - lshift I)^-1 * x */ lis_solve_kernel(A, x, z, solver, precon); lis_solver_get_iter(solver,&iter2); /* 1/evalue = <x,z> */ lis_vector_dotex_mmm(x, z, &qdot_xz); lis_quad_minus((LIS_QUAD *)qdot_xz.hi); lis_vector_axpyzex_mmmm(qdot_xz,x,z,q); lis_quad_minus((LIS_QUAD *)qdot_xz.hi); ievalue = qdot_xz.hi[0]; /* resid = ||z - 1/evalue * x||_2 / |1/evalue| */ lis_vector_nrm2(q, &resid); resid = fabs(resid/ievalue); /* x = z */ lis_vector_copy(z,x); /* 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 && A->my_rank==0 ) lis_print_rhistory(iter,resid); } if( tol >= resid ) { esolver->retcode = LIS_SUCCESS; esolver->iter[0] = iter; esolver->resid[0] = resid; esolver->evalue[0] = 1/ievalue; lis_vector_nrm2(x, &nrm2); lis_vector_scale(1/nrm2, x); if (lshift != 0) lis_matrix_shift_diagonal(A, -lshift); 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] = 1/ievalue; lis_vector_nrm2(x, &nrm2); lis_vector_scale(1/nrm2, x); if (lshift != 0) { lis_matrix_shift_diagonal(A, -lshift); } lis_solver_destroy(solver); LIS_DEBUG_FUNC_OUT; return LIS_MAXITER; }