00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <winstd.H>
00027
00028 #include <algorithm>
00029
00030 #if defined(BL_OLD_STL)
00031 #include <float.h>
00032 #else
00033 #include <cfloat>
00034 #endif
00035
00036 #include <iostream>
00037 #include <iomanip>
00038 #include <list>
00039 #include <limits>
00040
00041 #include <BLassert.H>
00042 #include <MultiFab.H>
00043 #include <ParallelDescriptor.H>
00044
00045 void
00046 MultiFab::Copy (MultiFab& dst,
00047 const MultiFab& src,
00048 int srccomp,
00049 int dstcomp,
00050 int numcomp,
00051 int nghost)
00052 {
00053 if (dst.boxArray()!=src.boxArray())
00054 BoxLib::Error("dstBA<>srcBA");
00055 if (dst.distributionMap != src.distributionMap)
00056 BoxLib::Error("dstMap<>srcMap");
00057 if ((dst.nGrow() < nghost)||(src.nGrow() < nghost))
00058 BoxLib::Error("nGrow<nghost");
00059
00060 BL_ASSERT(dst.boxArray() == src.boxArray());
00061 BL_ASSERT(dst.distributionMap == src.distributionMap);
00062 BL_ASSERT(dst.nGrow() >= nghost && src.nGrow() >= nghost);
00063
00064 for (MFIter mfi(dst); mfi.isValid(); ++mfi)
00065 {
00066 Box bx = BoxLib::grow(mfi.validbox(),nghost);
00067
00068 if (bx.ok())
00069 dst[mfi].copy(src[mfi], bx, srccomp, bx, dstcomp, numcomp);
00070 else
00071 BoxLib::Error("bx not ok");
00072 }
00073 }
00074
00075 void
00076 MultiFab::FillBoundary ()
00077 {
00078 FillBoundary(0, n_comp);
00079 }
00080
00081 void
00082 MultiFab::plus (Real val,
00083 int nghost)
00084 {
00085 plus(val,0,n_comp,nghost);
00086 }
00087
00088 void
00089 MultiFab::plus (Real val,
00090 const Box& region,
00091 int nghost)
00092 {
00093 plus(val,region,0,n_comp,nghost);
00094 }
00095
00096 void
00097 MultiFab::mult (Real val,
00098 int nghost)
00099 {
00100 mult(val,0,n_comp,nghost);
00101 }
00102
00103 void
00104 MultiFab::mult (Real val,
00105 const Box& region,
00106 int nghost)
00107 {
00108 mult(val,region,0,n_comp,nghost);
00109 }
00110
00111 void
00112 MultiFab::invert (Real numerator,
00113 int nghost)
00114 {
00115 invert(numerator,0,n_comp,nghost);
00116 }
00117
00118 void
00119 MultiFab::invert (Real numerator,
00120 const Box& region,
00121 int nghost)
00122 {
00123 invert(numerator,region,0,n_comp,nghost);
00124 }
00125
00126 void
00127 MultiFab::negate (int nghost)
00128 {
00129 negate(0,n_comp,nghost);
00130 }
00131
00132 void
00133 MultiFab::negate (const Box& region,
00134 int nghost)
00135 {
00136 negate(region,0,n_comp,nghost);
00137 }
00138
00139 MultiFab::MultiFab () {}
00140
00141 MultiFab::MultiFab (const BoxArray& bxs,
00142 int ncomp,
00143 int ngrow,
00144 FabAlloc alloc)
00145 :
00146 FabArray<FArrayBox>(bxs,ncomp,ngrow,alloc)
00147 {}
00148
00149 MultiFab::MultiFab (const BoxArray& bxs,
00150 int ncomp,
00151 int ngrow,
00152 const DistributionMapping& dm,
00153 FabAlloc alloc)
00154 :
00155 FabArray<FArrayBox>(bxs,ncomp,ngrow,dm,alloc)
00156 {}
00157
00158 void
00159 MultiFab::operator= (const Real& r)
00160 {
00161 setVal(r);
00162 }
00163
00164 Real
00165 MultiFab::min (int comp,
00166 int nghost) const
00167 {
00168 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00169
00170 Real mn = std::numeric_limits<Real>::max();
00171
00172 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00173 {
00174 mn = std::min(mn,get(mfi).min(BoxLib::grow(mfi.validbox(),nghost),comp));
00175 }
00176
00177 ParallelDescriptor::ReduceRealMin(mn);
00178
00179 return mn;
00180 }
00181
00182 Real
00183 MultiFab::min (const Box& region,
00184 int comp,
00185 int nghost) const
00186 {
00187 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00188
00189 Real mn = std::numeric_limits<Real>::max();
00190
00191 for ( MFIter mfi(*this); mfi.isValid(); ++mfi)
00192 {
00193 Box b = BoxLib::grow(mfi.validbox(),nghost) & region;
00194
00195 if (b.ok())
00196 mn = std::min(mn, get(mfi).min(b,comp));
00197 }
00198
00199 ParallelDescriptor::ReduceRealMin(mn);
00200
00201 return mn;
00202 }
00203
00204 Real
00205 MultiFab::max (int comp,
00206 int nghost) const
00207 {
00208 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00209
00210 Real mn = -std::numeric_limits<Real>::max();
00211
00212 for ( MFIter mfi(*this); mfi.isValid(); ++mfi)
00213 {
00214 mn = std::max(mn, get(mfi).max(BoxLib::grow(mfi.validbox(),nghost),comp));
00215 }
00216
00217 ParallelDescriptor::ReduceRealMax(mn);
00218
00219 return mn;
00220 }
00221
00222 Real
00223 MultiFab::max (const Box& region,
00224 int comp,
00225 int nghost) const
00226 {
00227 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00228
00229 Real mn = -std::numeric_limits<Real>::max();
00230
00231 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00232 {
00233 Box b = BoxLib::grow(mfi.validbox(),nghost) & region;
00234
00235 if (b.ok())
00236 mn = std::max(mn, get(mfi).max(b,comp));
00237 }
00238
00239 ParallelDescriptor::ReduceRealMax(mn);
00240
00241 return mn;
00242 }
00243
00244 void
00245 MultiFab::minus (const MultiFab& mf,
00246 int strt_comp,
00247 int num_comp,
00248 int nghost)
00249 {
00250 BL_ASSERT(boxarray == mf.boxarray);
00251 BL_ASSERT(strt_comp >= 0);
00252 #ifndef NDEBUG
00253 int lst_comp = strt_comp + num_comp - 1;
00254 #endif
00255 BL_ASSERT(lst_comp < n_comp && lst_comp < mf.n_comp);
00256 BL_ASSERT(nghost <= n_grow && nghost <= mf.n_grow);
00257
00258 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00259 {
00260 Box bx = BoxLib::grow(mfi.validbox(),nghost);
00261
00262 get(mfi).minus(mf[mfi], bx, strt_comp, strt_comp, num_comp);
00263 }
00264 }
00265
00266 void
00267 MultiFab::plus (Real val,
00268 int comp,
00269 int num_comp,
00270 int nghost)
00271 {
00272 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00273 BL_ASSERT(comp+num_comp <= n_comp);
00274
00275 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00276 {
00277 get(mfi).plus(val,BoxLib::grow(mfi.validbox(),nghost),comp,num_comp);
00278 }
00279 }
00280
00281 void
00282 MultiFab::plus (Real val,
00283 const Box& region,
00284 int comp,
00285 int num_comp,
00286 int nghost)
00287 {
00288 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00289 BL_ASSERT(comp+num_comp <= n_comp);
00290
00291 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00292 {
00293 Box b = BoxLib::grow(mfi.validbox(),nghost) & region;
00294
00295 if (b.ok())
00296 get(mfi).plus(val,b,comp,num_comp);
00297 }
00298 }
00299
00300 void
00301 MultiFab::plus (const MultiFab& mf,
00302 int strt_comp,
00303 int num_comp,
00304 int nghost)
00305 {
00306 BL_ASSERT(boxarray == mf.boxarray);
00307 BL_ASSERT(strt_comp >= 0);
00308 #ifndef NDEBUG
00309 int lst_comp = strt_comp + num_comp - 1;
00310 #endif
00311 BL_ASSERT(lst_comp < n_comp && lst_comp < mf.n_comp);
00312 BL_ASSERT(nghost <= n_grow && nghost <= mf.n_grow);
00313
00314 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00315 {
00316 Box bx = BoxLib::grow(mfi.validbox(),nghost);
00317
00318 get(mfi).plus(mf[mfi], bx, strt_comp, strt_comp, num_comp);
00319 }
00320 }
00321
00322 void
00323 MultiFab::mult (Real val,
00324 int comp,
00325 int num_comp,
00326 int nghost)
00327 {
00328 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00329 BL_ASSERT(comp+num_comp <= n_comp);
00330
00331 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00332 {
00333 get(mfi).mult(val, BoxLib::grow(mfi.validbox(),nghost),comp,num_comp);
00334 }
00335 }
00336
00337 void
00338 MultiFab::mult (Real val,
00339 const Box& region,
00340 int comp,
00341 int num_comp,
00342 int nghost)
00343 {
00344 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00345 BL_ASSERT(comp+num_comp <= n_comp);
00346
00347 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00348 {
00349 Box b = BoxLib::grow(mfi.validbox(),nghost) & region;
00350
00351 if (b.ok())
00352 get(mfi).mult(val, b, comp, num_comp);
00353 }
00354 }
00355
00356 void
00357 MultiFab::invert (Real numerator,
00358 int comp,
00359 int num_comp,
00360 int nghost)
00361 {
00362 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00363 BL_ASSERT(comp+num_comp <= n_comp);
00364
00365 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00366 {
00367 get(mfi).invert(numerator, BoxLib::grow(mfi.validbox(),nghost),comp,num_comp);
00368 }
00369 }
00370
00371 void
00372 MultiFab::invert (Real numerator,
00373 const Box& region,
00374 int comp,
00375 int num_comp,
00376 int nghost)
00377 {
00378 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00379 BL_ASSERT(comp+num_comp <= n_comp);
00380
00381 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00382 {
00383 Box b = BoxLib::grow(mfi.validbox(),nghost) & region;
00384
00385 if (b.ok())
00386 get(mfi).invert(numerator,b,comp,num_comp);
00387 }
00388 }
00389
00390 void
00391 MultiFab::negate (int comp,
00392 int num_comp,
00393 int nghost)
00394 {
00395 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00396 BL_ASSERT(comp+num_comp <= n_comp);
00397
00398 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00399 {
00400 get(mfi).negate(BoxLib::grow(mfi.validbox(),nghost),comp,num_comp);
00401 }
00402 }
00403
00404 void
00405 MultiFab::negate (const Box& region,
00406 int comp,
00407 int num_comp,
00408 int nghost)
00409 {
00410 BL_ASSERT(nghost >= 0 && nghost <= n_grow);
00411 BL_ASSERT(comp+num_comp <= n_comp);
00412
00413 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
00414 {
00415 Box b = BoxLib::grow(mfi.validbox(),nghost) & region;
00416
00417 if (b.ok())
00418 get(mfi).negate(b,comp,num_comp);
00419 }
00420 }
00421
00422 void
00423 BoxLib::linInterpAddBox (MultiFabCopyDescriptor& fabCopyDesc,
00424 BoxList* returnUnfilledBoxes,
00425 Array<FillBoxId>& returnedFillBoxIds,
00426 const Box& subbox,
00427 const MultiFabId& faid1,
00428 const MultiFabId& faid2,
00429 Real t1,
00430 Real t2,
00431 Real t,
00432 int src_comp,
00433 int dest_comp,
00434 int num_comp,
00435 bool extrap)
00436 {
00437 const Real teps = (t2-t1)/1000.0;
00438
00439 if ( (!extrap)&&((t<t1-teps)||(t>t2+teps)) ) {
00440 std::cout << "t,t1,t2,teps " << t << ' ' << t1 << ' ' << t2 << ' ' <<
00441 teps << '\n';
00442 BoxLib::Error("t out of range in linInterpAddBox");
00443 }
00444
00445 if (t >= t1-teps && t <= t1+teps)
00446 {
00447 returnedFillBoxIds.resize(1);
00448 returnedFillBoxIds[0] = fabCopyDesc.AddBox(faid1,
00449 subbox,
00450 returnUnfilledBoxes,
00451 src_comp,
00452 dest_comp,
00453 num_comp);
00454 }
00455 else if (t > t2-teps && t < t2+teps)
00456 {
00457 returnedFillBoxIds.resize(1);
00458 returnedFillBoxIds[0] = fabCopyDesc.AddBox(faid2,
00459 subbox,
00460 returnUnfilledBoxes,
00461 src_comp,
00462 dest_comp,
00463 num_comp);
00464 }
00465 else
00466 {
00467 returnedFillBoxIds.resize(2);
00468 BoxList tempUnfilledBoxes(subbox.ixType());
00469 returnedFillBoxIds[0] = fabCopyDesc.AddBox(faid1,
00470 subbox,
00471 returnUnfilledBoxes,
00472 src_comp,
00473 dest_comp,
00474 num_comp);
00475 returnedFillBoxIds[1] = fabCopyDesc.AddBox(faid2,
00476 subbox,
00477 &tempUnfilledBoxes,
00478 src_comp,
00479 dest_comp,
00480 num_comp);
00481
00482
00483
00484
00485 }
00486 }
00487
00488 void
00489 BoxLib::linInterpFillFab (MultiFabCopyDescriptor& fabCopyDesc,
00490 const Array<FillBoxId>& fillBoxIds,
00491 const MultiFabId& faid1,
00492 const MultiFabId& faid2,
00493 FArrayBox& dest,
00494 Real t1,
00495 Real t2,
00496 Real t,
00497 int src_comp,
00498 int dest_comp,
00499 int num_comp,
00500 bool extrap)
00501 {
00502 const Real teps = (t2-t1)/1000.0;
00503
00504 BL_ASSERT(extrap || ( (t>=t1-teps) && (t <= t2+teps) ) );
00505
00506 if (t >= t1-teps && t <= t1+teps)
00507 {
00508 fabCopyDesc.FillFab(faid1, fillBoxIds[0], dest);
00509 }
00510 else if (t > t2-teps && t < t2+teps)
00511 {
00512 fabCopyDesc.FillFab(faid2, fillBoxIds[0], dest);
00513 }
00514 else
00515 {
00516 BL_ASSERT(dest_comp + num_comp <= dest.nComp());
00517
00518 FArrayBox dest1(dest.box(), dest.nComp());
00519 dest1.setVal(Real(1.e30));
00520 FArrayBox dest2(dest.box(), dest.nComp());
00521 dest2.setVal(Real(1.e30));
00522 fabCopyDesc.FillFab(faid1, fillBoxIds[0], dest1);
00523 fabCopyDesc.FillFab(faid2, fillBoxIds[1], dest2);
00524 dest.linInterp(dest1,
00525 dest1.box(),
00526 src_comp,
00527 dest2,
00528 dest2.box(),
00529 src_comp,
00530 t1,
00531 t2,
00532 t,
00533 dest.box(),
00534 dest_comp,
00535 num_comp);
00536 }
00537 }
00538
00539
00540
00541
00542
00543 struct SIRec
00544 {
00545 SIRec ()
00546 :
00547 m_i(-1),
00548 m_j(-1) {}
00549
00550 SIRec (int i,
00551 int j,
00552 const Box& bx)
00553 :
00554 m_i(i),
00555 m_j(j),
00556 m_bx(bx)
00557 {
00558 BL_ASSERT(i >= 0);
00559 BL_ASSERT(j >= 0);
00560 }
00561
00562 SIRec (const SIRec& rhs)
00563 :
00564 m_i(rhs.m_i),
00565 m_j(rhs.m_j),
00566 m_bx(rhs.m_bx),
00567 m_fbid(rhs.m_fbid) {}
00568
00569 int m_i;
00570 int m_j;
00571 Box m_bx;
00572 FillBoxId m_fbid;
00573 };
00574
00575
00576
00577
00578
00579 struct SI
00580 {
00581 SI ();
00582
00583 SI (const BoxArray& ba,
00584 int scomp,
00585 int ncomp,
00586 int ngrow);
00587
00588 SI (const SI& rhs);
00589
00590 ~SI ();
00591
00592 bool operator== (const SI& rhs) const;
00593 bool operator!= (const SI& rhs) const;
00594
00595 Array<int> m_cache;
00596 CommDataCache m_commdata;
00597 std::vector<SIRec> m_sirec;
00598 BoxArray m_ba;
00599 int m_scomp;
00600 int m_ncomp;
00601 int m_ngrow;
00602 };
00603
00604 inline
00605 SI::SI ()
00606 :
00607 m_scomp(-1),
00608 m_ncomp(-1),
00609 m_ngrow(-1)
00610 {}
00611
00612 inline
00613 SI::SI (const BoxArray& ba,
00614 int scomp,
00615 int ncomp,
00616 int ngrow)
00617 :
00618 m_ba(ba),
00619 m_scomp(scomp),
00620 m_ncomp(ncomp),
00621 m_ngrow(ngrow)
00622 {
00623 BL_ASSERT(ncomp > 0);
00624 BL_ASSERT(scomp >= 0);
00625 BL_ASSERT(ngrow >= 0);
00626 }
00627
00628 inline
00629 SI::SI (const SI& rhs)
00630 :
00631 m_cache(rhs.m_cache),
00632 m_commdata(rhs.m_commdata),
00633 m_sirec(rhs.m_sirec),
00634 m_ba(rhs.m_ba),
00635 m_scomp(rhs.m_scomp),
00636 m_ncomp(rhs.m_ncomp),
00637 m_ngrow(rhs.m_ngrow)
00638 {}
00639
00640 inline
00641 SI::~SI () {}
00642
00643 inline
00644 bool
00645 SI::operator== (const SI& rhs) const
00646 {
00647 return
00648 m_scomp == rhs.m_scomp &&
00649 m_ncomp == rhs.m_ncomp &&
00650 m_ngrow == rhs.m_ngrow &&
00651 m_ba == rhs.m_ba;
00652 }
00653
00654 inline
00655 bool
00656 SI::operator!= (const SI& rhs) const
00657 {
00658 return !operator==(rhs);
00659 }
00660
00661
00662
00663
00664 typedef std::list<SI> SIList;
00665
00666
00667
00668
00669 static SIList SICache;
00670
00671 void
00672 MultiFab::FlushSICache ()
00673 {
00674 SICache.clear();
00675 }
00676
00677 int
00678 MultiFab::SICacheSize ()
00679 {
00680 return SICache.size();
00681 }
00682
00683 static
00684 SI&
00685 BuildFBsirec (const SI& si,
00686 const MultiFab& mf)
00687 {
00688 BL_ASSERT(si.m_ncomp > 0);
00689 BL_ASSERT(si.m_scomp >= 0);
00690 BL_ASSERT(si.m_ngrow >= 0);
00691 BL_ASSERT(mf.nGrow() == si.m_ngrow);
00692 BL_ASSERT(mf.boxArray() == si.m_ba);
00693
00694
00695
00696 SICache.push_front(si);
00697
00698
00699
00700 const BoxArray& ba = mf.boxArray();
00701 const DistributionMapping& DMap = mf.DistributionMap();
00702 const int MyProc = ParallelDescriptor::MyProc();
00703 std::vector<SIRec>& sirec = SICache.front().m_sirec;
00704 Array<int>& cache = SICache.front().m_cache;
00705
00706 cache.resize(ParallelDescriptor::NProcs(),0);
00707
00708 for (MFIter mfi(mf); mfi.isValid(); ++mfi)
00709 {
00710 const int i = mfi.index();
00711
00712 for (int j = 0; j < mf.size(); j++)
00713 {
00714 if (i != j)
00715 {
00716 if (ba[j].intersects(mf[mfi].box()))
00717 {
00718 Box bx = ba[j] & mf[mfi].box();
00719
00720 sirec.push_back(SIRec(i,j,bx));
00721
00722 if (DMap[j] != MyProc)
00723
00724
00725
00726 cache[DMap[j]] += 1;
00727 }
00728 }
00729 }
00730
00731 BL_ASSERT(cache[DMap[i]] == 0);
00732 }
00733
00734 return SICache.front();
00735 }
00736
00737
00738
00739
00740
00741 inline
00742 SI&
00743 TheFBsirec (int scomp,
00744 int ncomp,
00745 const MultiFab& mf)
00746 {
00747 BL_ASSERT(ncomp > 0);
00748 BL_ASSERT(scomp >= 0);
00749
00750 const SI si(mf.boxArray(), scomp, ncomp, mf.nGrow());
00751
00752 for (SIList::iterator it = SICache.begin(); it != SICache.end(); ++it)
00753 if (*it == si)
00754 return *it;
00755
00756 return BuildFBsirec(si,mf);
00757 }
00758
00759 void
00760 MultiFab::FillBoundary (int scomp,
00761 int ncomp)
00762 {
00763
00764 MultiFabCopyDescriptor mfcd;
00765 SI& si = TheFBsirec(scomp,ncomp,*this);
00766 const MultiFabId mfid = mfcd.RegisterMultiFab(this);
00767
00768
00769
00770 for (unsigned int i = 0; i < si.m_sirec.size(); i++)
00771 {
00772 si.m_sirec[i].m_fbid = mfcd.AddBox(mfid,
00773 si.m_sirec[i].m_bx,
00774 0,
00775 si.m_sirec[i].m_j,
00776 scomp,
00777 scomp,
00778 ncomp);
00779 }
00780
00781 mfcd.CollectData(&si.m_cache,&si.m_commdata);
00782
00783 for (unsigned int i = 0; i < si.m_sirec.size(); i++)
00784 {
00785 BL_ASSERT(DistributionMap()[si.m_sirec[i].m_i] == ParallelDescriptor::MyProc());
00786
00787
00788
00789 mfcd.FillFab(mfid,si.m_sirec[i].m_fbid,(*this)[si.m_sirec[i].m_i]);
00790 }
00791 }