Page MenuHomec4science

ref_subset.cc
No OneTemporary

File Metadata

Created
Wed, Oct 2, 11:04

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>
/* -------------------------------------------------------------------------- */
//#define PROC_INVALID -1
__BEGIN_LIBMULTISCALE__
/* -------------------------------------------------------------------------- */
// attach a vector of data to the subset
template <typename Ref> bool RefSubset<Ref>::attachData(AttachedObject *obj) {
LM_ASSERT(std::find(attached.begin(), attached.end(), obj) == attached.end(),
"obj " << obj << " was alread attached in the past");
if (AttachedVector<Real> *objPtr =
dynamic_cast<AttachedVector<Real> *>(obj)) {
DUMP("want to register obj " << &(objPtr->getV()), DBG_DETAIL);
for (UInt j = 0; j < attached.size(); ++j) {
if (AttachedVector<Real> *ptr =
dynamic_cast<AttachedVector<Real> *>(attached[j])) {
if (&ptr->getV() == &objPtr->getV()) {
DUMP("obj " << &(objPtr->getV()) << " was already registered",
DBG_DETAIL);
return false;
}
}
}
}
attached.push_back(obj);
return true;
}
/* -------------------------------------------------------------------------- */
// detach a vector of data from the subset
template <typename Ref> void RefSubset<Ref>::detachData(AttachedObject *obj) {
UInt size = attached.size();
for (UInt i = 0; i < size; ++i) {
if (attached[i] == obj) {
attached[i] = attached[size - 1];
attached.resize(size - 1);
break;
}
}
}
/* -------------------------------------------------------------------------- */
template <typename Ref>
void RefSubset<Ref>::declareSentAtoms(MapRefToUInt &sent_atoms,
MapUIntToRefList &sent_reverse) {
DUMP("declare atoms sent for subset " << name, DBG_INFO);
// clear maps
sent.clear();
sent_indexes.clear();
MapRefToUInt sent_index_in_subset;
// loop over subset atoms
UInt nAtoms = container.size();
for (UInt i = 0; i < nAtoms; ++i) {
// get the reference to the atom "i"
Ref at = container.get(i);
if (sent_atoms.count(at) > 0) {
if (sent_atoms[at] == UINT_MAX)
continue;
DUMP("invalidating atom " << i << " in subset " << name
<< " old position: " << at << " ,sent to proc "
<< sent_atoms[at],
DBG_INFO);
sent_index_in_subset[at] = i;
holes.push_back(i);
}
}
// loop over the sent atoms to build ordered buffer list
typename MapUIntToRefList::iterator it;
typename MapUIntToRefList::iterator end;
for (it = sent_reverse.begin(), end = sent_reverse.end(); it != end; ++it) {
UInt proc = (*it).first;
std::vector<Ref> &listsent = (*it).second;
for (UInt i = 0; i < listsent.size(); ++i) {
Ref at = listsent[i];
if (sent_index_in_subset.count(at)) {
IF_REF_TRACED(at, "traced atom sent to " << proc << " for container "
<< &container << " (index was "
<< sent_index_in_subset[at]
<< ")");
sent[proc].push_back(at);
sent_indexes[proc].push_back(sent_index_in_subset[at]);
}
}
}
{
typename MapUIntToRefList::iterator it2;
typename MapUIntToRefList::iterator end2;
for (it2 = sent.begin(), end2 = sent.end(); it2 != end2; ++it2) {
DUMP("I am supposed to send " << (*it2).second.size() << " atoms to proc "
<< (*it2).first << " for subset "
<< subset_id,
DBG_INFO);
}
}
}
/* -------------------------------------------------------------------------- */
template <typename Ref>
void RefSubset<Ref>::declareRecvAtoms(MapRefToUInt &masks,
MapUIntToRefList &recv_atoms) {
DUMP("declare atoms received for subset " << name, DBG_INFO);
UInt mask = 1 << subset_id;
// clear maps
recv.clear();
recv_indexes.clear();
typename MapUIntToRefList::iterator it;
typename MapUIntToRefList::iterator end;
for (it = recv_atoms.begin(), end = recv_atoms.end(); it != end; ++it) {
UInt proc = (*it).first;
std::vector<Ref> &recvlist = (*it).second;
for (UInt i = 0; i < recvlist.size(); ++i) {
Ref at = recvlist[i];
// check if I am concerned with this atom
// DUMP("atom " << i << " in recv list. mask "
// << masks[at] << " my mask " << mask,DBG_INFO);
if (masks[at] & mask) {
// if so I register it
recv[proc].push_back(at);
// also I need to find a new spot for it
UInt new_index;
// search in the holes created by the gone atoms
if (!holes.empty()) {
new_index = holes.back();
container.get(new_index) = at;
holes.pop_back();
} else {
new_index = container.size();
container.add(at);
}
IF_REF_TRACED(at, "traced atom received from "
<< proc << " for container " << &container
<< " (index is now " << new_index << ")");
recv_indexes[proc].push_back(new_index);
}
}
}
{
typename MapUIntToUIntList::iterator it2;
typename MapUIntToUIntList::iterator end2;
for (it2 = recv_indexes.begin(), end2 = recv_indexes.end(); it2 != end2;
++it2) {
DUMP("I am supposed to recv " << (*it2).second.size()
<< " atoms from proc " << (*it2).first
<< " for subset " << subset_id,
DBG_INFO);
}
}
}
/* -------------------------------------------------------------------------- */
template <typename Ref>
void RefSubset<Ref>::buildMasksForSentAtoms(MapRefToUInt &masks) {
UInt mask = 1 << subset_id;
typename MapUIntToRefList::iterator it;
typename MapUIntToRefList::iterator end;
for (it = sent.begin(), end = sent.end(); it != end; ++it) {
std::vector<Ref> &reflist = (*it).second;
UInt nAtoms = reflist.size();
for (UInt i = 0; i < nAtoms; ++i) {
Ref at = reflist[i];
if (!masks.count(at))
masks[at] = mask;
else
masks[at] |= mask;
}
}
}
/* -------------------------------------------------------------------------- */
template <typename Ref>
void RefSubset<Ref>::packAttachedData(std::map<UInt, PackBuffer> &buffer) {
typename MapUIntToUIntList::iterator it;
typename MapUIntToUIntList::iterator end;
for (it = sent_indexes.begin(), end = sent_indexes.end(); it != end; ++it) {
UInt proc = (*it).first;
std::vector<UInt> listsent = (*it).second;
if (proc == UINT_MAX)
continue;
for (UInt i = 0; i < listsent.size(); ++i) {
for (UInt j = 0; j < attached.size(); ++j) {
attached[j]->packData(listsent[i], buffer[proc], proc);
}
}
}
}
/* -------------------------------------------------------------------------- */
template <typename Ref>
void RefSubset<Ref>::unpackAttachedData(std::map<UInt, PackBuffer> &buffer) {
typename MapUIntToUIntList::iterator it;
typename MapUIntToUIntList::iterator end;
for (it = recv_indexes.begin(), end = recv_indexes.end(); it != end; ++it) {
UInt proc = (*it).first;
std::vector<UInt> listrecv = (*it).second;
if (proc == UINT_MAX)
continue;
for (UInt i = 0; i < listrecv.size(); ++i) {
for (UInt j = 0; j < attached.size(); ++j) {
attached[j]->unpackData(listrecv[i], buffer[proc], proc);
}
}
}
}
/* -------------------------------------------------------------------------- */
template <typename Ref>
void RefSubset<Ref>::translateMovingReferences(MapRefToRef &moved) {
// loop over the contained atoms and shift references of moved atoms
UInt nAtoms = container.size();
for (UInt i = 0; i < nAtoms; ++i) {
// get the reference to the atom "i"
Ref &at = container.get(i);
if (moved.count(at)) {
DUMP("translating atom in subset " << subset_id << " numero " << i
<< " from position " << at
<< " to position " << moved[at],
DBG_INFO);
IF_REF_TRACED(at, "translate atom " << at << " to ref " << moved[at]);
at = moved[at];
}
}
}
/* -------------------------------------------------------------------------- */
template <typename Ref> void RefSubset<Ref>::fillRemainingHoles() {
// 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 nAtoms = container.size();
if (index == nAtoms - 1)
// container.resize(nAtoms-1);
resize(nAtoms - 1);
else
moveLastReference(index);
}
}
/* -------------------------------------------------------------------------- */
template <typename Ref>
void RefSubset<Ref>::moveReference(UInt i_src, UInt i_dest) {
if (i_src == i_dest)
return;
IF_REF_TRACED(container.get(i_src), "traced atom moved from index "
<< i_src << " to index " << i_dest
<< " for container " << &container);
DUMP("atom moved from index " << i_src << " to index " << i_dest
<< " for container " << &container,
DBG_INFO);
container.get(i_dest) = container.get(i_src);
for (UInt j = 0; j < attached.size(); ++j) {
attached[j]->moveAttachedValues(i_src, i_dest);
}
}
/* -------------------------------------------------------------------------- */
template <typename Ref> void RefSubset<Ref>::moveLastReference(UInt i_dest) {
UInt nAtoms = container.size();
if (nAtoms - 1 == i_dest)
return;
moveReference(nAtoms - 1, i_dest);
// container.resize(nAtoms-1);
resize(nAtoms - 1);
}
/* -------------------------------------------------------------------------- */
template <typename Ref> void RefSubset<Ref>::resize(UInt sz) {
DUMP(name << " resizes from " << container.size() << " to " << sz, DBG_INFO);
container.resize(sz);
for (UInt j = 0; j < attached.size(); ++j) {
attached[j]->resize(sz);
}
}
/* -------------------------------------------------------------------------- */
#define DECLARE_REF_SUBSET(n, data, obj) \
template class RefSubset< \
ContainerArray<typename BOOST_PP_TUPLE_ELEM(3, 0, obj)::RefPoint>>;
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