// $Header: /home/eschnett/C/carpet/Carpet/Carpet/CarpetLib/src/ggf.cc,v 1.46 2004/09/17 16:37:26 schnetter Exp $ #include #include #include #include #include #include "cctk.h" #include "defs.hh" #include "dh.hh" #include "th.hh" #include "ggf.hh" using namespace std; // Constructors template ggf::ggf (const int varindex, const operator_type transport_operator, th& t, dh& d, const int tmin, const int tmax, const int prolongation_order_time, const int vectorlength, const int vectorindex, ggf* const vectorleader) : varindex(varindex), transport_operator(transport_operator), t(t), tmin(tmin), tmax(tmax), prolongation_order_time(prolongation_order_time), h(d.h), d(d), storage(tmax-tmin+1), vectorlength(vectorlength), vectorindex(vectorindex), vectorleader(vectorleader) { assert (&t.h == &d.h); assert (vectorlength >= 1); assert (vectorindex >= 0 && vectorindex < vectorlength); assert ((vectorindex==0 && !vectorleader) || (vectorindex!=0 && vectorleader)); d.add(this); } // Destructors template ggf::~ggf () { d.remove(this); } // Comparison template bool ggf::operator== (const ggf& f) const { return this == &f; } // Modifiers template void ggf::recompose_crop () { // Free storage that will not be needed storage.resize(tmax-tmin+1); for (int tl=tmin; tl<=tmax; ++tl) { for (int rl=h.reflevels(); rl<(int)storage.at(tl-tmin).size(); ++rl) { for (int c=0; c<(int)storage.at(tl-tmin).at(rl).size(); ++c) { for (int ml=0; ml<(int)storage.at(tl-tmin).at(rl).at(c).size(); ++ml) { delete storage.at(tl-tmin).at(rl).at(c).at(ml); } // for ml } // for c } // for rl storage.at(tl-tmin).resize(h.reflevels()); } // for tl } template void ggf::recompose_allocate (const int rl) { // TODO: restructure storage only when needed // Retain storage that might be needed oldstorage.resize(tmax-tmin+1); for (int tl=tmin; tl<=tmax; ++tl) { oldstorage.at(tl-tmin).resize(h.reflevels()); assert (oldstorage.at(tl-tmin).at(rl).size() == 0); oldstorage.at(tl-tmin).at(rl) = storage.at(tl-tmin).at(rl); storage.at(tl-tmin).at(rl).resize(0); } // Resize structure and allocate storage storage.resize(tmax-tmin+1); for (int tl=tmin; tl<=tmax; ++tl) { storage.at(tl-tmin).resize(h.reflevels()); storage.at(tl-tmin).at(rl).resize(h.components(rl)); for (int c=0; callocate (d.boxes.at(rl).at(c).at(ml).exterior, h.proc(rl,c)); } // for ml } // for c } // for tl } template void ggf::recompose_fill (comm_state& state, const int rl, const bool do_prolongate) { // Initialise the new storage for (int c=0; cextent(); ovlp.normalize(); work -= ovlp; for (typename ibset::const_iterator r=ovlp.begin(); r!=ovlp.end(); ++r) { storage.at(tl-tmin).at(rl).at(c).at(ml)->copy_from (state, oldstorage.at(tl-tmin).at(rl).at(cc).at(ml), *r); } } // if ml } // for cc } // if rl if (do_prolongate) { // Initialise from coarser level, if possible if (rl>0) { if (transport_operator != op_none) { const int numtl = prolongation_order_time+1; assert (tmax-tmin+1 >= numtl); vector tls(numtl); vector times(numtl); for (int i=0; i*> gsrcs(numtl); for (int i=0; iextent() == gsrcs.at(0)->extent()); } const CCTK_REAL time = t.time(tl,rl,ml); // TODO: choose larger regions first // TODO: prefer regions from the same processor const iblist& list = d.boxes.at(rl).at(c).at(ml).recv_ref_coarse.at(cc); for (typename iblist::const_iterator iter=list.begin(); iter!=list.end(); ++iter) { ibset ovlp = work & *iter; ovlp.normalize(); work -= ovlp; for (typename ibset::const_iterator r=ovlp.begin(); r!=ovlp.end(); ++r) { storage.at(tl-tmin).at(rl).at(c).at(ml)->interpolate_from (state, gsrcs, times, *r, time, d.prolongation_order_space, prolongation_order_time); } // for r } // for iter } // for cc } // if transport_operator } // if rl } // if do_prolongate // Note that work need not be empty here; in this case, not // everything could be initialised. This is okay on outer // boundaries. // TODO: check this. } // for tl } // for ml } // for c } template void ggf::recompose_free (const int rl) { // Delete old storage for (int tl=tmin; tl<=tmax; ++tl) { for (int c=0; c<(int)oldstorage.at(tl-tmin).at(rl).size(); ++c) { for (int ml=0; ml<(int)oldstorage.at(tl-tmin).at(rl).at(c).size(); ++ml) { delete oldstorage.at(tl-tmin).at(rl).at(c).at(ml); } // for ml } // for c oldstorage.at(tl-tmin).at(rl).resize(0); } // for tl } template void ggf::recompose_bnd_prolongate (comm_state& state, const int rl, const bool do_prolongate) { if (do_prolongate) { // Set boundaries if (rl>0) { for (int c=0; c void ggf::recompose_sync (comm_state& state, const int rl, const bool do_prolongate) { if (do_prolongate) { // Set boundaries for (int c=0; c void ggf::cycle (int rl, int c, int ml) { assert (rl>=0 && rl=0 && c=0 && ml* tmpdata = storage.at(tmin-tmin).at(rl).at(c).at(ml); for (int tl=tmin; tl<=tmax-1; ++tl) { storage.at(tl-tmin).at(rl).at(c).at(ml) = storage.at(tl+1-tmin).at(rl).at(c).at(ml); } storage.at(tmax-tmin).at(rl).at(c).at(ml) = tmpdata; } // Flip the time levels by exchanging the data sets template void ggf::flip (int rl, int c, int ml) { assert (rl>=0 && rl=0 && c=0 && ml* tmpdata = storage.at(tl1-tmin).at(rl).at(c).at(ml); storage.at(tl1-tmin).at(rl).at(c).at(ml) = storage.at(tl2-tmin).at(rl).at(c).at(ml); storage.at(tl2-tmin).at(rl).at(c).at(ml) = tmpdata; } } // Operations // Copy a region template void ggf::copycat (comm_state& state, int tl1, int rl1, int c1, int ml1, const ibbox dh::dboxes::* recv_box, int tl2, int rl2, int ml2, const ibbox dh::dboxes::* send_box) { assert (tl1>=tmin && tl1<=tmax); assert (rl1>=0 && rl1=0 && c1=0 && ml1=tmin && tl2<=tmax); assert (rl2>=0 && rl2copy_from (state, storage.at(tl2-tmin).at(rl2).at(c2).at(ml2), recv); } // Copy regions template void ggf::copycat (comm_state& state, int tl1, int rl1, int c1, int ml1, const iblist dh::dboxes::* recv_list, int tl2, int rl2, int ml2, const iblist dh::dboxes::* send_list) { assert (tl1>=tmin && tl1<=tmax); assert (rl1>=0 && rl1=0 && c1=0 && ml1=tmin && tl2<=tmax); assert (rl2>=0 && rl2copy_from (state, storage.at(tl2-tmin).at(rl2).at(c2).at(ml2), *r); } } // Copy regions template void ggf::copycat (comm_state& state, int tl1, int rl1, int c1, int ml1, const iblistvect dh::dboxes::* recv_listvect, int tl2, int rl2, int ml2, const iblistvect dh::dboxes::* send_listvect) { assert (tl1>=tmin && tl1<=tmax); assert (rl1>=0 && rl1=0 && c1=0 && ml1=tmin && tl2<=tmax); assert (rl2>=0 && rl2copy_from (state, storage.at(tl2-tmin).at(rl2).at(c2).at(ml2), *r); } } } // Interpolate a region template void ggf::intercat (comm_state& state, int tl1, int rl1, int c1, int ml1, const ibbox dh::dboxes::* recv_list, const vector tl2s, int rl2, int ml2, const ibbox dh::dboxes::* send_list, CCTK_REAL time) { assert (tl1>=tmin && tl1<=tmax); assert (rl1>=0 && rl1=0 && c1=0 && ml1=tmin && tl2s.at(i)<=tmax); } assert (rl2>=0 && rl2=0 && ml2*> gsrcs(tl2s.size()); vector times(tl2s.size()); for (int i=0; i<(int)gsrcs.size(); ++i) { assert (rl2<(int)storage.at(tl2s.at(i)-tmin).size()); assert (c2<(int)storage.at(tl2s.at(i)-tmin).at(rl2).size()); assert (ml2<(int)storage.at(tl2s.at(i)-tmin).at(rl2).at(c2).size()); gsrcs.at(i) = storage.at(tl2s.at(i)-tmin).at(rl2).at(c2).at(ml2); times.at(i) = t.time(tl2s.at(i),rl2,ml2); } const ibbox recv = d.boxes.at(rl1).at(c1).at(ml1).*recv_list; const ibbox send = d.boxes.at(rl2).at(c2).at(ml2).*send_list; assert (all(recv.shape()==send.shape())); // interpolate the content assert (recv==send); storage.at(tl1-tmin).at(rl1).at(c1).at(ml1)->interpolate_from (state, gsrcs, times, recv, time, d.prolongation_order_space, prolongation_order_time); } // Interpolate regions template void ggf::intercat (comm_state& state, int tl1, int rl1, int c1, int ml1, const iblist dh::dboxes::* recv_list, const vector tl2s, int rl2, int ml2, const iblist dh::dboxes::* send_list, const CCTK_REAL time) { assert (tl1>=tmin && tl1<=tmax); assert (rl1>=0 && rl1=0 && c1=0 && ml1=tmin && tl2s.at(i)<=tmax); } assert (rl2>=0 && rl2=0 && ml2*> gsrcs(tl2s.size()); vector times(tl2s.size()); for (int i=0; i<(int)gsrcs.size(); ++i) { assert (rl2<(int)storage.at(tl2s.at(i)-tmin).size()); assert (c2<(int)storage.at(tl2s.at(i)-tmin).at(rl2).size()); assert (ml2<(int)storage.at(tl2s.at(i)-tmin).at(rl2).at(c2).size()); gsrcs.at(i) = storage.at(tl2s.at(i)-tmin).at(rl2).at(c2).at(ml2); times.at(i) = t.time(tl2s.at(i),rl2,ml2); } const iblist recv = d.boxes.at(rl1).at(c1).at(ml1).*recv_list; const iblist send = d.boxes.at(rl2).at(c2).at(ml2).*send_list; assert (recv.size()==send.size()); // walk all boxes for (typename iblist::const_iterator r=recv.begin(), s=send.begin(); r!=recv.end(); ++r, ++s) { // (use the send boxes for communication) // interpolate the content storage.at(tl1-tmin).at(rl1).at(c1).at(ml1)->interpolate_from (state, gsrcs, times, *r, time, d.prolongation_order_space, prolongation_order_time); } } // Interpolate regions template void ggf::intercat (comm_state& state, int tl1, int rl1, int c1, int ml1, const iblistvect dh::dboxes::* recv_listvect, const vector tl2s, int rl2, int ml2, const iblistvect dh::dboxes::* send_listvect, const CCTK_REAL time) { assert (tl1>=tmin && tl1<=tmax); assert (rl1>=0 && rl1=0 && c1=0 && ml1=tmin && tl2s.at(i)<=tmax); } assert (rl2>=0 && rl2=0 && ml2*> gsrcs(tl2s.size()); vector times(tl2s.size()); for (int i=0; i<(int)gsrcs.size(); ++i) { assert (rl2<(int)storage.at(tl2s.at(i)-tmin).size()); assert (c2<(int)storage.at(tl2s.at(i)-tmin).at(rl2).size()); assert (ml2<(int)storage.at(tl2s.at(i)-tmin).at(rl2).at(c2).size()); gsrcs.at(i) = storage.at(tl2s.at(i)-tmin).at(rl2).at(c2).at(ml2); times.at(i) = t.time(tl2s.at(i),rl2,ml2); } const iblist recv = (d.boxes.at(rl1).at(c1).at(ml1).*recv_listvect).at(c2); const iblist send = (d.boxes.at(rl2).at(c2).at(ml2).*send_listvect).at(c1); assert (recv.size()==send.size()); // walk all boxes for (typename iblist::const_iterator r=recv.begin(), s=send.begin(); r!=recv.end(); ++r, ++s) { // (use the send boxes for communication) // interpolate the content storage.at(tl1-tmin).at(rl1).at(c1).at(ml1)->interpolate_from (state, gsrcs, times, *r, time, d.prolongation_order_space, prolongation_order_time); } } } // Copy a component from the next time level template void ggf::copy (comm_state& state, int tl, int rl, int c, int ml) { // Copy copycat (state, tl ,rl,c,ml, &dh::dboxes::exterior, tl+1,rl, ml, &dh::dboxes::exterior); } // Synchronise the boundaries a component template void ggf::sync (comm_state& state, int tl, int rl, int c, int ml) { // Copy copycat (state, tl,rl,c,ml, &dh::dboxes::recv_sync, tl,rl, ml, &dh::dboxes::send_sync); } // Prolongate the boundaries of a component template void ggf::ref_bnd_prolongate (comm_state& state, int tl, int rl, int c, int ml, CCTK_REAL time) { // Interpolate assert (rl>=1); if (transport_operator == op_none) return; vector tl2s; // Interpolation in time assert (tmax-tmin+1 >= prolongation_order_time+1); tl2s.resize(prolongation_order_time+1); for (int i=0; i<=prolongation_order_time; ++i) tl2s.at(i) = tmax - i; intercat (state, tl ,rl ,c,ml, &dh::dboxes::recv_ref_bnd_coarse, tl2s,rl-1, ml, &dh::dboxes::send_ref_bnd_fine, time); } // Restrict a multigrid level template void ggf::mg_restrict (comm_state& state, int tl, int rl, int c, int ml, CCTK_REAL time) { // Require same times assert (abs(t.get_time(rl,ml) - t.get_time(rl,ml-1)) <= 1.0e-8 * abs(t.get_time(rl,ml))); const vector tl2s(1,tl); intercat (state, tl ,rl,c,ml, &dh::dboxes::recv_mg_coarse, tl2s,rl, ml-1, &dh::dboxes::send_mg_fine, time); } // Prolongate a multigrid level template void ggf::mg_prolongate (comm_state& state, int tl, int rl, int c, int ml, CCTK_REAL time) { // Require same times assert (abs(t.get_time(rl,ml) - t.get_time(rl,ml+1)) <= 1.0e-8 * abs(t.get_time(rl,ml))); const vector tl2s(1,tl); intercat (state, tl ,rl,c,ml, &dh::dboxes::recv_mg_coarse, tl2s,rl, ml+1, &dh::dboxes::send_mg_fine, time); } // Restrict a refinement level template void ggf::ref_restrict (comm_state& state, int tl, int rl, int c, int ml, CCTK_REAL time) { // Require same times assert (abs(t.get_time(rl,ml) - t.get_time(rl+1,ml)) <= 1.0e-8 * abs(t.get_time(rl,ml))); if (transport_operator == op_none) return; const vector tl2s(1,tl); intercat (state, tl ,rl ,c,ml, &dh::dboxes::recv_ref_fine, tl2s,rl+1, ml, &dh::dboxes::send_ref_coarse, time); } // Prolongate a refinement level template void ggf::ref_prolongate (comm_state& state, int tl, int rl, int c, int ml, CCTK_REAL time) { assert (rl>=1); if (transport_operator == op_none) return; vector tl2s; // Interpolation in time assert (tmax-tmin+1 >= prolongation_order_time+1); tl2s.resize(prolongation_order_time+1); for (int i=0; i<=prolongation_order_time; ++i) tl2s.at(i) = tmax - i; intercat (state, tl ,rl ,c,ml, &dh::dboxes::recv_ref_coarse, tl2s,rl-1, ml, &dh::dboxes::send_ref_fine, time); } template class ggf<3>;