00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011 #ifndef _ARK4DENSEOUTPUT_H_
00012 #define _ARK4DENSEOUTPUT_H_
00013
00014
00015 #include "NamespaceHeader.H"
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 template <class Soln, class Rhs, class IMEXOp>
00034 class ARK4DenseOutput
00035 {
00036 public:
00037
00038 ARK4DenseOutput<Soln, Rhs, IMEXOp>() { m_isDefined = false; }
00039
00040
00041 void define(const Soln& a_state, Real a_dt, bool a_denseOutput = false);
00042
00043
00044 void advance(Real a_time, Soln& a_state);
00045
00046
00047
00048 void denseOutputCoefs(Vector<Rhs*>& a_interpCoefs);
00049
00050
00051 void resetDt(Real a_dt);
00052
00053
00054 void start0end1(bool a_start0, bool a_end1);
00055
00056
00057
00058
00059 IMEXOp& getImExOp();
00060
00061 bool isDefined() const { return m_isDefined; }
00062
00063 bool hasDenseOutput() const { return m_hasDenseOutput; }
00064
00065
00066 static const int s_nStages = 6;
00067 static const Real s_aIdiag;
00068 static const Real s_c[s_nStages];
00069 static const Real s_aE[s_nStages][s_nStages];
00070 static const Real s_aI[s_nStages][s_nStages];
00071 static const Real s_b[s_nStages];
00072 static const int s_nDenseCoefs = 3;
00073 static const Real s_bstar[s_nDenseCoefs][s_nStages];
00074
00075 protected:
00076 bool m_isDefined;
00077 bool m_denseOutput;
00078 bool m_hasDenseOutput;
00079 Real m_dt;
00080 Real m_time;
00081 Soln m_phi[s_nStages];
00082 Rhs m_rhs;
00083 Rhs m_denseCoefs[s_nDenseCoefs];
00084 Rhs m_kE;
00085 Rhs m_kI;
00086 IMEXOp m_opImEx;
00087
00088 private:
00089
00090 };
00091
00092
00093
00094 template <class Soln, class Rhs, class IMEXOp>
00095 void ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00096 define(const Soln& a_state, Real a_dt, bool a_denseOutput)
00097 {
00098 CH_TIMERS("ARK4DenseOutput::define");
00099 m_dt = a_dt;
00100 m_denseOutput = a_denseOutput;
00101
00102 for (int stage = 0; stage < s_nStages; stage++)
00103 m_phi[stage].define(a_state);
00104
00105
00106 m_kE.define(a_state);
00107 m_kI.define(a_state);
00108 m_rhs.define(a_state);
00109
00110
00111 m_opImEx.define(a_state, m_dt, s_aIdiag);
00112
00113
00114 for (int coef = 0; m_denseOutput && (coef < s_nDenseCoefs); coef++)
00115 m_denseCoefs[coef].define(a_state);
00116
00117 m_hasDenseOutput = false;
00118 m_isDefined = true;
00119 }
00120
00121
00122
00123
00124 template <class Soln, class Rhs, class IMEXOp>
00125 IMEXOp& ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00126 getImExOp()
00127 {
00128 return m_opImEx;
00129 }
00130
00131
00132
00133
00134 template <class Soln, class Rhs, class IMEXOp>
00135 void ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00136 resetDt(Real a_dt)
00137 {
00138 CH_assert(isDefined());
00139
00140
00141 Real reltol = 1e-14;
00142 if (Abs(m_dt - a_dt) > m_dt*reltol)
00143 {
00144 m_dt = a_dt;
00145 m_hasDenseOutput = false;
00146 m_opImEx.resetDt(m_dt);
00147 }
00148 }
00149
00150
00151
00152
00153 template <class Soln, class Rhs, class IMEXOp>
00154 void ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00155 start0end1(bool a_start0, bool a_end1)
00156 {
00157 CH_assert(isDefined());
00158
00159 int stage0 = -1;
00160 if (a_start0) stage0 = 0;
00161
00162 int stage1 = -1;
00163 if (a_end1) stage1 = s_nStages-1;
00164
00165 m_opImEx.stage0stage1(stage0, stage1);
00166 }
00167
00168
00169
00170
00171 template <class Soln, class Rhs, class IMEXOp>
00172 void ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00173 advance(Real a_time, Soln& a_state)
00174 {
00175 CH_TIMERS("ARK4DenseOutput::advance");
00176 CH_assert(isDefined());
00177
00178 CH_TIMER("ARK4DenseOutput::advance - explicit op", t1);
00179 CH_TIMER("ARK4DenseOutput::advance - implicit op", t2);
00180 CH_TIMER("ARK4DenseOutput::advance - implicit solve", t3);
00181
00182
00183 if (m_denseOutput)
00184 {
00185 m_hasDenseOutput = false;
00186 for (int icoef=0; icoef < s_nDenseCoefs; ++icoef)
00187 m_denseCoefs[icoef].zero();
00188 }
00189
00190
00191 for (int stage = 0; stage < s_nStages; stage++)
00192 m_phi[stage].copy(a_state);
00193
00194
00195
00196 a_state.copy(m_phi[0]);
00197
00198
00199 for (int stage = 0; stage < s_nStages; stage++)
00200 {
00201 Real t = a_time + s_c[stage]*m_dt;
00202 if (stage > 0)
00203 {
00204
00205 m_rhs.copy(m_phi[stage]);
00206
00207
00208 CH_START(t3);
00209 m_opImEx.solve(m_phi[stage], m_rhs, t, stage);
00210 CH_STOP(t3);
00211 }
00212
00213
00214 CH_START(t1);
00215 m_opImEx.explicitOp(m_kE, t, m_phi[stage], stage);
00216 CH_STOP(t1);
00217
00218
00219 a_state.increment(m_kE, m_dt*s_b[stage], true);
00220 for (int k=stage+1; k < s_nStages; ++k)
00221 m_phi[k].increment(m_kE, m_dt*s_aE[k][stage]);
00222
00223 CH_START(t2);
00224 m_opImEx.implicitOp(m_kI, t, m_phi[stage], stage);
00225 CH_STOP(t2);
00226
00227
00228 a_state.increment(m_kI, m_dt*s_b[stage], true);
00229 for (int k=stage+1; k < s_nStages; ++k)
00230 m_phi[k].increment(m_kI, m_dt*s_aI[k][stage]);
00231
00232
00233
00234
00235
00236 if (m_denseOutput)
00237 {
00238
00239 for (int icoef=0; icoef < s_nDenseCoefs; ++icoef)
00240 {
00241 m_denseCoefs[icoef].increment(m_kE, m_dt*s_bstar[icoef][stage]);
00242 m_denseCoefs[icoef].increment(m_kI, m_dt*s_bstar[icoef][stage]);
00243
00244
00245
00246
00247
00248
00249
00250 }
00251 }
00252 }
00253
00254 m_hasDenseOutput = m_denseOutput;
00255 m_time = a_time;
00256 }
00257
00258
00259
00260
00261
00262 template <class Soln, class Rhs, class IMEXOp>
00263 void ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00264 denseOutputCoefs(Vector<Rhs*>& a_interpCoefs)
00265 {
00266 CH_TIMERS("ARK4DenseOutput::denseOutputCoefs");
00267
00268 const int nCoef = s_nDenseCoefs+1;
00269 CH_assert(m_hasDenseOutput);
00270 CH_assert(a_interpCoefs.size() == nCoef);
00271
00272 for (int icoef=0; icoef < nCoef; ++icoef)
00273 CH_assert(a_interpCoefs[icoef] != NULL);
00274
00275
00276
00277
00278 a_interpCoefs[0]->copy(m_phi[0]);
00279
00280
00281 for (int icoef = 1; icoef < nCoef ; ++icoef)
00282 {
00283
00284
00285
00286
00287
00288 a_interpCoefs[icoef]->copy(m_denseCoefs[icoef-1]);
00289 }
00290 }
00291
00292
00293
00294
00295
00296
00297 template <class Soln, class Rhs, class IMEXOp>
00298 const Real ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00299 s_aIdiag = 0.25;
00300
00301
00302 template <class Soln, class Rhs, class IMEXOp>
00303 const Real ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00304 s_c[] = { 0.0, 0.5, 0.332, 0.62, 0.85, 1.0 };
00305
00306
00307 template <class Soln, class Rhs, class IMEXOp>
00308 const Real ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00309 s_aE[][ARK4DenseOutput<Soln, Rhs, IMEXOp>::s_nStages] = {
00310 {0., 0., 0., 0., 0., 0.},
00311 {0.5, 0., 0., 0., 0., 0.},
00312 {0.221776, 0.110224, 0., 0., 0., 0.},
00313 {-0.04884659515311857, -0.17772065232640102, 0.8465672474795197, 0., 0., 0.},
00314 {-0.15541685842491548, -0.3567050098221991, 1.0587258798684427, 0.30339598837867193, 0., 0.},
00315 { 0.2014243506726763, 0.008742057842904185, 0.15993995707168115, 0.4038290605220775, 0.22606457389066084, 0.}
00316 };
00317
00318
00319 template <class Soln, class Rhs, class IMEXOp>
00320 const Real ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00321 s_aI[][ARK4DenseOutput<Soln, Rhs, IMEXOp>::s_nStages] = {
00322 {0., 0., 0., 0., 0., 0.},
00323 {0.25, 0.25, 0., 0., 0., 0.},
00324 {0.137776, -0.055776, 0.25, 0., 0., 0.},
00325 {0.14463686602698217, -0.22393190761334475, 0.4492950415863626, 0.25, 0., 0.},
00326 {0.09825878328356477, -0.5915442428196704, 0.8101210538282996, 0.283164405707806, 0.25, 0.},
00327 {0.15791629516167136, 0., 0.18675894052400077, 0.6805652953093346, -0.27524053099500667, 0.25}
00328 };
00329
00330
00331 template <class Soln, class Rhs, class IMEXOp>
00332 const Real ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00333 s_b[] =
00334 {0.15791629516167136, 0., 0.18675894052400077, 0.6805652953093346, -0.27524053099500667, 0.25};
00335
00336
00337 template <class Soln, class Rhs, class IMEXOp>
00338 const Real ARK4DenseOutput<Soln, Rhs, IMEXOp>::
00339 s_bstar[][ARK4DenseOutput<Soln, Rhs, IMEXOp>::s_nStages] = {
00340 {0.961753400252887, 0., 0.787405595186356, -2.74544192086633, 3.70351728061223, -1.70723435518514},
00341 {-1.76418754019038, 0., -0.774504669155511, 9.64023584441292, -12.544886411271, 5.44334277620397},
00342 {0.960350435099165, 0., 0.173858014493155, -6.21422862823726, 8.56612859966376, -3.48610842101883}
00343 };
00344
00345 #include "NamespaceFooter.H"
00346 #endif