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