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 "BaseLevelHeatSolver.H"
00025 #include "NamespaceHeader.H"
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 template <class LevelDataType,
00042 class FluxDataType,
00043 class FluxRegisterType>
00044 class BaseLevelTGA : public BaseLevelHeatSolver<LevelDataType, FluxDataType, FluxRegisterType>
00045 {
00046
00047 public:
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 BaseLevelTGA(const Vector<DisjointBoxLayout>& a_grids,
00060 const Vector<int>& a_refRat,
00061 const ProblemDomain& a_level0Domain,
00062 RefCountedPtr<AMRLevelOpFactory<LevelDataType> >& a_opFact,
00063 const RefCountedPtr<AMRMultiGrid<LevelDataType> >& a_solver)
00064 :BaseLevelHeatSolver<LevelDataType,FluxDataType,FluxRegisterType>(a_grids, a_refRat, a_level0Domain, a_opFact, a_solver),
00065 m_mu1(0.0),
00066 m_mu2(0.0),
00067 m_mu3(0.0),
00068 m_mu4(0.0),
00069 m_r1(0.0)
00070 {
00071 Real tgaEpsilon = 1.e-12;
00072 #ifdef CH_USE_FLOAT
00073 tgaEpsilon = sqrt(tgaEpsilon);
00074 #endif
00075 Real a = 2.0 - sqrt(2.0) - tgaEpsilon;
00076 m_mu1 = (a - sqrt( a*a - 4.0*a + 2.0))/2.0 ;
00077 m_mu2 = (a + sqrt( a*a - 4.0*a + 2.0))/2.0 ;
00078 m_mu3 = (1.0 - a);
00079 m_mu4 = 0.5 - a;
00080
00081 Real discr = sqrt(a*a - 4.0*a + 2.0);
00082 m_r1 = (2.0*a - 1.0)/(a + discr);
00083 }
00084
00085
00086 virtual ~BaseLevelTGA()
00087 {
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 void updateSoln(LevelDataType& a_phiNew,
00123 LevelDataType& a_phiOld,
00124 LevelDataType& a_src,
00125 LevelData<FluxDataType>& a_flux,
00126 FluxRegisterType* a_fineFluxRegPtr,
00127 FluxRegisterType* a_crseFluxRegPtr,
00128 const LevelDataType* a_crsePhiOldPtr,
00129 const LevelDataType* a_crsePhiNewPtr,
00130 Real a_oldTime,
00131 Real a_crseOldTime,
00132 Real a_crseNewTime,
00133 Real a_dt,
00134 int a_level,
00135 bool a_zeroPhi = true,
00136 bool a_rhsAlreadyKappaWeighted = false,
00137 int a_fluxStartComponent = 0)
00138 {
00139
00140 if (!this->m_ops[a_level]->isTimeDependent())
00141 {
00142 this->updateSolnWithTimeIndependentOp(a_phiNew, a_phiOld, a_src, a_flux,
00143 a_fineFluxRegPtr, a_crseFluxRegPtr,
00144 a_crsePhiOldPtr, a_crsePhiNewPtr,
00145 a_oldTime, a_crseOldTime, a_crseNewTime,
00146 a_dt, a_level, a_zeroPhi,
00147 a_fluxStartComponent);
00148 return;
00149 }
00150 else
00151 {
00152
00153
00154 this->updateSolnWithTimeDependentOp(a_phiNew, a_phiOld, a_src, a_flux,
00155 a_fineFluxRegPtr, a_crseFluxRegPtr,
00156 a_crsePhiOldPtr, a_crsePhiNewPtr,
00157 a_oldTime, a_crseOldTime, a_crseNewTime,
00158 a_dt, a_level, a_zeroPhi,
00159 a_fluxStartComponent);
00160 return;
00161 }
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 void computeDiffusion(LevelDataType& a_diffusiveTerm,
00202 LevelDataType& a_phiOld,
00203 LevelDataType& a_src,
00204 LevelData<FluxDataType>& a_flux,
00205 FluxRegisterType* a_fineFluxRegPtr,
00206 FluxRegisterType* a_crseFluxRegPtr,
00207 const LevelDataType* a_crsePhiOldPtr,
00208 const LevelDataType* a_crsePhiNewPtr,
00209 Real a_oldTime,
00210 Real a_crseOldTime,
00211 Real a_crseNewTime,
00212 Real a_dt,
00213 int a_level,
00214 bool a_zeroPhi = true,
00215 bool a_rhsAlreadyKappaWeighted = false)
00216 {
00217 CH_TIME("BaseLevelTGA::computeDiffusion");
00218
00219
00220
00221
00222 if (!this->m_ops[a_level]->isTimeDependent())
00223 {
00224
00225
00226
00227 LevelDataType phiNew;
00228
00229 this->m_ops[a_level]->create(phiNew, a_phiOld);
00230 this->m_ops[a_level]->setToZero(phiNew);
00231 if (!a_zeroPhi)
00232 {
00233 this->m_ops[a_level]->assignLocal(phiNew, a_phiOld);
00234 }
00235
00236 updateSoln(phiNew, a_phiOld, a_src, a_flux,
00237 a_fineFluxRegPtr, a_crseFluxRegPtr,
00238 a_crsePhiOldPtr, a_crsePhiNewPtr,
00239 a_oldTime, a_crseOldTime,
00240 a_crseNewTime, a_dt, a_level, a_zeroPhi, a_rhsAlreadyKappaWeighted);
00241
00242
00243 this->m_ops[a_level]->incr(phiNew, a_phiOld, -1.0);
00244 this->m_ops[a_level]->scale(phiNew, 1.0/a_dt);
00245
00246
00247 this->m_ops[a_level]->diagonalScale(phiNew, false);
00248
00249
00250 this->m_ops[a_level]->incr(phiNew, a_src, -1.0);
00251
00252
00253 this->m_ops[a_level]->assignLocal(a_diffusiveTerm, phiNew);
00254 }
00255 else
00256 {
00257
00258
00259
00260
00261
00262
00263
00264 LevelDataType phidadt, aOld, aNew, rhs;
00265 this->m_ops[a_level]->create(phidadt, a_phiOld);
00266 this->m_ops[a_level]->create(aOld, a_phiOld);
00267 this->m_ops[a_level]->create(aNew, a_phiOld);
00268 this->m_ops[a_level]->create(rhs, a_phiOld);
00269 for (DataIterator dit = a_phiOld.disjointBoxLayout().dataIterator(); dit.ok(); ++dit)
00270 {
00271
00272 this->m_ops[a_level]->setTime(a_oldTime, 0.0, a_dt);
00273 aOld[dit()].setVal(1.);
00274 this->m_ops[a_level]->diagonalScale(aOld);
00275 this->m_ops[a_level]->setTime(a_oldTime, 1.0, a_dt);
00276 aNew[dit()].setVal(1.);
00277 this->m_ops[a_level]->diagonalScale(aNew);
00278
00279
00280 phidadt[dit()].axby(aNew[dit()], aOld[dit()], 1.0/a_dt, -1.0/a_dt);
00281 phidadt[dit()] *= a_phiOld[dit()];
00282
00283
00284
00285 rhs[dit()].axby(a_src[dit()], phidadt[dit()], 1.0, -1.0);
00286 }
00287
00288
00289 LevelDataType phiNew;
00290 this->m_ops[a_level]->create(phiNew, a_phiOld);
00291 this->m_ops[a_level]->setToZero(phiNew);
00292 if (!a_zeroPhi)
00293 {
00294 this->m_ops[a_level]->assignLocal(phiNew, a_phiOld);
00295 }
00296 updateSoln(phiNew, a_phiOld, rhs, a_flux,
00297 a_fineFluxRegPtr, a_crseFluxRegPtr,
00298 a_crsePhiOldPtr, a_crsePhiNewPtr,
00299 a_oldTime, a_crseOldTime,
00300 a_crseNewTime, a_dt, a_level, a_zeroPhi);
00301
00302
00303
00304
00305
00306 for (DataIterator dit = a_phiOld.disjointBoxLayout().dataIterator(); dit.ok(); ++dit)
00307 {
00308 aNew[dit()] *= phiNew[dit()];
00309 aOld[dit()] *= a_phiOld[dit()];
00310 a_diffusiveTerm[dit()].axby(aNew[dit()], aOld[dit()], 1.0/a_dt, -1.0/a_dt);
00311 a_diffusiveTerm[dit()] -= a_src[dit()];
00312 }
00313 }
00314 }
00315
00316 protected:
00317
00318
00319
00320
00321
00322
00323
00324 virtual void setSourceGhostCells(LevelDataType& a_src,
00325 const DisjointBoxLayout& a_dbl,
00326 int a_level) = 0;
00327
00328
00329
00330 Real m_mu1, m_mu2, m_mu3, m_mu4, m_r1;
00331
00332 private:
00333
00334
00335
00336 void updateSolnWithTimeIndependentOp(LevelDataType& a_phiNew,
00337 LevelDataType& a_phiOld,
00338 LevelDataType& a_src,
00339 LevelData<FluxDataType>& a_flux,
00340 FluxRegisterType* a_fineFluxRegPtr,
00341 FluxRegisterType* a_crseFluxRegPtr,
00342 const LevelDataType* a_crsePhiOldPtr,
00343 const LevelDataType* a_crsePhiNewPtr,
00344 Real a_oldTime,
00345 Real a_crseOldTime,
00346 Real a_crseNewTime,
00347 Real a_dt,
00348 int a_level,
00349 bool a_zeroPhi = true,
00350 int a_fluxStartComponent = 0)
00351 {
00352 CH_TIME("BaseLevelTGA::updateWithTimeIndependentOp");
00353
00354 CH_assert(!this->m_ops[a_level]->isTimeDependent());
00355 int ncomp = a_phiNew.nComp();
00356 Interval intervBase(0, ncomp-1);
00357 Interval intervFlux(a_fluxStartComponent, a_fluxStartComponent + ncomp-1);
00358
00359 CH_assert(a_level >= 0);
00360 CH_assert(a_level < this->m_grids.size());
00361 CH_assert((a_level == 0) || (a_crsePhiOldPtr != NULL));
00362 CH_assert((a_level == 0) || (a_crsePhiNewPtr != NULL));
00363 CH_assert(a_crseNewTime >= a_crseOldTime);
00364 CH_assert(a_dt >= 0.);
00365
00366 LevelDataType rhst, srct, phis;
00367 this->m_ops[a_level]->create(rhst, a_src);
00368 this->m_ops[a_level]->create(srct, a_phiNew);
00369 this->m_ops[a_level]->create(phis, a_phiNew);
00370
00371 this->m_ops[a_level]->setToZero(srct);
00372 this->m_ops[a_level]->setToZero(rhst);
00373
00374 this->m_ops[a_level]->incr(srct, a_src, a_dt);
00375
00376
00377 if (!a_zeroPhi)
00378 {
00379 this->m_ops[a_level]->setToZero(phis);
00380 this->m_ops[a_level]->incr(phis, a_phiNew, 1.0);
00381 }
00382
00383
00384 this->m_ops[a_level]->divideByIdentityCoef(srct);
00385
00386 LevelDataType coarseData;
00387
00388 if ((a_crsePhiOldPtr != NULL) && (a_level > 0))
00389 {
00390 this->m_ops[a_level-1]->create(coarseData, *a_crsePhiOldPtr);
00391 setSourceGhostCells(srct, this->m_grids[a_level], a_level);
00392 }
00393
00394
00395
00396 this->applyHelm(rhst, srct, NULL, a_level, m_mu4, a_dt, true);
00397 this->incrementFlux(a_flux, srct, a_level, m_mu4, a_dt, -1.0, true);
00398
00399
00400 if (a_level > 0)
00401 {
00402 this->timeInterp(coarseData, *a_crsePhiOldPtr, *a_crsePhiNewPtr,
00403 a_oldTime, a_crseOldTime, a_crseNewTime, a_level-1);
00404 }
00405
00406
00407
00408 this->applyHelm(a_phiNew, a_phiOld, &coarseData, a_level, m_mu3, a_dt, false);
00409 this->incrementFlux(a_flux, a_phiOld, a_level, m_mu3, a_dt, -1., false);
00410
00411
00412 this->m_ops[a_level]->incr(rhst, a_phiNew, 1.0);
00413
00414
00415
00416 if (a_level > 0)
00417 {
00418 Real intermediateTime = a_oldTime + (1.0-m_r1)*a_dt;
00419
00420 this->timeInterp(coarseData, *a_crsePhiOldPtr, *a_crsePhiNewPtr,
00421 intermediateTime, a_crseOldTime, a_crseNewTime, a_level-1);
00422 }
00423
00424
00425 if (!a_zeroPhi)
00426 {
00427 this->m_ops[a_level]->setToZero(a_phiNew);
00428 this->m_ops[a_level]->incr(a_phiNew, phis, 1.0);
00429 }
00430
00431
00432
00433 this->solveHelm(a_phiNew, coarseData, rhst, a_level, m_mu2, a_dt, a_zeroPhi);
00434 this->incrementFlux(a_flux, a_phiNew, a_level, m_mu2, a_dt, -1.0, false);
00435
00436
00437 this->m_ops[a_level]->assignLocal(rhst, a_phiNew);
00438
00439
00440 if (a_level > 0)
00441 {
00442 Real newTime = a_oldTime + a_dt;
00443 this->timeInterp(coarseData, *a_crsePhiOldPtr, *a_crsePhiNewPtr,
00444 newTime, a_crseOldTime, a_crseNewTime, a_level-1);
00445 }
00446
00447
00448
00449 this->m_ops[a_level]->diagonalScale(rhst, true);
00450
00451
00452 if (!a_zeroPhi)
00453 {
00454 this->m_ops[a_level]->setToZero(a_phiNew);
00455 this->m_ops[a_level]->incr(a_phiNew, phis, 1.0);
00456 }
00457
00458
00459 this->solveHelm(a_phiNew, coarseData, rhst, a_level, m_mu1, a_dt, a_zeroPhi);
00460 this->incrementFlux(a_flux, a_phiNew, a_level, m_mu1, a_dt, -1.0, false);
00461
00462
00463
00464
00465 if ((a_fineFluxRegPtr != NULL) && (a_level < this->m_grids.size()-1))
00466 {
00467 Real fluxMult = 1.0;
00468 for (DataIterator dit = this->m_grids[a_level].dataIterator(); dit.ok(); ++dit)
00469 {
00470 FluxDataType& thisFlux = a_flux[dit];
00471 for (int dir=0; dir<SpaceDim; ++dir)
00472 {
00473 a_fineFluxRegPtr->incrementCoarse(thisFlux[dir],
00474 fluxMult, dit(),
00475 intervBase,
00476 intervFlux,
00477 dir);
00478 }
00479 }
00480 }
00481
00482 if ((a_crseFluxRegPtr != NULL) && (a_level > 0))
00483 {
00484 Real fluxMult = 1.0;
00485
00486 for (DataIterator dit = this->m_grids[a_level].dataIterator(); dit.ok(); ++dit)
00487 {
00488 FluxDataType& thisFlux = a_flux[dit];
00489 for (int dir=0; dir<SpaceDim; ++dir)
00490 {
00491 a_crseFluxRegPtr->incrementFine(thisFlux[dir], fluxMult, dit(),
00492 intervBase,
00493 intervFlux,
00494 dir);
00495 }
00496 }
00497 }
00498
00499 }
00500
00501
00502
00503 void updateSolnWithTimeDependentOp(LevelDataType& a_phiNew,
00504 LevelDataType& a_phiOld,
00505 LevelDataType& a_src,
00506 LevelData<FluxDataType>& a_flux,
00507 FluxRegisterType* a_fineFluxRegPtr,
00508 FluxRegisterType* a_crseFluxRegPtr,
00509 const LevelDataType* a_crsePhiOldPtr,
00510 const LevelDataType* a_crsePhiNewPtr,
00511 Real a_oldTime,
00512 Real a_crseOldTime,
00513 Real a_crseNewTime,
00514 Real a_dt,
00515 int a_level,
00516 bool a_zeroPhi = true,
00517 int a_fluxStartComponent = 0)
00518 {
00519 CH_TIME("BaseLevelTGA::updateWithTimeDependentOp");
00520 int ncomp = a_phiNew.nComp();
00521 Interval intervBase(0, ncomp-1);
00522 Interval intervFlux(a_fluxStartComponent, a_fluxStartComponent + ncomp-1);
00523
00524 CH_assert(a_level >= 0);
00525 CH_assert(a_level < this->m_grids.size());
00526 CH_assert((a_level == 0) || (a_crsePhiOldPtr != NULL));
00527 CH_assert((a_level == 0) || (a_crsePhiNewPtr != NULL));
00528 CH_assert(a_crseNewTime >= a_crseOldTime);
00529 CH_assert(a_dt >= 0.);
00530
00531 LevelDataType rhst, srct, phis;
00532 this->m_ops[a_level]->create(rhst, a_src);
00533 this->m_ops[a_level]->create(srct, a_phiNew);
00534 this->m_ops[a_level]->create(phis, a_phiNew);
00535
00536 this->m_ops[a_level]->setToZero(srct);
00537 this->m_ops[a_level]->setToZero(rhst);
00538 this->m_ops[a_level]->incr(srct, a_src, 1.0);
00539
00540
00541 if (!a_zeroPhi)
00542 {
00543 this->m_ops[a_level]->setToZero(phis);
00544 this->m_ops[a_level]->incr(phis, a_phiNew, 1.0);
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 this->m_ops[a_level]->setTime(a_oldTime, 0.5, a_dt);
00567
00568
00569
00570 this->m_ops[a_level]->divideByIdentityCoef(srct);
00571
00572
00573 LevelDataType coarseData;
00574 if ((a_crsePhiOldPtr != NULL) && (a_level > 0))
00575 {
00576 this->m_ops[a_level-1]->create(coarseData, *a_crsePhiOldPtr);
00577 setSourceGhostCells(srct, this->m_grids[a_level], a_level);
00578 }
00579
00580
00581
00582
00583
00584
00585 this->applyHelm(rhst, srct, NULL, a_level, m_mu4, a_dt, true);
00586 this->incrementFlux(a_flux, srct, a_level, a_dt*m_mu4, a_dt, -1.0, true);
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 if (a_level > 0)
00597 {
00598 this->timeInterp(coarseData, *a_crsePhiOldPtr, *a_crsePhiNewPtr,
00599 a_oldTime, a_crseOldTime, a_crseNewTime, a_level-1);
00600 }
00601
00602
00603 this->m_ops[a_level]->setTime(a_oldTime, 0.0, a_dt);
00604
00605
00606
00607
00608
00609
00610 this->applyHelm(a_phiNew, a_phiOld, &coarseData, a_level, m_mu3, a_dt, false);
00611 this->incrementFlux(a_flux, a_phiOld, a_level, m_mu3, a_dt, -1., false);
00612
00613
00614
00615 this->m_ops[a_level]->divideByIdentityCoef(a_phiNew);
00616
00617
00618
00619 this->m_ops[a_level]->incr(rhst, a_phiNew, 1.0);
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 if (a_level > 0)
00630 {
00631 Real intermediateTime = a_oldTime + (1.0-m_r1)*a_dt;
00632
00633 this->timeInterp(coarseData, *a_crsePhiOldPtr, *a_crsePhiNewPtr,
00634 intermediateTime, a_crseOldTime, a_crseNewTime, a_level-1);
00635 }
00636
00637
00638 if (!a_zeroPhi)
00639 {
00640 this->m_ops[a_level]->setToZero(a_phiNew);
00641 this->m_ops[a_level]->incr(a_phiNew, phis, 1.0);
00642 }
00643
00644
00645
00646 this->m_ops[a_level]->setTime(a_oldTime, 1.0 - m_r1, a_dt);
00647
00648
00649
00650 this->m_ops[a_level]->diagonalScale(rhst, false);
00651
00652
00653
00654 this->solveHelm(a_phiNew, coarseData, rhst, a_level, m_mu2, a_dt, a_zeroPhi);
00655 this->incrementFlux(a_flux, a_phiNew, a_level, m_mu2, a_dt, -1.0, false);
00656
00657
00658 this->m_ops[a_level]->assignLocal(rhst, a_phiNew);
00659
00660
00661
00662
00663
00664
00665
00666 if (a_level > 0)
00667 {
00668 Real newTime = a_oldTime + a_dt;
00669 this->timeInterp(coarseData, *a_crsePhiOldPtr, *a_crsePhiNewPtr,
00670 newTime, a_crseOldTime, a_crseNewTime, a_level-1);
00671 }
00672
00673
00674 this->m_ops[a_level]->setTime(a_oldTime, 1.0, a_dt);
00675
00676
00677
00678 this->m_ops[a_level]->diagonalScale(rhst);
00679
00680
00681 if (!a_zeroPhi)
00682 {
00683 this->m_ops[a_level]->setToZero(a_phiNew);
00684 this->m_ops[a_level]->incr(a_phiNew, phis, 1.0);
00685 }
00686
00687
00688
00689 this->solveHelm(a_phiNew, coarseData, rhst, a_level, m_mu1, a_dt, a_zeroPhi);
00690 this->incrementFlux(a_flux, a_phiNew, a_level, m_mu1, a_dt, -1.0, false);
00691
00692
00693
00694
00695 if ((a_fineFluxRegPtr != NULL) && (a_level < this->m_grids.size()-1))
00696 {
00697 Real fluxMult = 1.0;
00698 for (DataIterator dit = this->m_grids[a_level].dataIterator(); dit.ok(); ++dit)
00699 {
00700 FluxDataType& thisFlux = a_flux[dit];
00701 for (int dir=0; dir<SpaceDim; ++dir)
00702 {
00703 a_fineFluxRegPtr->incrementCoarse(thisFlux[dir],
00704 fluxMult, dit(),
00705 intervBase,
00706 intervFlux,
00707 dir);
00708 }
00709 }
00710 }
00711
00712 if ((a_crseFluxRegPtr != NULL) && (a_level > 0))
00713 {
00714 Real fluxMult = 1.0;
00715
00716 for (DataIterator dit = this->m_grids[a_level].dataIterator(); dit.ok(); ++dit)
00717 {
00718 FluxDataType& thisFlux = a_flux[dit];
00719 for (int dir=0; dir<SpaceDim; ++dir)
00720 {
00721 a_crseFluxRegPtr->incrementFine(thisFlux[dir], fluxMult, dit(),
00722 intervBase,
00723 intervFlux,
00724 dir);
00725 }
00726 }
00727 }
00728 }
00729
00730 private:
00731
00732
00733 BaseLevelTGA& operator=(const BaseLevelTGA&);
00734 BaseLevelTGA(const BaseLevelTGA& a_opin);
00735 BaseLevelTGA();
00736 };
00737
00738 #include "NamespaceFooter.H"
00739
00740 #endif