diff --git a/src/common/ref_subset.cc b/src/common/ref_subset.cc index b072482..fb8194b 100644 --- a/src/common/ref_subset.cc +++ b/src/common/ref_subset.cc @@ -1,482 +1,488 @@ /** * @file ref_subset.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date Mon Sep 08 23:40:22 2014 * * @brief This file contains the interface of containers of references 4 the * migration system * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * LibMultiScale is free software: you can redistribute it and/or modify it * under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * LibMultiScale is distributed in the hope that it will be useful, but * WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with LibMultiScale. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <boost/preprocessor.hpp> #include <memory> /* -------------------------------------------------------------------------- */ #include "lib_continuum.hh" #include "lib_dd.hh" #include "lib_md.hh" #include "lm_common.hh" #include "ref_subset.hh" #include "trace_atom.hh" #include <boost/preprocessor.hpp> /* -------------------------------------------------------------------------- */ __BEGIN_LIBMULTISCALE__ /* -------------------------------------------------------------------------- */ template <typename Ref, bool is_subset> void RefSubset<Ref, is_subset>::declareSentRefs( MapRefToUInt &sent_refs, MapUIntToRefList &sent_reverse) { DUMP("declare refs sent for subset " << container.getID(), DBG_INFO); // clear maps sent.clear(); sent_indexes.clear(); MapRefToUInt sent_index_in_subset; // loop over subset refs if constexpr (is_subset) { for (auto &&[i, ref] : enumerate(container)) { // get the reference to the ref "i" in subset if (sent_refs.count(ref) > 0) { if (sent_refs[ref] == UINT_MAX) continue; sent_index_in_subset[ref] = i; this->holes.push_back(i); } } } // loop over the sent refs to build ordered buffer list UInt idx; for (auto &&[proc, listsent] : sent_reverse) { for (auto &&ref : listsent) { if (is_subset and not sent_index_in_subset.count(ref)) continue; if constexpr (not is_subset) { idx = ref.getIndex(); } else { idx = sent_index_in_subset[ref]; } sent[proc].push_back(ref); sent_indexes[proc].push_back(idx); IF_REF_TRACED(ref, "traced ref sent to " << proc << " for container " << container.getID()); } for (auto &&[proc, list_sent] : sent) { DUMP("I am supposed to send " << list_sent.size() << " refs to proc " << proc << " for subset " << container.getID() << "(" << subset_id << ")", DBG_INFO); } } } /* ------------------------------------------------------------------------ */ template <typename Ref, bool is_subset> void RefSubset<Ref, is_subset>::declareRecvRefs(MapRefToUInt &masks, MapUIntToRefList &recv_refs) { DUMP("declare refs received for subset " << container.getID(), DBG_INFO); UInt mask [[gnu::unused]] = 1 << subset_id; // clear maps recv.clear(); recv_indexes.clear(); auto register_newref = [&](auto proc, auto new_index, auto &ref) { IF_REF_TRACED(ref, "traced ref received from " << proc << " for container " << container.getID() << " (index is now " << new_index << ")"); recv_indexes[proc].push_back(new_index); recv[proc].push_back(ref); }; for (auto &&[proc, recvlist] : recv_refs) { for (auto &&ref : recvlist) { if constexpr (is_subset) { // check if concerned with ref => register if (masks[ref] & mask) { UInt new_index; // find a new index (if possible within holes) if (!this->holes.empty()) { new_index = this->holes.back(); container.get(new_index) = ref; this->holes.pop_back(); } else { new_index = container.size(); container.push_back(ref); } register_newref(proc, new_index, ref); } } else { register_newref(proc, ref.getIndex(), ref); } } } for (auto &&[proc, recvlist] : recv_indexes) { DUMP("I am supposed to recv " << recvlist.size() << " refs from proc " << proc << " for subset " << container.getID() << "(" << subset_id << ")", DBG_INFO); } } /* ----------------------------------------------------------------------- */ template <typename Ref, bool is_subset> void RefSubset<Ref, is_subset>::buildMasksForSentRefs(MapRefToUInt &masks) { if constexpr (not is_subset) return; UInt mask = 1 << subset_id; for (auto &&[proc, reflist] : sent) { UInt nRefs = reflist.size(); for (UInt i = 0; i < nRefs; ++i) { Ref ref = reflist[i]; if (!masks.count(ref)) masks[ref] = mask; else masks[ref] |= mask; } } } /* ----------------------------------------------------------------------- */ // template <typename Ref, bool is_subset> // void RefSubset<Ref, is_subset>::packAttachedData( // LAMMPS_NS::PackBuffer &buffer) { // LM_TOIMPLEMENT; // // for (auto &&[proc, listsent] : sent_indexes) { // // if (proc == UINT_MAX) // // continue; // // for (auto &&[i, sent_index] : enumerate(listsent)) { // // if (this->attached_objects.size() > 0) // // DUMP(container.getID() // // << " prepares to pack to proc " << proc << " subset index // " // // << i << " ref index " << sent_index, // // DBG_MESSAGE); // // for (auto &&[ptr, att_obj] : this->attached_objects) { // // DUMP("prepares to pack obj " << att_obj->getID(), DBG_MESSAGE); // // att_obj->packData(sent_index, buffer[proc], proc, true); // // } // // } // // } // } /* ------------------------------------------------------------------------ */ // template <typename Ref, bool is_subset> // void RefSubset<Ref, is_subset>::unpackAttachedData( // LAMMPS_NS::PackBuffer &buffer) { // LM_TOIMPLEMENT; // // for (auto &&[proc, listrecv] : recv_indexes) { // // if (proc == UINT_MAX) // // continue; // // for (auto &&[i, recv_index] : enumerate(listrecv)) { // // if (CHECK_REF_TRACED(recv[proc][i])) // // DUMP(container.getID() // // << " prepares to unpack from proc " << proc << " subset // // index " // // << i << " ref index " << recv_index, // // DBG_MESSAGE); // // for (auto &&[ptr, att_obj] : this->attached_objects) { // // if (CHECK_REF_TRACED(recv[proc][i])) // // DUMP("prepares to pack obj " << att_obj->getID(), // DBG_MESSAGE); // // att_obj->unpackData(recv_index, buffer[proc], proc, // // CHECK_REF_TRACED(recv[proc][i])); // // } // // } // // } // } /* ----------------------------------------------------------------------- */ #define printInfoAttachedValue(mess, att_obj, container, i_src) \ { \ DUMP(container.getID() << "[" << i_src << "] = " << container.get(i_src) \ << " attached:" << att_obj->getID() << ": " \ << att_obj->getV().row(i_src) << " ### " << mess, \ DBG_DETAIL); \ } /* ----------------------------------------------------------------------- */ template <typename Ref, bool is_subset> void RefSubset<Ref, is_subset>::packData(Ref &ref, LAMMPS_NS::PackBuffer &buffer, bool verbose) { auto index = this->getRefIndex(ref); if (index == -1) { LM_FATAL(this->getID() << ": this should not happen:" << ref); } for (auto &&[ID, att_obj] : this->attached_objects) { att_obj->packData(index, buffer, verbose); if (CHECK_REF_TRACED(ref)) { if (auto ptr = dynamic_cast<AttachedVector<Real> *>(att_obj.get())) { printInfoAttachedValue("packing", ptr, container, index); } } } if constexpr (is_subset) { DUMP(this->getID() << ": adding the hole" << index, DBG_DETAIL); this->holes.push_back(index); this->reverse_index_map.erase(ref); } } /* ----------------------------------------------------------------------- */ template <typename Ref, bool is_subset> void RefSubset<Ref, is_subset>::unpackData(Ref &ref, LAMMPS_NS::PackBuffer &buffer, bool verbose) { auto index = this->getRefIndex(ref); if constexpr (is_subset) { if (index != -1) LM_FATAL("this should not happen: found " << container.getID() << "[" << index << "] = " << ref); if (this->holes.size() > 0) { index = this->holes.back(); this->holes.pop_back(); } else { index = this->container.size(); this->container.resize(index + 1); } this->container.get(index) = ref; this->reverse_index_map[ref] = index; } for (auto &&[ID, att_obj] : this->attached_objects) { att_obj->unpackData(index, buffer, verbose); if (CHECK_REF_TRACED(ref)) { if (auto ptr = dynamic_cast<AttachedVector<Real> *>(att_obj.get())) { printInfoAttachedValue("unpacking", ptr, container, index); } } } } /* ----------------------------------------------------------------------- */ template <typename Ref, bool is_subset> void RefSubset<Ref, is_subset>::translateMovingReference(Ref &src, Ref &dst) { if constexpr (not is_subset) return; // get the index of the reference to be shifted in the subset auto i_src = this->getRefIndex(src); // check if the moved(src) ref atom is in this subset // if not I am not concerned by this change if (i_src == -1) { DUMP("could not find " << src << " in " << this->container.getID(), DBG_MESSAGE); return; } // if (CHECK_REF_TRACED(container.get(i_src))) { for (auto &&[ptr, att_obj] : this->attached_objects) { if (auto ptr = dynamic_cast<AttachedVector<Real> *>(att_obj.get())) { printInfoAttachedValue("before translate", ptr, container, i_src); } } //} // check if the ref atom of the destination is in this subset // This ref atom points certainly to an atom that left the processor // if it is in this subset then I have a hole to register container.get(i_src) = dst; this->reverse_index_map.erase(src); this->reverse_index_map[dst] = i_src; // if (CHECK_REF_TRACED(container.get(i_src))) { for (auto &&[ptr, att_obj] : this->attached_objects) { if (auto ptr = dynamic_cast<AttachedVector<Real> *>(att_obj.get())) { printInfoAttachedValue("after translate", ptr, container, i_src); } } //} } /* -------------------------------------------------------------------------- */ template <typename Ref, bool is_subset> void RefSubset<Ref, is_subset>::fillRemainingHoles() { if constexpr (not is_subset) return; + std::sort(this->holes.begin(), this->holes.end()); // checks if there are remaining holes for which we need to displace // the references order and attached values while (!this->holes.empty()) { UInt index = this->holes.back(); this->holes.pop_back(); + DUMP("filling hole: " << index + << " container size was: " << container.size(), + DBG_DETAIL); UInt nRefs = container.size(); if (index == nRefs - 1) // container.resize(nRefs - 1); resize(nRefs - 1); else moveLastReferenceToHole(index); + DUMP("filling hole: " << index << " container size: " << container.size(), + DBG_DETAIL); } } /* ---------------------------------------------------------------------- */ template <typename Ref, bool is_subset> void RefSubset<Ref, is_subset>::moveReference(UInt i_src, UInt i_dest) { if (i_src == i_dest) return; IF_REF_TRACED(container.get(i_src), " = " << container.getID() << "[" << i_src << "]: " << " traced ref moved from index " << i_src << " to index " << i_dest << " for container " << container.getID()); if (CHECK_REF_TRACED(container.get(i_src))) { for (auto &&[ptr, att_obj] : this->attached_objects) { if (auto ptr = dynamic_cast<AttachedVector<Real> *>(att_obj.get())) { printInfoAttachedValue("before moving ", ptr, container, i_src); } } } if constexpr (is_subset) container.get(i_dest) = container.get(i_src); for (auto &&[ptr, att_obj] : this->attached_objects) { att_obj->moveAttachedValues(i_src, i_dest); if (CHECK_REF_TRACED(container.get(i_dest))) { if (auto ptr = dynamic_cast<AttachedVector<Real> *>(att_obj.get())) { printInfoAttachedValue("after moving attached ", ptr, container, i_dest); } } } } /* ------------------------------------------------------------------------ */ template <typename Ref, bool is_subset> void RefSubset<Ref, is_subset>::moveLastReferenceToHole(UInt i_dest) { if constexpr (not is_subset) return; UInt nRefs = container.size(); if (nRefs - 1 == i_dest) return; if (i_dest > nRefs - 1) { int a = 1; while (a) { } } moveReference(nRefs - 1, i_dest); // container.resize(nRefs-1); resize(nRefs - 1); } /* -------------------------------------------------------------------------- */ template <typename Ref, bool is_subset> UInt RefSubset<Ref, is_subset>::resize(UInt sz) { if constexpr (is_subset) { if (sz == UInt(-1)) LM_FATAL("this should not happen"); container.resize(sz); } else { if (sz != UInt(-1)) LM_FATAL("this should not happen"); sz = container.size(); } DUMP(container.getID() << " resizes from " << container.size() << " to " << sz, DBG_INFO); for (auto &&[ptr, att_obj] : this->attached_objects) { att_obj->resize(sz); } return sz; } /* ----------------------------------------------------------------------- */ template <typename Ref, bool is_subset> bool RefSubset<Ref, is_subset>::is_hole(UInt index) { auto it = std::find(this->holes.begin(), this->holes.end(), index); bool is_hole(it != this->holes.end()); return is_hole; } /* ----------------------------------------------------------------------- */ template <typename Ref, bool is_subset> int RefSubset<Ref, is_subset>::getRefIndex(Ref &ref) { if constexpr (is_subset) { if (this->reverse_index_map.count(ref)) { return this->reverse_index_map[ref]; } // return reverse_index_map[ref]; // for (auto &&[i, e] : enumerate(container)) { // if ((not this->is_hole(i)) and e == ref) // return i; // } return -1; } return ref.getIndex(); } /* ----------------------------------------------------------------------- */ template <typename Ref, bool is_subset> void RefSubset<Ref, is_subset>::fillMasks(MapRefToUInt &masks) { for (auto &&[i, e] : enumerate(container)) { if (masks.count(e) != 0) masks[e] |= this->mask(); else masks[e] = this->mask(); if constexpr (is_subset) reverse_index_map[e] = i; } } /* ----------------------------------------------------------------------- */ #define DECLARE_REF_SUBSET(n, data, obj) \ template class RefSubset<ContainerArray<typename BOOST_PP_TUPLE_ELEM( \ 3, 0, obj)::ContainerPoints::Ref>, \ true>; \ template class RefSubset< \ typename BOOST_PP_TUPLE_ELEM(3, 0, obj)::ContainerPoints, false>; BOOST_PP_SEQ_FOR_EACH(DECLARE_REF_SUBSET, f, LIST_ATOM_MODEL) BOOST_PP_SEQ_FOR_EACH(DECLARE_REF_SUBSET, f, LIST_DD_MODEL) BOOST_PP_SEQ_FOR_EACH(DECLARE_REF_SUBSET, f, LIST_CONTINUUM_MODEL) #undef DECLARE_REF_SUBSET __END_LIBMULTISCALE__