00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00041 class BiCGStabVtk {
00042 public:
00043 template <class fieldT, class fieldG>
00044 static inversion_stats inverter(fieldT &psi_out,
00045 fieldT &psi_in,
00046 fieldG &U,
00047 coefficients &coeff,
00048 mdp_real absolute_precision=mdp_precision,
00049 mdp_real relative_precision=0,
00050 int max_steps=2000) {
00051 mpi.begin_function("BiConugateGradientStabilizedInverter");
00052 const string filename_prefix="test";
00053 const int tc=0;
00054 string filename1, filename2;
00055 int step=0;
00056 fieldT p(psi_in);
00057 fieldT q(psi_in);
00058 fieldT r(psi_in);
00059 fieldT s(psi_in);
00060 fieldT t(psi_in);
00061
00062 mdp_field<float> sv(psi_in.lattice());
00063 mdp_site x(psi_in.lattice());
00064 double residue, rresidue=-1, old_rresidue;
00065 mdp_complex alpha, beta, rho, rho_old, omega;
00066 double time=mpi.time();
00067 inversion_stats stats;
00068
00069 mpi << "\tstep\tresidue\t\ttime (sec)\n";
00070
00071
00072 if(BiCGStabRestart==false)
00073 psi_out=psi_in;
00074
00075 psi_out.update();
00076 mul_Q(r,psi_out,U,coeff);
00077 r*=-1;
00078 r+=psi_in;
00079 q=r;
00080
00081 p=0.0;
00082 s=0.0;
00083
00084 rho_old=alpha=omega=1;
00085
00086 mpi << "\t<target>\n"
00087 << "\t\t<max_steps>" << max_steps << "</max_steps>\n"
00088 << "\t\t<absolute_precision>" << absolute_precision << "</absolute_precision>\n"
00089 << "\t\t<relative_precision>" << relative_precision << "</relative_precision>\n"
00090 << "\t</target>\n";
00091
00092 do {
00093
00094 rho=q*r;
00095 beta=(rho/rho_old)*(alpha/omega);
00096 rho_old=rho;
00097 p*=beta;
00098 p+=r;
00099 mdp_add_scaled_field(p, -beta*omega, s);
00100 p.update();
00101 mul_Q(s,p,U,coeff);
00102 alpha=rho/(q*s);
00103 mdp_add_scaled_field(r, -alpha, s);
00104 r.update();
00105 mul_Q(t,r,U,coeff);
00106 omega=t*r;
00107 omega/=norm_square(t);
00108 mdp_add_scaled_field(psi_out, omega, r);
00109 mdp_add_scaled_field(psi_out, alpha, p);
00110
00111
00112 residue=norm_square(r);
00113 residue=sqrt(residue/r.global_size());
00114
00115
00116 old_rresidue=rresidue;
00117 rresidue=relative_residue(r,psi_out);
00118
00119
00120 forallsites(x) {
00121 sv(x)=0.0;
00122 for(int a=0; a<4; a++)
00123 for(int k=0; k<psi_in.nc; k++)
00124 sv(x)+=sqrt(real(psi_out(x,a,k)*conj(psi_out(x,a,k))));
00125 }
00126 filename1=filename_prefix+".field."+tostring(step)+".vtk";
00127 sv.save_vtk(filename1,tc);
00128 forallsites(x) {
00129 sv(x)=0.0;
00130 for(int a=0; a<4; a++)
00131 for(int k=0; k<psi_in.nc; k++)
00132 sv(x)+=log(real(r(x,a,k)*conj(r(x,a,k)))+PRECISION);
00133 }
00134 filename2=filename_prefix+".residue."+tostring(step)+".vtk";
00135 sv.save_vtk(filename2,tc);
00136
00137
00138 mdp_add_scaled_field(r, -omega, t);
00139
00140 mpi << "\t\t<step>" << step << "</step>\n"
00141 << "\t\t<residue>" << residue << "</residue>\n"
00142 << "\t\t<relative_residue>" << rresidue << "</relative_residue>\n"
00143 << "\t\t<time>" << mpi.time()-time << "</time>\n\n";
00144
00145 if((step>10) && (rresidue==old_rresidue))
00146 error("not converging");
00147 step++;
00148
00149 } while (residue>absolute_precision &&
00150 rresidue>relative_precision &&
00151 step<max_steps);
00152
00153 psi_out.update();
00154
00155 stats.target_absolute_precision=absolute_precision;
00156 stats.target_relative_precision=relative_precision;
00157 stats.max_steps=max_steps;
00158 stats.absolute_precision=residue;
00159 stats.relative_precision=rresidue;
00160 stats.residue=residue;
00161 stats.steps=step;
00162 stats.mul_Q_steps=2*step+1;
00163 stats.time=mpi.time()-time;
00164
00165 mpi << "\t<stats>\n"
00166 << "\t\t<max_steps>" << step << "</max_steps>\n"
00167 << "\t\t<absolute_precision>" << residue << "</absolute_precision>\n"
00168 << "\t\t<relative_precision>" << rresidue << "</relative_precision>\n"
00169 << "\t\t<time>" << stats.time << "</time>\n"
00170 << "\t</stats>\n";
00171
00172 mpi.end_function("BiConugateGradientStabilizedInverter");
00173 return stats;
00174 }
00175 };
00176
00177 template <class fieldT, class fieldG>
00178 inversion_stats BiConjugateGradientStabilizedInverterVtk(fieldT &psi_out,
00179 fieldT &psi_in,
00180 fieldG &U,
00181 coefficients &coeff,
00182 mdp_real absolute_precision=mdp_precision,
00183 mdp_real relative_precision=0,
00184 int max_steps=2000) {
00185 return BiCGStabVtk::inverter(psi_out,psi_in,U,coeff,
00186 absolute_precision,
00187 relative_precision,
00188 max_steps);
00189 }