Page MenuHomec4science

ref_subset.cc
No OneTemporary

File Metadata

Created
Sat, May 25, 08:27

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 "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;
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 (!holes.empty()) {
new_index = holes.back();
container.get(new_index) = ref;
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(
std::map<UInt, PackBuffer> &buffer) {
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(
std::map<UInt, PackBuffer> &buffer) {
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]));
}
}
}
}
/* --------------------------------------------------------------------------
*/
template <typename Ref, bool is_subset>
void RefSubset<Ref, is_subset>::translateMovingReferences(MapRefToRef &moved) {
if constexpr (not is_subset)
return;
// loop over the contained refs and shift references of moved refs
UInt nRefs = container.size();
for (UInt i = 0; i < nRefs; ++i) {
// get the reference to the ref "i"
Ref &ref = container.get(i);
if (moved.count(ref)) {
DUMP("translating ref in subset " << subset_id << " numero " << i
<< " from position " << ref
<< " to position " << moved[ref],
DBG_INFO);
IF_REF_TRACED(ref, container.getID() << ": translate ref(" << i << ") "
<< ref << " to ref " << moved[ref]);
ref = moved[ref];
}
}
}
/* --------------------------------------------------------------------------
*/
template <typename Ref, bool is_subset>
void RefSubset<Ref, is_subset>::fillRemainingHoles() {
if constexpr (not is_subset)
return;
// checks if there are remaining holes for which we need to displace
// the references order and attached values
while (!holes.empty()) {
UInt index = holes.back();
holes.pop_back();
UInt nRefs = container.size();
if (index == nRefs - 1)
// container.resize(nRefs-1);
resize(nRefs - 1);
else
moveLastReference(index);
}
}
/* --------------------------------------------------------------------------
*/
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), "traced ref moved from index "
<< i_src << " to index " << i_dest
<< " for container " << &container);
DUMP("ref moved from index " << i_src << " to index " << i_dest
<< " for container " << &container,
DBG_INFO);
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);
}
}
/* ------------------------------------------------------------------------ */
template <typename Ref, bool is_subset>
void RefSubset<Ref, is_subset>::moveLastReference(UInt i_dest) {
if constexpr (not is_subset)
return;
UInt nRefs = container.size();
if (nRefs - 1 == i_dest)
return;
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;
}
/* --------------------------------------------------------------------------
*/
#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