73 m_equ[0]->PrintSummary(out);
76 out <<
"\tArnoldi solver type : Modified Arnoldi" << endl;
95 int nq =
m_equ[0]->UpdateFields()[0]->GetNcoeffs();
99 std::string evlFile =
m_session->GetFilename().substr(0,
m_session->GetFilename().find_last_of(
'.')) +
".evl";
100 ofstream evlout(evlFile.c_str());
103 Array<OneD, NekDouble> alpha = Array<OneD, NekDouble> (
m_kdim+1, 0.0);
104 Array<OneD, NekDouble> wr = Array<OneD, NekDouble> (
m_kdim, 0.0);
105 Array<OneD, NekDouble> wi = Array<OneD, NekDouble> (
m_kdim, 0.0);
106 Array<OneD, NekDouble> zvec = Array<OneD, NekDouble> (m_kdim*
m_kdim, 0.0);
108 Array<OneD, Array<OneD, NekDouble> > Kseq
109 = Array<OneD, Array<OneD, NekDouble> > (m_kdim + 1);
110 Array<OneD, Array<OneD, NekDouble> > Tseq
111 = Array<OneD, Array<OneD, NekDouble> > (m_kdim + 1);
112 for (i = 0; i < m_kdim + 1; ++i)
114 Kseq[i] = Array<OneD, NekDouble>(ntot, 0.0);
115 Tseq[i] = Array<OneD, NekDouble>(ntot, 0.0);
120 if(
m_session->DefinesFunction(
"InitialConditions"))
122 out <<
"\tInital vector : specified in input file " << endl;
123 m_equ[0]->SetInitialConditions(0.0,
false);
129 out <<
"\tInital vector : random " << endl;
140 out <<
"Iteration: " << 0 << endl;
143 alpha[0] = std::sqrt(
Blas::Ddot(ntot, &Kseq[0][0], 1,
148 Vmath::Smul(ntot, 1.0/alpha[0], Kseq[0], 1, Kseq[0], 1);
152 for (i = 1; !converged && i <=
m_kdim; ++i)
158 alpha[i] = std::sqrt(
Blas::Ddot(ntot, &Kseq[i][0], 1,
164 Vmath::Smul(ntot, 1.0/alpha[i], Kseq[i], 1, Kseq[i], 1);
167 for (
int k = 0; k < i + 1; ++k)
173 EV_small(Tseq, ntot, alpha, i, zvec, wr, wi, resnorm);
176 converged =
EV_test(i,i,zvec,wr,wi,resnorm,std::min(i,
m_nvec),evlout,resid0);
177 converged = max (converged, 0);
178 out <<
"Iteration: " << i <<
" (residual : " << resid0 <<
")" <<endl;
184 for (i = m_kdim + 1; !converged && i <=
m_nits; ++i)
189 for (
int j = 1; j <=
m_kdim; ++j)
191 alpha[j-1] = alpha[j];
197 EV_update(Kseq[m_kdim - 1], Kseq[m_kdim]);
200 alpha[
m_kdim] = std::sqrt(
Vmath::Dot(ntot, &Kseq[m_kdim][0], 1, &Kseq[m_kdim][0], 1));
202 Vmath::Smul(ntot, 1.0/alpha[m_kdim], Kseq[m_kdim], 1, Kseq[m_kdim], 1);
205 for (
int k = 0; k < m_kdim + 1; ++k)
211 EV_small(Tseq, ntot, alpha, m_kdim, zvec, wr, wi, resnorm);
214 converged =
EV_test(i,m_kdim,zvec,wr,wi,resnorm,
m_nvec,evlout,resid0);
215 out <<
"Iteration: " << i <<
" (residual : " << resid0 <<
")" <<endl;
225 for(j = 0; j <
m_equ[0]->GetNvariables(); ++j)
229 if (
m_comm->GetRank() == 0)
231 out <<
"L 2 error (variable " <<
m_equ[0]->GetVariable(j) <<
") : " << vL2Error << endl;
232 out <<
"L inf error (variable " <<
m_equ[0]->GetVariable(j) <<
") : " << vLinfError << endl;
237 EV_post(Tseq, Kseq, ntot, min(--i, m_kdim),
m_nvec, zvec, wr, wi, converged);
252 Array<OneD, NekDouble> &src,
253 Array<OneD, NekDouble> &tgt)
258 m_equ[0]->TransCoeffToPhys();
265 Array<OneD, MultiRegions::ExpListSharedPtr> fields;
266 fields =
m_equ[0]->UpdateFields();
271 m_equ[1]->TransCoeffToPhys();
285 Array<
OneD, Array<OneD, NekDouble> > &Kseq,
287 const Array<OneD, NekDouble> &alpha,
289 Array<OneD, NekDouble> &zvec,
290 Array<OneD, NekDouble> &wr,
291 Array<OneD, NekDouble> &wi,
294 int kdimp = kdim + 1;
297 Array<OneD, NekDouble> R(kdimp * kdimp, 0.0);
298 Array<OneD, NekDouble> H(kdimp * kdim, 0.0);
299 Array<OneD, NekDouble> rwork(lwork, 0.0);
302 for (
int i = 0; i < kdimp; ++i)
305 ASSERTL0(gsc != 0.0,
"Vectors are linearly independent.");
307 Vmath::Smul(ntot, 1.0/gsc, Kseq[i], 1, Kseq[i], 1);
308 for (
int j = i + 1; j < kdimp; ++j)
310 gsc =
Vmath::Dot(ntot, Kseq[i], 1, Kseq[j], 1);
311 Vmath::Svtvp(ntot, -gsc, Kseq[i], 1, Kseq[j], 1, Kseq[j], 1);
317 for (
int i = 0; i < kdim; ++i)
319 for (
int j = 0; j < kdim; ++j)
321 H[j*kdim+i] = alpha[j+1] * R[(j+1)*kdimp+i]
322 -
Vmath::Dot(j, &H[0] + i, kdim, &R[0] + j*kdimp, 1);
323 H[j*kdim+i] /= R[j*kdimp+j];
327 H[(kdim-1)*kdim+kdim] = alpha[kdim]
328 * std::fabs(R[kdim*kdimp+kdim] / R[(kdim-1)*kdimp + kdim-1]);
330 Lapack::dgeev_(
'N',
'V',kdim,&H[0],kdim,&wr[0],&wi[0],0,1,&zvec[0],kdim,&rwork[0],lwork,ier);
334 resnorm = H[(kdim-1)*kdim + kdim];
344 Array<OneD, NekDouble> &zvec,
345 Array<OneD, NekDouble> &wr,
346 Array<OneD, NekDouble> &wi,
355 Array<OneD, NekDouble> resid(kdim);
356 for (
int i = 0; i < kdim; ++i)
358 resid[i] = resnorm * std::fabs(zvec[kdim - 1 + i*kdim]) /
359 std::sqrt(
Vmath::Dot(kdim, &zvec[0] + i*kdim, 1, &zvec[0] + i*kdim, 1));
360 if (wi[i] < 0.0) resid[i-1] = resid[i] = hypot(resid[i-1], resid[i]);
362 EV_sort(zvec, wr, wi, resid, kdim);
364 if (resid[nvec-1] <
m_evtol) idone = nvec;
366 evlout <<
"-- Iteration = " << itrn <<
", H(k+1, k) = " << resnorm << endl;
369 evlout.setf(ios::scientific, ios::floatfield);
372 evlout <<
"EV Magnitude Angle Growth Frequency Residual"
377 evlout <<
"EV Real Imaginary inverse real inverse imag Residual"
381 for (
int i = 0; i < kdim; i++)
383 WriteEvs(evlout,i,wr[i],wi[i],resid[i]);
387 resid0 = resid[nvec-1];
396 Array<OneD, NekDouble> &evec,
397 Array<OneD, NekDouble> &wr,
398 Array<OneD, NekDouble> &wi,
399 Array<OneD, NekDouble> &test,
402 Array<OneD, NekDouble> z_tmp(dim,0.0);
404 for (
int j = 1; j < dim; ++j)
411 while (i >= 0 && test[i] > te_tmp)
416 Vmath::Vcopy(dim, &evec[0] + i*dim, 1, &evec[0] + (i+1)*dim, 1);
422 Vmath::Vcopy(dim, &z_tmp[0], 1, &evec[0] + (i+1)*dim, 1);
431 Array<
OneD, Array<OneD, NekDouble> > &Tseq,
432 Array<
OneD, Array<OneD, NekDouble> > &Kseq,
436 Array<OneD, NekDouble> &zvec,
437 Array<OneD, NekDouble> &wr,
438 Array<OneD, NekDouble> &wi,
444 ASSERTL0(
false,
"Convergence was not achieved within the prescribed number of iterations.");
449 ASSERTL0(
false,
"Minimum residual reached.");
451 else if (icon == nvec)
454 EV_big(Tseq, Kseq, ntot, kdim, icon, zvec, wr, wi);
455 Array<OneD, MultiRegions::ExpListSharedPtr> fields
456 =
m_equ[0]->UpdateFields();
458 for (
int j = 0; j < icon; ++j)
460 std::string file =
m_session->GetFilename().substr(0,
m_session->GetFilename().find_last_of(
'.')) +
"_eig_" + boost::lexical_cast<std::string>(j);
468 ASSERTL0(
false,
"Unrecognised value.");
477 Array<
OneD, Array<OneD, NekDouble> > &bvecs,
478 Array<
OneD, Array<OneD, NekDouble> > &evecs,
482 Array<OneD, NekDouble> &zvec,
483 Array<OneD, NekDouble> &wr,
484 Array<OneD, NekDouble> &wi)
489 for (
int j = 0; j < nvec; ++j)
492 for (
int i = 0; i < kdim; ++i)
494 wgt = zvec[i + j*kdim];
495 Vmath::Svtvp(ntot, wgt, bvecs[i], 1, evecs[j], 1, evecs[j], 1);
500 for (
int i = 0; i < nvec; ++i)
504 norm = std::sqrt(
Vmath::Dot(ntot, evecs[i], evecs[i]));
505 Vmath::Smul(ntot, 1.0/norm, evecs[i], 1, evecs[i], 1);
509 norm =
Vmath::Dot(ntot, evecs[i], 1, evecs[i], 1);
510 norm +=
Vmath::Dot(ntot, evecs[i+1], 1, evecs[i+1], 1);
511 norm = std::sqrt(norm);
512 Vmath::Smul(ntot, 1.0/norm, evecs[i], 1, evecs[i], 1);
513 Vmath::Smul(ntot, 1.0/norm, evecs[i+1], 1, evecs[i+1], 1);