Page MenuHomec4science

ref_subset.cc
No OneTemporary

File Metadata

Created
Fri, May 31, 21:44

ref_subset.cc

/**
* @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__

Event Timeline