00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011 #ifndef _BASELEVELTGA_H__
00012 #define _BASELEVELTGA_H__
00013
00014 #include <iostream>
00015 #include <math.h>
00016 #include "SPACE.H"
00017 #include <stdlib.h>
00018 #include <REAL.H>
00019 #include <Box.H>
00020 #include <DisjointBoxLayout.H>
00021 #include <LevelData.H>
00022 #include <ProblemDomain.H>
00023 #include "AMRTGA.H"
00024 #include "NamespaceHeader.H"
00025
00026
00028
00031 template <class T, class TFlux, class TFR>
00032 class BaseLevelTGA
00033 {
00034
00035 public:
00036
00037 LevelTGAHelmOp<T, TFlux>* newOp(const ProblemDomain& a_indexSpace,
00038 RefCountedPtr<AMRLevelOpFactory<T > >& a_opFact)
00039 {
00040 LevelTGAHelmOp<T, TFlux>* retval = (LevelTGAHelmOp<T,TFlux>*)
00041 (a_opFact->AMRnewOp(a_indexSpace));
00042
00043 return retval;
00044 }
00045
00047
00049 BaseLevelTGA(const Vector<DisjointBoxLayout>& a_grids,
00050 const Vector<int>& a_refRat,
00051 const ProblemDomain& a_level0Domain,
00052 RefCountedPtr<AMRLevelOpFactory< T > >& a_opFact,
00053 const RefCountedPtr<AMRMultiGrid<T > >& a_solver);
00054
00056 virtual ~BaseLevelTGA()
00057 {
00058 }
00059
00060
00062
00064 void updateSoln(T& a_phiNew,
00065 T& a_phiOld,
00066 T& a_src,
00067 LevelData<TFlux>& a_flux,
00068 TFR* a_FineFluxRegPtr,
00069 TFR* a_CrseFluxRegPtr,
00070 const T* a_crsePhiOldPtr,
00071 const T* a_crsePhiNewPtr,
00072 Real oldTime,
00073 Real crseOldTime,
00074 Real crseNewTime,
00075 Real dt,
00076 int a_level,
00077 bool a_zeroPhi = true,
00078 int a_fluxStartComponent = 0);
00079
00080
00082
00086 void computeDiffusion(T& a_DiffusiveTerm,
00087 T& a_phiOld,
00088 T& a_src,
00089 LevelData<TFlux>& a_flux,
00090 TFR* a_FineFluxRegPtr,
00091 TFR* a_crseFluxRegPtr,
00092 const T* a_crsePhiOldPtr,
00093 const T* a_crsePhiNewPtr,
00094 Real a_oldTime,
00095 Real a_crseOldTime,
00096 Real a_crseNewTime,
00097 Real a_dt,
00098 int a_level);
00099
00100
00101 protected:
00102
00103 void incrementFlux(LevelData<TFlux>& a_diffusiveFlux,
00104 T& a_phi,
00105 int a_level,
00106 Real a_mu,
00107 Real a_dt,
00108 Real a_sign,
00109 bool a_setToZero);
00110
00112
00116 void solveHelm(T& a_phi,
00117 T& a_phiC,
00118 T& a_rhs,
00119 int a_level,
00120 Real a_mu,
00121 Real a_dt,
00122 bool a_zeroPhi = true);
00123
00125
00132 void applyHelm(T& a_ans,
00133 const T& a_phi,
00134 const T* a_phiC,
00135 int a_level,
00136 Real a_mu,
00137 Real a_dt,
00138 bool a_applyBC);
00139
00141
00144 void resetSolverAlphaAndBeta(const Real& a_alpha,
00145 const Real& a_beta);
00146
00148
00153 void timeInterp(T& a_data,
00154 const T& a_oldData,
00155 const T& a_newData,
00156 Real a_time,
00157 Real a_oldTime,
00158 Real a_newTime,
00159 int a_Lev);
00160
00161
00162 virtual void setSourceGhostCells(T& a_src,
00163 const DisjointBoxLayout& a_dbl) = 0;
00164
00165
00166
00167 Vector<DisjointBoxLayout> m_grids ;
00168 Vector<int> m_refRat;
00169 ProblemDomain m_level0Domain;
00170 Vector<RefCountedPtr<LevelTGAHelmOp<T,TFlux> > > m_ops;
00171 RefCountedPtr<AMRMultiGrid<T > > m_solver;
00172 Real m_mu1, m_mu2, m_mu3, m_mu4, m_r1;
00173
00174 private:
00175
00176 void operator=(const BaseLevelTGA& a_opin)
00177 {
00178 MayDay::Error("invalid operator");
00179 }
00180 BaseLevelTGA(BaseLevelTGA& a_opin)
00181 {
00182 MayDay::Error("invalid operator");
00183 }
00185 BaseLevelTGA()
00186 {
00187 MayDay::Error("weak construction is bad");
00188 }
00189
00190 };
00191
00192 template <class T, class TFlux, class TFR>
00193 BaseLevelTGA<T, TFlux, TFR>::
00194 BaseLevelTGA(const Vector<DisjointBoxLayout>& a_grids,
00195 const Vector<int>& a_refRat,
00196 const ProblemDomain& a_level0Domain,
00197 RefCountedPtr<AMRLevelOpFactory< T > >& a_opFact,
00198 const RefCountedPtr<AMRMultiGrid<T > >& a_solver)
00199 {
00200 m_grids = a_grids;
00201 m_refRat = a_refRat;
00202 m_level0Domain = a_level0Domain;
00203 m_solver = a_solver;
00204
00205 Real tgaEpsilon = 1.e-12;
00206 Real a = 2.0 - sqrt(2.0) - tgaEpsilon;
00207 m_mu1 = (a - sqrt(pow(a,2) - 4.0*a + 2.0))/2.0 ;
00208 m_mu2 = (a + sqrt(pow(a,2) - 4.0*a + 2.0))/2.0 ;
00209 m_mu3 = (1.0 - a);
00210 m_mu4 = 0.5 - a;
00211
00212 Real discr = sqrt(a*a - 4.0*a + 2.0);
00213 m_r1 = (2.0*a - 1.0)/(a + discr);
00214
00215 m_ops.resize(a_grids.size());
00216 ProblemDomain domLev = a_level0Domain;
00217 for (int ilev = 0; ilev < m_ops.size(); ilev++)
00218 {
00219 m_ops[ilev] = RefCountedPtr<LevelTGAHelmOp<T,TFlux> >
00220 (newOp(domLev, a_opFact));
00221 if (ilev < m_ops.size() - 1)
00222 {
00223 domLev.refine(a_refRat[ilev]);
00224 }
00225 }
00226 }
00227
00228 template <class T, class TFlux, class TFR>
00229 void
00230 BaseLevelTGA<T, TFlux, TFR>::
00231 resetSolverAlphaAndBeta(const Real& a_alpha,
00232 const Real& a_beta)
00233 {
00234 Vector<MGLevelOp<T >* > ops = m_solver->getAllOperators();
00235 for(int iop = 0; iop < ops.size(); iop++)
00236 {
00237 LevelTGAHelmOp<T,TFlux>* helmop = (LevelTGAHelmOp<T,TFlux>*) ops[iop];
00238 helmop->setAlphaAndBeta(a_alpha, a_beta);
00239 }
00240 for(int iop = 0; iop < m_ops.size(); iop++)
00241 {
00242 m_ops[iop]->setAlphaAndBeta(a_alpha, a_beta);
00243 }
00244 }
00245 template <class T, class TFlux, class TFR>
00246 void
00247 BaseLevelTGA<T, TFlux, TFR>::
00248 applyHelm(T& a_ans,
00249 const T& a_phi,
00250 const T* a_phiC,
00251 int a_level,
00252 Real a_mu,
00253 Real a_dt,
00254 bool a_applyBC)
00255 {
00256 Real factor = a_mu*a_dt;
00257 m_ops[a_level]->setAlphaAndBeta(1.0, factor);
00258 T zero;
00259 m_ops[a_level]->create(zero, a_ans);
00260 m_ops[a_level]->setToZero(zero);
00261
00262
00263
00264 if(a_applyBC)
00265 {
00266 if( (a_phiC == NULL) || (a_level==0))
00267 {
00268 m_ops[a_level]->applyOp(a_ans, a_phi, false);
00269 }
00270 else
00271 {
00272 m_ops[a_level]->AMROperatorNF(a_ans, a_phi, *a_phiC, false);
00273 }
00274 }
00275 else
00276 {
00277 m_ops[a_level]->applyOpNoBoundary(a_ans, a_phi);
00278 }
00279 }
00280
00281
00282 template <class T, class TFlux, class TFR>
00283 void
00284 BaseLevelTGA<T, TFlux, TFR>::
00285 timeInterp(T& a_data,
00286 const T& a_oldData,
00287 const T& a_newData,
00288 Real a_time,
00289 Real a_oldTime,
00290 Real a_newTime,
00291 int a_lev)
00292 {
00293 Real eps = 1.0e-10;
00294 CH_assert(a_newTime >= a_oldTime);
00295 Real diff = (a_newTime - a_oldTime);
00296 m_ops[a_lev]->setToZero(a_data);
00297 if(diff < eps)
00298 {
00299
00300 m_ops[a_lev]->incr(a_data, a_oldData, 1.0);
00301 }
00302 else
00303 {
00304 Real factor = (a_time-a_oldTime)/(a_newTime - a_oldTime);
00305 m_ops[a_lev]->incr(a_data, a_oldData, 1.0-factor);
00306 m_ops[a_lev]->incr(a_data, a_newData, factor);
00307 }
00308 }
00309
00310
00311 template <class T, class TFlux, class TFR>
00312 void
00313 BaseLevelTGA<T, TFlux, TFR>::
00314 solveHelm(T& a_phi,
00315 T& a_phiC,
00316 T& a_rhs,
00317 int a_level,
00318 Real a_mu,
00319 Real a_dt,
00320 bool a_zeroPhi)
00321 {
00322 if (a_zeroPhi)
00323 {
00324 m_ops[a_level]->setToZero(a_phi);
00325 }
00326 Vector<T* > phi(m_grids.size(), NULL);
00327 Vector<T* > rhs(m_grids.size(), NULL);
00328 phi[a_level] = &a_phi;
00329 rhs[a_level] = &a_rhs;
00330 if(a_level > 0)
00331 {
00332 phi[a_level-1] = &a_phiC;
00333 }
00334
00335 Real factor = -a_dt*a_mu;
00336 resetSolverAlphaAndBeta(1.0, factor);
00337
00338 m_solver->solve(phi, rhs, a_level, a_level, a_zeroPhi);
00339 int solverExitStatus = m_solver->m_exitStatus;
00340 if (solverExitStatus==2 || solverExitStatus==4 || solverExitStatus==6)
00341 {
00342
00343
00344
00345
00346 pout() << "BaseLevelTGA:: WARNING: solver exitStatus == "
00347 << solverExitStatus << std::endl;
00348 }
00349 }
00350
00351 template <class T, class TFlux, class TFR>
00352 void
00353 BaseLevelTGA<T, TFlux, TFR>::
00354 incrementFlux(LevelData<TFlux>& a_diffusiveFlux,
00355 T& a_phi,
00356 int a_level,
00357 Real a_mu,
00358 Real a_dt,
00359 Real a_sign,
00360 bool a_setToZero)
00361 {
00362 Real factor = a_sign*a_dt*a_mu;
00363 m_ops[a_level]->setAlphaAndBeta(1.0, factor);
00364
00365
00366 TFlux tempFlux;
00367 m_ops[a_level]->fillGrad(a_phi);
00368 for (DataIterator dit = a_phi.dataIterator(); dit.ok(); ++dit)
00369 {
00370 TFlux& thisFlux = a_diffusiveFlux[dit];
00371 if(a_setToZero)
00372 {
00373 thisFlux.setVal(0.0);
00374 }
00375
00376 m_ops[a_level]->getFlux(tempFlux, a_phi, m_grids[a_level][dit], dit(), 1.0);
00377 thisFlux += tempFlux;
00378 }
00379 }
00380
00381 template <class T, class TFlux, class TFR>
00382 void
00383 BaseLevelTGA<T, TFlux, TFR>::
00384 updateSoln(T& a_phiNew,
00385 T& a_phiOld,
00386 T& a_src,
00387 LevelData<TFlux>& a_flux,
00388 TFR* a_fineFluxRegPtr,
00389 TFR* a_crseFluxRegPtr,
00390 const T* a_crsePhiOldPtr,
00391 const T* a_crsePhiNewPtr,
00392 Real a_oldTime,
00393 Real a_crseOldTime,
00394 Real a_crseNewTime,
00395 Real a_dt,
00396 int a_level,
00397 bool a_zeroPhi,
00398 int a_fluxStartComponent)
00399 {
00400 int ncomp = a_phiNew.nComp();
00401 Interval intervBase(0, ncomp-1);
00402 Interval intervFlux(a_fluxStartComponent, a_fluxStartComponent + ncomp-1);
00403
00404 CH_assert(a_level >= 0);
00405 CH_assert(a_level < m_grids.size());
00406 CH_assert((a_level == 0) || (a_crsePhiOldPtr != NULL));
00407 CH_assert((a_level == 0) || (a_crsePhiNewPtr != NULL));
00408 CH_assert(a_crseNewTime >= a_crseOldTime);
00409 CH_assert(a_dt >= 0.);
00410
00411 T rhst, srct;
00412 m_ops[a_level]->create(rhst, a_src);
00413 m_ops[a_level]->create(srct, a_phiNew);
00414 m_ops[a_level]->setToZero(srct);
00415 m_ops[a_level]->setToZero(rhst);
00416 m_ops[a_level]->incr(srct, a_src, 1.0);
00417 T coarseData;
00418
00419 if ((a_crsePhiOldPtr != NULL) && (a_level > 0))
00420 {
00421 m_ops[a_level-1]->create(coarseData, *a_crsePhiOldPtr);
00422 setSourceGhostCells(srct, m_grids[a_level]);
00423 }
00424
00425 applyHelm(rhst, srct, NULL, a_level, m_mu4, a_dt, false);
00426
00427 m_ops[a_level]->scale(rhst, a_dt);
00428 incrementFlux(a_flux, srct, a_level, a_dt*m_mu4, a_dt, -1.0, true);
00429
00430
00431 if (a_level > 0)
00432 {
00433 timeInterp(coarseData,
00434 *a_crsePhiOldPtr,
00435 *a_crsePhiNewPtr,
00436 a_oldTime,
00437 a_crseOldTime,
00438 a_crseNewTime,
00439 a_level-1);
00440
00441 }
00442
00443
00444 applyHelm(a_phiNew, a_phiOld, &coarseData, a_level, m_mu3, a_dt, true);
00445
00446 incrementFlux(a_flux, a_phiOld, a_level, m_mu3, a_dt, -1., false);
00447
00448 m_ops[a_level]->incr(rhst, a_phiNew, 1.0);
00449
00450
00451
00452
00453 if(a_level > 0)
00454 {
00455 Real intermediateTime = a_oldTime + (1-m_r1)*a_dt;
00456
00457 timeInterp(coarseData,
00458 *a_crsePhiOldPtr,
00459 *a_crsePhiNewPtr,
00460 intermediateTime,
00461 a_crseOldTime,
00462 a_crseNewTime,
00463 a_level-1);
00464
00465 }
00466
00467 solveHelm(a_phiNew, coarseData, rhst, a_level, m_mu2, a_dt, a_zeroPhi);
00468
00469 incrementFlux(a_flux, a_phiNew, a_level, m_mu2, a_dt, -1.0, false);
00470
00471 m_ops[a_level]->assign(rhst, a_phiNew);
00472
00473
00474
00475 if (a_level > 0)
00476 {
00477 Real newTime = a_oldTime + a_dt;
00478 timeInterp(coarseData,
00479 *a_crsePhiOldPtr,
00480 *a_crsePhiNewPtr,
00481 newTime,
00482 a_crseOldTime,
00483 a_crseNewTime,
00484 a_level-1);
00485 }
00486
00487
00488
00489 solveHelm(a_phiNew, coarseData, rhst, a_level, m_mu1, a_dt, a_zeroPhi);
00490
00491 incrementFlux(a_flux, a_phiNew, a_level, m_mu1, a_dt, -1.0, false);
00492
00493
00494
00495 if ((a_fineFluxRegPtr != NULL) && (a_level > 0))
00496 {
00497 Real fluxMult = 1.0;
00498 for (DataIterator dit = m_grids[a_level].dataIterator(); dit.ok(); ++dit)
00499 {
00500 TFlux& thisFlux = a_flux[dit];
00501 for(int dir=0; dir<SpaceDim; ++dir)
00502 {
00503 a_fineFluxRegPtr->incrementCoarse(thisFlux[dir],
00504 fluxMult, dit(),
00505 intervBase,
00506 intervFlux,
00507 dir);
00508 }
00509 }
00510 }
00511
00512 if ((a_crseFluxRegPtr != NULL) && (a_level > 0))
00513 {
00514 Real fluxMult = 1.0;
00515
00516 for (DataIterator dit = m_grids[a_level].dataIterator(); dit.ok(); ++dit)
00517 {
00518 TFlux& thisFlux = a_flux[dit];
00519 for(int dir=0; dir<SpaceDim; ++dir)
00520 {
00521 a_crseFluxRegPtr->incrementFine(thisFlux[dir],
00522 fluxMult, dit(),
00523 intervBase,
00524 intervFlux,
00525 dir);
00526 }
00527 }
00528 }
00529 }
00530
00531
00532
00533
00534 template <class T, class TFlux, class TFR>
00535 void
00536 BaseLevelTGA<T, TFlux, TFR>::
00537 computeDiffusion(T& a_diffusiveTerm,
00538 T& a_phiOld,
00539 T& a_src,
00540 LevelData<TFlux>& a_flux,
00541 TFR* a_fineFluxRegPtr,
00542 TFR* a_crseFluxRegPtr,
00543 const T* a_crsePhiOldPtr,
00544 const T* a_crsePhiNewPtr,
00545 Real a_oldTime,
00546 Real a_crseOldTime,
00547 Real a_crseNewTime,
00548 Real a_dt,
00549 int a_level)
00550 {
00551
00552 T tempSoln;
00553
00554 m_ops[a_level]->create(tempSoln, a_phiOld);
00555 m_ops[a_level]->setToZero(tempSoln);
00556
00557 updateSoln(tempSoln, a_phiOld, a_src, a_flux,
00558 a_fineFluxRegPtr,
00559 a_crseFluxRegPtr,
00560 a_crsePhiOldPtr,
00561 a_crsePhiNewPtr,
00562 a_oldTime,
00563 a_crseOldTime,
00564 a_crseNewTime, a_dt, a_level);
00565
00566
00567 m_ops[a_level]->incr(tempSoln, a_phiOld, -1.0);
00568 m_ops[a_level]->scale(tempSoln, 1.0/a_dt);
00569
00570
00571 m_ops[a_level]->diagonalScale(tempSoln);
00572
00573
00574 m_ops[a_level]->incr(tempSoln, a_src, -1.0);
00575
00576
00577 m_ops[a_level]->assign(a_diffusiveTerm, tempSoln);
00578 }
00579
00580 #include "NamespaceFooter.H"
00581 #endif