00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011 #ifndef _RK4DENSEOUTPUT_H_
00012 #define _RK4DENSEOUTPUT_H_
00013
00014
00015 #include "NamespaceHeader.H"
00016
00017
00018
00019
00020
00021
00022
00023 template <class Soln, class Rhs, class EXOP>
00024 class RK4DenseOutput
00025 {
00026 public:
00027
00028 RK4DenseOutput<Soln, Rhs, EXOP>() { m_isDefined = false; }
00029
00030
00031 void define(const Soln& a_state, Real a_dt, bool a_denseOutput = false);
00032
00033
00034 void advance(Real a_time, Soln& a_state);
00035
00036
00037
00038 void denseOutputCoefs(Vector<Rhs*>& a_interpCoefs);
00039
00040
00041 void resetDt(Real a_dt);
00042
00043
00044 void start0end1(bool a_start0, bool a_end1);
00045
00046
00047
00048
00049 EXOP& getEXOP();
00050
00051 bool isDefined() const { return m_isDefined; }
00052
00053 bool hasDenseOutput() const { return m_hasDenseOutput; }
00054
00055
00056 static const int s_nStages = 4;
00057 static const Real s_c[s_nStages];
00058 static const Real s_a[s_nStages][s_nStages];
00059 static const Real s_b[s_nStages];
00060 static const int s_nDenseCoefs = 3;
00061 static const Real s_bstar[s_nDenseCoefs][s_nStages];
00062
00063 protected:
00064 bool m_isDefined;
00065 bool m_denseOutput;
00066 bool m_hasDenseOutput;
00067 Real m_dt;
00068 Real m_time;
00069 Soln m_phi[s_nStages];
00070 Rhs m_rhs;
00071 Rhs m_denseCoefs[s_nDenseCoefs];
00072 Rhs m_kE;
00073 EXOP m_opEx;
00074
00075 private:
00076
00077 };
00078
00079
00080
00081 template <class Soln, class Rhs, class EXOP>
00082 void RK4DenseOutput<Soln, Rhs, EXOP>::
00083 define(const Soln& a_state, Real a_dt, bool a_denseOutput)
00084 {
00085 CH_TIMERS("RK4DenseOutput::define");
00086 m_dt = a_dt;
00087 m_denseOutput = a_denseOutput;
00088
00089 for (int stage = 0; stage < s_nStages; stage++)
00090 m_phi[stage].define(a_state);
00091
00092
00093 m_kE.define(a_state);
00094 m_rhs.define(a_state);
00095
00096
00097 m_opEx.define(a_state, m_dt);
00098
00099
00100 for (int coef = 0; m_denseOutput && (coef < s_nDenseCoefs); coef++)
00101 m_denseCoefs[coef].define(a_state);
00102
00103 m_hasDenseOutput = false;
00104 m_isDefined = true;
00105 }
00106
00107
00108
00109
00110 template <class Soln, class Rhs, class EXOP>
00111 EXOP& RK4DenseOutput<Soln, Rhs, EXOP>::
00112 getEXOP()
00113 {
00114 return m_opEx;
00115 }
00116
00117
00118
00119
00120 template <class Soln, class Rhs, class EXOP>
00121 void RK4DenseOutput<Soln, Rhs, EXOP>::
00122 resetDt(Real a_dt)
00123 {
00124 CH_assert(isDefined());
00125
00126
00127 Real reltol = 1e-14;
00128 if (Abs(m_dt - a_dt) > m_dt*reltol)
00129 {
00130 m_dt = a_dt;
00131 m_hasDenseOutput = false;
00132 m_opEx.resetDt(m_dt);
00133 }
00134 }
00135
00136
00137
00138
00139 template <class Soln, class Rhs, class EXOP>
00140 void RK4DenseOutput<Soln, Rhs, EXOP>::
00141 start0end1(bool a_start0, bool a_end1)
00142 {
00143 CH_assert(isDefined());
00144
00145 int stage0 = -1;
00146 if (a_start0) stage0 = 0;
00147
00148 int stage1 = -1;
00149 if (a_end1) stage1 = s_nStages-1;
00150
00151 m_opEx.stage0stage1(stage0, stage1);
00152 }
00153
00154
00155
00156
00157 template <class Soln, class Rhs, class EXOP>
00158 void RK4DenseOutput<Soln, Rhs, EXOP>::
00159 advance(Real a_time, Soln& a_state)
00160 {
00161 CH_TIMERS("RK4DenseOutput::advance");
00162 CH_assert(isDefined());
00163
00164 CH_TIMER("RK4DenseOutput::advance - explicit op", t1);
00165
00166
00167 if (m_denseOutput)
00168 {
00169 m_hasDenseOutput = false;
00170 for (int icoef=0; icoef < s_nDenseCoefs; ++icoef)
00171 m_denseCoefs[icoef].zero();
00172 }
00173
00174
00175 for (int stage = 0; stage < s_nStages; stage++)
00176 m_phi[stage].copy(a_state);
00177
00178
00179
00180 a_state.copy(m_phi[0]);
00181
00182
00183 for (int stage = 0; stage < s_nStages; stage++)
00184 {
00185 Real t = a_time + s_c[stage]*m_dt;
00186 if (stage > 0)
00187 {
00188
00189 m_rhs.copy(m_phi[stage]);
00190 }
00191
00192
00193 CH_START(t1);
00194 m_opEx.explicitOp(m_kE, t, m_phi[stage], stage);
00195 CH_STOP(t1);
00196
00197
00198 a_state.increment(m_kE, m_dt*s_b[stage], true);
00199 for (int k=stage+1; k < s_nStages; ++k)
00200 m_phi[k].increment(m_kE, m_dt*s_a[k][stage]);
00201
00202
00203
00204
00205
00206 if (m_denseOutput)
00207 {
00208
00209 for (int icoef=0; icoef < s_nDenseCoefs; ++icoef)
00210 {
00211 m_denseCoefs[icoef].increment(m_kE, m_dt*s_bstar[icoef][stage]);
00212
00213
00214
00215
00216
00217
00218
00219 }
00220 }
00221 }
00222
00223 m_hasDenseOutput = m_denseOutput;
00224 m_time = a_time;
00225 }
00226
00227
00228
00229
00230
00231 template <class Soln, class Rhs, class EXOP>
00232 void RK4DenseOutput<Soln, Rhs, EXOP>::
00233 denseOutputCoefs(Vector<Rhs*>& a_interpCoefs)
00234 {
00235 CH_TIMERS("RK4DenseOutput::denseOutputCoefs");
00236
00237 const int nCoef = s_nDenseCoefs+1;
00238 CH_assert(m_hasDenseOutput);
00239 CH_assert(a_interpCoefs.size() == nCoef);
00240
00241 for (int icoef=0; icoef < nCoef; ++icoef)
00242 CH_assert(a_interpCoefs[icoef] != NULL);
00243
00244
00245
00246
00247 a_interpCoefs[0]->copy(m_phi[0]);
00248
00249
00250 for (int icoef = 1; icoef < nCoef ; ++icoef)
00251 {
00252
00253
00254
00255
00256
00257 a_interpCoefs[icoef]->copy(m_denseCoefs[icoef-1]);
00258 }
00259 }
00260
00261
00262
00263
00264
00265
00266
00267 template <class Soln, class Rhs, class EXOP>
00268 const Real RK4DenseOutput<Soln, Rhs, EXOP>::
00269 s_c[] = { 0.0, 0.5, 0.5, 1.0 };
00270
00271
00272 template <class Soln, class Rhs, class EXOP>
00273 const Real RK4DenseOutput<Soln, Rhs, EXOP>::
00274 s_a[][RK4DenseOutput<Soln, Rhs, EXOP>::s_nStages] = {
00275 {0., 0., 0., 0.},
00276 {0.5, 0., 0., 0.},
00277 {0., 0.5, 0., 0.},
00278 {0., 0., 1.0, 0.},
00279 };
00280
00281
00282 template <class Soln, class Rhs, class EXOP>
00283 const Real RK4DenseOutput<Soln, Rhs, EXOP>::
00284 s_b[] =
00285 {0.16666666666666667, 0.33333333333333333, 0.33333333333333333, 0.16666666666666667};
00286
00287
00288 template <class Soln, class Rhs, class EXOP>
00289 const Real RK4DenseOutput<Soln, Rhs, EXOP>::
00290 s_bstar[][RK4DenseOutput<Soln, Rhs, EXOP>::s_nStages] = {
00291 {1.0, 0., 0., 0.},
00292 {-1.5, 1.0, 1.0, -0.5},
00293 {0.66666666666666667, -0.66666666666666667, -0.66666666666666667, 0.66666666666666667}
00294 };
00295
00296
00297 #include "NamespaceFooter.H"
00298 #endif