diff --git a/src/synchronizer/communication_descriptor.hh b/src/synchronizer/communication_descriptor.hh index 1278dc39c..2a5d752f3 100644 --- a/src/synchronizer/communication_descriptor.hh +++ b/src/synchronizer/communication_descriptor.hh @@ -1,144 +1,147 @@ /** * @file synchronizer_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Wed Aug 3 13:49:36 2016 * * @brief Implementation of the helper classes for the synchronizer * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu 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. * * Akantu 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 Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "communication_tag.hh" #include "data_accessor.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COMMUNICATION_DESCRIPTOR_HH__ #define __AKANTU_COMMUNICATION_DESCRIPTOR_HH__ namespace akantu { /* ------------------------------------------------------------------------ */ enum CommunicationSendRecv { _send, _recv, _csr_not_defined }; /* -------------------------------------------------------------------------- */ struct CommunicationSRType { typedef CommunicationSendRecv type; static const type _begin_ = _send; static const type _end_ = _csr_not_defined; }; typedef safe_enum<CommunicationSRType> send_recv_t; /* ------------------------------------------------------------------------ */ class Communication { public: Communication(const CommunicationSendRecv & type = _csr_not_defined) : _size(0), _type(type) {} Communication(const Communication &) = delete; Communication & operator=(const Communication &) = delete; void resize(UInt size) { this->_size = size; this->_buffer.resize(size); } inline const CommunicationSendRecv & type() const { return this->_type; } inline const UInt & size() const { return this->_size; } inline const CommunicationRequest & request() const { return this->_request; } inline CommunicationRequest & request() { return this->_request; } inline const CommunicationBuffer & buffer() const { return this->_buffer; } inline CommunicationBuffer & buffer() { return this->_buffer; } private: UInt _size; CommunicationBuffer _buffer; CommunicationRequest _request; CommunicationSendRecv _type; }; template <class Entity> class Communications; /* ------------------------------------------------------------------------ */ template <class Entity> class CommunicationDescriptor { public: CommunicationDescriptor(Communication & communication, Array<Entity> & scheme, Communications<Entity> & communications, const SynchronizationTag & tag, UInt proc); CommunicationDescriptor(const CommunicationDescriptor &) = default; CommunicationDescriptor & operator=(const CommunicationDescriptor &) = default; /// get the quantity of data in the buffer UInt getNbData() { return communication.size(); } /// set the quantity of data in the buffer void setNbData(UInt size) { communication.resize(size); } /// get the corresponding tag const SynchronizationTag & getTag() const { return tag; } /// get the data buffer CommunicationBuffer & getBuffer(); /// get the corresponding request CommunicationRequest & getRequest(); /// get the communication scheme Array<Entity> & getScheme(); + /// reset the buffer before pack or after unpack + void resetBuffer(); + /// pack data for entities in the buffer void packData(DataAccessor<Entity> & accessor); /// unpack data for entities from the buffer void unpackData(DataAccessor<Entity> & accessor); /// posts asynchronous send requests void postSend(int hash_id); /// posts asynchronous receive requests void postRecv(int hash_id); /// free the request void freeRequest(); UInt getProc() { return proc; } protected: Communication & communication; Array<Entity> & scheme; Communications<Entity> & communications; const SynchronizationTag & tag; UInt proc; UInt rank; UInt counter; }; /* -------------------------------------------------------------------------- */ } // akantu #include "communication_descriptor_tmpl.hh" #endif /* __AKANTU_COMMUNICATION_DESCRIPTOR_HH__ */ diff --git a/src/synchronizer/communication_descriptor_tmpl.hh b/src/synchronizer/communication_descriptor_tmpl.hh index 1060aa06b..5af6080f0 100644 --- a/src/synchronizer/communication_descriptor_tmpl.hh +++ b/src/synchronizer/communication_descriptor_tmpl.hh @@ -1,146 +1,151 @@ /** * @file communication_descriptor_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Sep 6 14:03:16 2016 * * @brief implementation of CommunicationDescriptor * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu 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. * * Akantu 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 Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "communication_descriptor.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COMMUNICATION_DESCRIPTOR_TMPL_HH__ #define __AKANTU_COMMUNICATION_DESCRIPTOR_TMPL_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ /* Implementations */ /* -------------------------------------------------------------------------- */ template <class Entity> CommunicationDescriptor<Entity>::CommunicationDescriptor( Communication & communication, Array<Entity> & scheme, Communications<Entity> & communications, const SynchronizationTag & tag, UInt proc) : communication(communication), scheme(scheme), communications(communications), tag(tag), proc(proc), rank(communications.getCommunicator().whoAmI()) { counter = communications.getCounter(tag); } /* -------------------------------------------------------------------------- */ template <class Entity> CommunicationBuffer & CommunicationDescriptor<Entity>::getBuffer() { return communication.buffer(); } /* -------------------------------------------------------------------------- */ template <class Entity> CommunicationRequest & CommunicationDescriptor<Entity>::getRequest() { return communication.request(); } /* -------------------------------------------------------------------------- */ template <class Entity> void CommunicationDescriptor<Entity>::freeRequest() { const StaticCommunicator & comm = communications.getCommunicator(); comm.testRequest(communication.request()); comm.freeCommunicationRequest(communication.request()); communications.decrementPending(tag, communication.type()); } /* -------------------------------------------------------------------------- */ template <class Entity> Array<Entity> & CommunicationDescriptor<Entity>::getScheme() { return scheme; } +template <class Entity> +void CommunicationDescriptor<Entity>::resetBuffer() { + this->communication.buffer().reset(); +} + /* -------------------------------------------------------------------------- */ template <class Entity> void CommunicationDescriptor<Entity>::packData( DataAccessor<Entity> & accessor) { AKANTU_DEBUG_ASSERT( communication.type() == _send, "Cannot pack data on communication that is not of type _send"); accessor.packData(communication.buffer(), scheme, tag); } /* -------------------------------------------------------------------------- */ template <class Entity> void CommunicationDescriptor<Entity>::unpackData( DataAccessor<Entity> & accessor) { AKANTU_DEBUG_ASSERT( communication.type() == _recv, "Cannot unpack data from communication that is not of type _recv"); accessor.unpackData(communication.buffer(), scheme, tag); } /* -------------------------------------------------------------------------- */ template <class Entity> void CommunicationDescriptor<Entity>::postSend(int hash_id) { AKANTU_DEBUG_ASSERT(communication.type() == _send, "Cannot send a communication that is not of type _send"); Tag comm_tag = Tag::genTag(rank, counter, tag, hash_id); AKANTU_DEBUG_ASSERT(communication.buffer().getPackedSize() == communication.size(), "a problem have been introduced with " << "false sent sizes declaration " << communication.buffer().getPackedSize() << " != " << communication.size()); AKANTU_DEBUG_INFO("Posting send to proc " << proc << " (tag: " << tag << " - " << communication.size() << " data to send) " << " [ " << comm_tag << " ]"); CommunicationRequest & request = communication.request(); request = communications.getCommunicator().asyncSend(communication.buffer(), proc, comm_tag); communications.incrementPending(tag, communication.type()); } /* -------------------------------------------------------------------------- */ template <class Entity> void CommunicationDescriptor<Entity>::postRecv(int hash_id) { AKANTU_DEBUG_ASSERT(communication.type() == _recv, "Cannot receive data for communication (" << communication.type() << ")that is not of type _recv"); Tag comm_tag = Tag::genTag(proc, counter, tag, hash_id); AKANTU_DEBUG_INFO("Posting receive from proc " << proc << " (tag: " << tag << " - " << communication.size() << " data to receive) " << " [ " << comm_tag << " ]"); CommunicationRequest & request = communication.request(); request = communications.getCommunicator().asyncReceive( communication.buffer(), proc, comm_tag); communications.incrementPending(tag, communication.type()); } } // akantu #endif /* __AKANTU_COMMUNICATION_DESCRIPTOR_TMPL_HH__ */ diff --git a/src/synchronizer/communications_tmpl.hh b/src/synchronizer/communications_tmpl.hh index 740989c09..b1bc3f840 100644 --- a/src/synchronizer/communications_tmpl.hh +++ b/src/synchronizer/communications_tmpl.hh @@ -1,515 +1,515 @@ /** * @file communications_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Tue Sep 6 17:14:06 2016 * * @brief Implementation of Communications * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu 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. * * Akantu 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 Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "communications.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COMMUNICATIONS_TMPL_HH__ #define __AKANTU_COMMUNICATIONS_TMPL_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ template <class Entity> class Communications<Entity>::iterator { typedef typename std::map<UInt, Communication>::iterator communication_iterator; public: iterator() : communications(NULL) {} iterator(scheme_iterator scheme_it, communication_iterator comm_it, Communications<Entity> & communications, const SynchronizationTag & tag) : scheme_it(scheme_it), comm_it(comm_it), communications(&communications), tag(tag) {} iterator & operator=(const iterator & other) { if (this != &other) { this->scheme_it = other.scheme_it; this->comm_it = other.comm_it; this->communications = other.communications; this->tag = other.tag; } return *this; } iterator & operator++() { ++scheme_it; ++comm_it; return *this; } CommunicationDescriptor<Entity> operator*() { AKANTU_DEBUG_ASSERT( scheme_it->first == comm_it->first, "The two iterators are not in phase, something wrong" << " happened, time to take out your favorite debugger (" << scheme_it->first << " != " << comm_it->first << ")"); return CommunicationDescriptor<Entity>(comm_it->second, scheme_it->second, *communications, tag, scheme_it->first); } bool operator==(const iterator & other) const { return scheme_it == other.scheme_it && comm_it == other.comm_it; } bool operator!=(const iterator & other) const { return scheme_it != other.scheme_it || comm_it != other.comm_it; } private: scheme_iterator scheme_it; communication_iterator comm_it; Communications<Entity> * communications; SynchronizationTag tag; }; /* -------------------------------------------------------------------------- */ template <class Entity> class Communications<Entity>::tag_iterator { typedef std::map<SynchronizationTag, UInt>::const_iterator internal_iterator; public: tag_iterator(const internal_iterator & it) : it(it) {} tag_iterator & operator++() { ++it; return *this; } SynchronizationTag operator*() { return it->first; } bool operator==(const tag_iterator & other) const { return it == other.it; } bool operator!=(const tag_iterator & other) const { return it != other.it; } private: internal_iterator it; }; /* -------------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::CommunicationPerProcs & Communications<Entity>::getCommunications(const SynchronizationTag & tag, const CommunicationSendRecv & sr) { auto comm_it = this->communications[sr].find(tag); if (comm_it == this->communications[sr].end()) AKANTU_CUSTOM_EXCEPTION_INFO( debug::CommunicationException(), "No known communications for the tag: " << tag); return comm_it->second; } /* ---------------------------------------------------------------------- */ template <class Entity> UInt Communications<Entity>::getPending( const SynchronizationTag & tag, const CommunicationSendRecv & sr) const { const std::map<SynchronizationTag, UInt> & pending = pending_communications[sr]; auto it = pending.find(tag); if (it == pending.end()) return 0; return it->second; } /* -------------------------------------------------------------------------- */ template <class Entity> bool Communications<Entity>::hasPending( const SynchronizationTag & tag, const CommunicationSendRecv & sr) const { return this->hasCommunication(tag) && (this->getPending(tag, sr) != 0); } /* ---------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::iterator Communications<Entity>::begin(const SynchronizationTag & tag, const CommunicationSendRecv & sr) { auto & comms = this->getCommunications(tag, sr); return iterator(this->schemes[sr].begin(), comms.begin(), *this, tag); } template <class Entity> typename Communications<Entity>::iterator Communications<Entity>::end(const SynchronizationTag & tag, const CommunicationSendRecv & sr) { auto & comms = this->getCommunications(tag, sr); return iterator(this->schemes[sr].end(), comms.end(), *this, tag); } /* ---------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::iterator Communications<Entity>::waitAny(const SynchronizationTag & tag, const CommunicationSendRecv & sr) { auto & comms = this->getCommunications(tag, sr); auto it = comms.begin(); auto end = comms.end(); std::vector<CommunicationRequest> requests; for (; it != end; ++it) { auto & request = it->second.request(); if(!request.isFreed()) requests.push_back(request); } UInt req_id = communicator.waitAny(requests); if (req_id != UInt(-1)) { auto & request = requests[req_id]; UInt proc = sr == _recv ? request.getSource() : request.getDestination(); return iterator(this->schemes[sr].find(proc), comms.find(proc), *this, tag); } else { return this->end(tag, sr); } } /* ---------------------------------------------------------------------- */ template <class Entity> void Communications<Entity>::waitAll(const SynchronizationTag & tag, const CommunicationSendRecv & sr) { auto & comms = this->getCommunications(tag, sr); auto it = comms.begin(); auto end = comms.end(); std::vector<CommunicationRequest> requests; for (; it != end; ++it) { requests.push_back(it->second.request()); } communicator.waitAll(requests); } template <class Entity> void Communications<Entity>::incrementPending( const SynchronizationTag & tag, const CommunicationSendRecv & sr) { ++(pending_communications[sr][tag]); } template <class Entity> void Communications<Entity>::decrementPending( const SynchronizationTag & tag, const CommunicationSendRecv & sr) { - ++(pending_communications[sr][tag]); + --(pending_communications[sr][tag]); } template <class Entity> void Communications<Entity>::freeRequests(const SynchronizationTag & tag, const CommunicationSendRecv & sr) { iterator it = this->begin(tag, sr); iterator end = this->end(tag, sr); for (; it != end; ++it) { (*it).freeRequest(); } } /* -------------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::Scheme & Communications<Entity>::createScheme(UInt proc, const CommunicationSendRecv & sr) { scheme_iterator it = schemes[sr].find(proc); // if (it != schemes[sr].end()) { // AKANTU_CUSTOM_EXCEPTION_INFO(debug::CommunicationException(), // "Communication scheme(" // << sr // << ") already created for proc: " << // proc); // } return schemes[sr][proc]; } template <class Entity> void Communications<Entity>::resetSchemes(const CommunicationSendRecv & sr) { scheme_iterator it = this->schemes[sr].begin(); scheme_iterator end = this->schemes[sr].end(); for (; it != end; ++it) { it->second.resize(0); } } /* -------------------------------------------------------------------------- */ template <class Entity> void Communications<Entity>::setCommunicationSize( const SynchronizationTag & tag, UInt proc, UInt size, const CommunicationSendRecv & sr) { // accessor that creates if it does not exists auto & comms = this->communications[sr]; auto & comms_per_tag = comms[tag]; comms_per_tag[proc].resize(size); } /* -------------------------------------------------------------------------- */ template <class Entity> void Communications<Entity>::initializeCommunications( const SynchronizationTag & tag) { for (auto t = send_recv_t::begin(); t != send_recv_t::end(); ++t) { pending_communications[*t].insert(std::make_pair(tag, 0)); auto & comms = this->communications[*t]; auto & comms_per_tag = comms.insert(std::make_pair(tag, CommunicationPerProcs())) .first->second; for (auto pair : this->schemes[*t]) { comms_per_tag.emplace(std::piecewise_construct, std::forward_as_tuple(pair.first), std::forward_as_tuple(*t)); } } comm_counter.insert(std::make_pair(tag, 0)); } /* -------------------------------------------------------------------------- */ template <class Entity> Communications<Entity>::Communications(const StaticCommunicator & communicator) : communicator(communicator) {} /* ---------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::iterator Communications<Entity>::begin_send(const SynchronizationTag & tag) { return this->begin(tag, _send); } template <class Entity> typename Communications<Entity>::iterator Communications<Entity>::end_send(const SynchronizationTag & tag) { return this->end(tag, _send); } /* ---------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::iterator Communications<Entity>::begin_recv(const SynchronizationTag & tag) { return this->begin(tag, _recv); } template <class Entity> typename Communications<Entity>::iterator Communications<Entity>::end_recv(const SynchronizationTag & tag) { return this->end(tag, _recv); } /* -------------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::tag_iterator Communications<Entity>::begin_tag() { return tag_iterator(comm_counter.begin()); } template <class Entity> typename Communications<Entity>::tag_iterator Communications<Entity>::end_tag() { return tag_iterator(comm_counter.end()); } /* -------------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::scheme_iterator Communications<Entity>::begin_send_scheme() { return this->schemes[_send].begin(); } template <class Entity> typename Communications<Entity>::scheme_iterator Communications<Entity>::end_send_scheme() { return this->schemes[_send].end(); } /* -------------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::const_scheme_iterator Communications<Entity>::begin_send_scheme() const { return this->schemes[_send].begin(); } template <class Entity> typename Communications<Entity>::const_scheme_iterator Communications<Entity>::end_send_scheme() const { return this->schemes[_send].end(); } /* -------------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::scheme_iterator Communications<Entity>::begin_recv_scheme() { return this->schemes[_recv].begin(); } template <class Entity> typename Communications<Entity>::scheme_iterator Communications<Entity>::end_recv_scheme() { return this->schemes[_recv].end(); } /* -------------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::const_scheme_iterator Communications<Entity>::begin_recv_scheme() const { return this->schemes[_recv].begin(); } template <class Entity> typename Communications<Entity>::const_scheme_iterator Communications<Entity>::end_recv_scheme() const { return this->schemes[_recv].end(); } /* ------------------------------------------------------------------------ */ template <class Entity> bool Communications<Entity>::hasCommunication( const SynchronizationTag & tag) const { return (communications[_send].find(tag) != communications[_send].end()); } template <class Entity> void Communications<Entity>::incrementCounter(const SynchronizationTag & tag) { auto it = comm_counter.find(tag); if (it == comm_counter.end()) { AKANTU_CUSTOM_EXCEPTION_INFO( debug::CommunicationException(), "No counter initialized in communications for the tags: " << tag); } ++(it->second); } template <class Entity> UInt Communications<Entity>::getCounter(const SynchronizationTag & tag) const { auto it = comm_counter.find(tag); if (it == comm_counter.end()) { AKANTU_CUSTOM_EXCEPTION_INFO( debug::CommunicationException(), "No counter initialized in communications for the tags: " << tag); } return it->second; } template <class Entity> bool Communications<Entity>::hasPendingRecv( const SynchronizationTag & tag) const { return this->hasPending(tag, _recv); } template <class Entity> bool Communications<Entity>::hasPendingSend( const SynchronizationTag & tag) const { return this->hasPending(tag, _send); } template <class Entity> const StaticCommunicator & Communications<Entity>::getCommunicator() const { return communicator; } /* -------------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::iterator Communications<Entity>::waitAnyRecv(const SynchronizationTag & tag) { return this->waitAny(tag, _recv); } template <class Entity> typename Communications<Entity>::iterator Communications<Entity>::waitAnySend(const SynchronizationTag & tag) { return this->waitAny(tag, _send); } template <class Entity> void Communications<Entity>::waitAllRecv(const SynchronizationTag & tag) { this->waitAll(tag, _recv); } template <class Entity> void Communications<Entity>::waitAllSend(const SynchronizationTag & tag) { this->waitAll(tag, _send); } template <class Entity> void Communications<Entity>::freeSendRequests(const SynchronizationTag & tag) { this->freeRequests(tag, _send); } template <class Entity> void Communications<Entity>::freeRecvRequests(const SynchronizationTag & tag) { this->freeRequests(tag, _recv); } /* -------------------------------------------------------------------------- */ template <class Entity> typename Communications<Entity>::Scheme & Communications<Entity>::createSendScheme(UInt proc) { return createScheme(proc, _send); } template <class Entity> typename Communications<Entity>::Scheme & Communications<Entity>::createRecvScheme(UInt proc) { return createScheme(proc, _recv); } /* -------------------------------------------------------------------------- */ template <class Entity> void Communications<Entity>::resetSchemes() { resetSchemes(_send); resetSchemes(_recv); } /* -------------------------------------------------------------------------- */ template <class Entity> const typename Communications<Entity>::Scheme & Communications<Entity>::getSendScheme(UInt proc) const { return this->schemes[_send].find(proc)->second; } /* -------------------------------------------------------------------------- */ template <class Entity> const typename Communications<Entity>::Scheme & Communications<Entity>::getRecvScheme(UInt proc) const { return this->schemes[_recv].find(proc)->second; } /* -------------------------------------------------------------------------- */ template <class Entity> void Communications<Entity>::setSendCommunicationSize( const SynchronizationTag & tag, UInt proc, UInt size) { this->setCommunicationSize(tag, proc, size, _send); } template <class Entity> void Communications<Entity>::setRecvCommunicationSize( const SynchronizationTag & tag, UInt proc, UInt size) { this->setCommunicationSize(tag, proc, size, _recv); } } // akantu #endif /* __AKANTU_COMMUNICATIONS_TMPL_HH__ */ diff --git a/src/synchronizer/node_synchronizer.hh b/src/synchronizer/node_synchronizer.hh index 7ac3bdf1d..c22f15c29 100644 --- a/src/synchronizer/node_synchronizer.hh +++ b/src/synchronizer/node_synchronizer.hh @@ -1,83 +1,78 @@ /** * @file node_synchronizer.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Sep 23 11:45:24 2016 * * @brief Synchronizer for nodal information * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu 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. * * Akantu 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 Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ -#include "synchronizer_impl.hh" #include "mesh_events.hh" +#include "synchronizer_impl.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NODE_SYNCHRONIZER_HH__ #define __AKANTU_NODE_SYNCHRONIZER_HH__ namespace akantu { -class NodeSynchronizer : public MeshEventHandler, public SynchronizerImpl<UInt> { +class NodeSynchronizer : public MeshEventHandler, + public SynchronizerImpl<UInt> { public: NodeSynchronizer( Mesh & mesh, const ID & id = "element_synchronizer", MemoryID memory_id = 0, const bool register_to_event_manager = true, StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator()); virtual ~NodeSynchronizer(); friend class NodeInfoPerProc; /// function to implement to react on akantu::NewNodesEvent - virtual void onNodesAdded(__attribute__((unused)) const Array<UInt> & nodes_list, - __attribute__((unused)) const NewNodesEvent & event) {} + virtual void onNodesAdded(const Array<UInt> &, const NewNodesEvent &) {} /// function to implement to react on akantu::RemovedNodesEvent - virtual void onNodesRemoved(__attribute__((unused)) const Array<UInt> & nodes_list, - __attribute__((unused)) const Array<UInt> & new_numbering, - __attribute__((unused)) const RemovedNodesEvent & event) {} + virtual void onNodesRemoved(const Array<UInt> &, const Array<UInt> &, + const RemovedNodesEvent &) {} /// function to implement to react on akantu::NewElementsEvent - virtual void onElementsAdded(__attribute__((unused)) const Array<Element> & elements_list, - __attribute__((unused)) const NewElementsEvent & event) {} + virtual void onElementsAdded(const Array<Element> &, + const NewElementsEvent &) {} /// function to implement to react on akantu::RemovedElementsEvent - virtual void - onElementsRemoved(__attribute__((unused)) const Array<Element> & elements_list, - __attribute__((unused)) const ElementTypeMapArray<UInt> & new_numbering, - __attribute__((unused)) const RemovedElementsEvent & event) {} + virtual void onElementsRemoved(const Array<Element> &, + const ElementTypeMapArray<UInt> &, + const RemovedElementsEvent &) {} /// function to implement to react on akantu::ChangedElementsEvent - virtual void - onElementsChanged(__attribute__((unused)) const Array<Element> & old_elements_list, - __attribute__((unused)) const Array<Element> & new_elements_list, - __attribute__((unused)) const ElementTypeMapArray<UInt> & new_numbering, - __attribute__((unused)) const ChangedElementsEvent & event) {} - + virtual void onElementsChanged(const Array<Element> &, const Array<Element> &, + const ElementTypeMapArray<UInt> &, + const ChangedElementsEvent &) {} public: AKANTU_GET_MACRO(Mesh, mesh, Mesh &); protected: Mesh & mesh; }; -} // akantu +} // akantu #endif /* __AKANTU_NODE_SYNCHRONIZER_HH__ */ diff --git a/src/synchronizer/synchronizer_impl_tmpl.hh b/src/synchronizer/synchronizer_impl_tmpl.hh index a6b590d40..df93c3ca7 100644 --- a/src/synchronizer/synchronizer_impl_tmpl.hh +++ b/src/synchronizer/synchronizer_impl_tmpl.hh @@ -1,207 +1,209 @@ /** * @file synchronizer_impl_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Wed Aug 24 13:29:47 2016 * * @brief Implementation of the SynchronizerImpl * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu 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. * * Akantu 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 Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "synchronizer_impl.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SYNCHRONIZER_IMPL_TMPL_HH__ #define __AKANTU_SYNCHRONIZER_IMPL_TMPL_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ template <class Entity> SynchronizerImpl<Entity>::SynchronizerImpl(const ID & id, MemoryID memory_id, const StaticCommunicator & comm) : Synchronizer(id, memory_id, comm), communications(comm) {} /* -------------------------------------------------------------------------- */ template <class Entity> void SynchronizerImpl<Entity>::asynchronousSynchronizeImpl( DataAccessor<Entity> & data_accessor, const SynchronizationTag & tag) { AKANTU_DEBUG_IN(); if (!this->communications.hasCommunication(tag)) this->computeBufferSize(data_accessor, tag); this->communications.incrementCounter(tag); // Posting the receive ------------------------------------------------------- if (this->communications.hasPendingRecv(tag)) { AKANTU_CUSTOM_EXCEPTION_INFO( debug::CommunicationException(), - "There must be some pending receive communications." - << " Tag is " << tag); + "There must still be some pending receive communications." + << " Tag is " << tag << " Cannot start new ones"); } auto recv_it = this->communications.begin_recv(tag); auto recv_end = this->communications.end_recv(tag); for (; recv_it != recv_end; ++recv_it) { auto comm_desc = *recv_it; comm_desc.postRecv(this->hash_id); } // Posting the sends ------------------------------------------------------- if (communications.hasPendingSend(tag)) { AKANTU_CUSTOM_EXCEPTION_INFO( debug::CommunicationException(), "There must be some pending sending communications." << " Tag is " << tag); } auto send_it = communications.begin_send(tag); auto send_end = communications.end_send(tag); for (; send_it != send_end; ++send_it) { auto comm_desc = *send_it; + comm_desc.resetBuffer(); #ifndef AKANTU_NDEBUG this->packSanityCheckData(comm_desc); #endif comm_desc.packData(data_accessor); comm_desc.postSend(this->hash_id); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class Entity> void SynchronizerImpl<Entity>::waitEndSynchronizeImpl( DataAccessor<Entity> & data_accessor, const SynchronizationTag & tag) { AKANTU_DEBUG_IN(); #ifndef AKANTU_NDEBUG if (!this->communications.hasPendingRecv(tag) && nb_proc > 1) AKANTU_CUSTOM_EXCEPTION_INFO(debug::CommunicationException(), "No pending communication with the tag \"" << tag); #endif auto recv_end = this->communications.end_recv(tag); decltype(recv_end) recv_it; while ((recv_it = this->communications.waitAnyRecv(tag)) != recv_end) { auto comm_desc = *recv_it; #ifndef AKANTU_NDEBUG this->unpackSanityCheckData(comm_desc); #endif comm_desc.unpackData(data_accessor); + comm_desc.resetBuffer(); comm_desc.freeRequest(); } this->communications.waitAllSend(tag); this->communications.freeSendRequests(tag); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class Entity> void SynchronizerImpl<Entity>::computeAllBufferSizes( DataAccessor<Entity> & data_accessor) { auto it = this->communications.begin_tag(); auto end = this->communications.end_tag(); for (; it != end; ++it) { auto tag = *it; this->computeBufferSize(data_accessor, tag); } } /* -------------------------------------------------------------------------- */ template <class Entity> void SynchronizerImpl<Entity>::computeBufferSizeImpl( DataAccessor<Entity> & data_accessor, const SynchronizationTag & tag) { AKANTU_DEBUG_IN(); this->communications.initializeCommunications(tag); AKANTU_DEBUG_ASSERT(communications.hasCommunication(tag) == true, "Communications where not properly initialized"); auto recv_it = this->communications.begin_recv_scheme(); auto recv_end = this->communications.end_recv_scheme(); for (; recv_it != recv_end; ++recv_it) { auto proc = recv_it->first; auto & scheme = recv_it->second; UInt srecv = 0; #ifndef AKANTU_NDEBUG srecv += this->sanityCheckDataSize(scheme, tag); #endif srecv += data_accessor.getNbData(scheme, tag); AKANTU_DEBUG_INFO("I have " << srecv << "(" << printMemorySize<char>(srecv) << " - " << scheme.getSize() << " element(s)) data to receive from " << proc << " for tag " << tag); this->communications.setRecvCommunicationSize(tag, proc, srecv); } auto send_it = this->communications.begin_send_scheme(); auto send_end = this->communications.end_send_scheme(); for (; send_it != send_end; ++send_it) { auto proc = send_it->first; auto & scheme = send_it->second; UInt ssend = 0; #ifndef AKANTU_NDEBUG ssend += this->sanityCheckDataSize(scheme, tag); #endif ssend += data_accessor.getNbData(scheme, tag); AKANTU_DEBUG_INFO("I have " << ssend << "(" << printMemorySize<char>(ssend) << " - " << scheme.getSize() << " element(s)) data to send to " << proc << " for tag " << tag); this->communications.setSendCommunicationSize(tag, proc, ssend); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class Entity> UInt SynchronizerImpl<Entity>::sanityCheckDataSize( const Array<Entity> &, const SynchronizationTag &) const { return 0; } /* -------------------------------------------------------------------------- */ template <class Entity> void SynchronizerImpl<Entity>::packSanityCheckData( CommunicationDescriptor<Entity> &) const {} /* -------------------------------------------------------------------------- */ template <class Entity> void SynchronizerImpl<Entity>::unpackSanityCheckData( CommunicationDescriptor<Entity> &) const {} /* -------------------------------------------------------------------------- */ } // akantu #endif /* __AKANTU_SYNCHRONIZER_IMPL_TMPL_HH__ */ diff --git a/test/test_model/test_model_solver/test_model_solver_dynamic.cc b/test/test_model/test_model_solver/test_model_solver_dynamic.cc index 1f0728dcb..bc69d292f 100644 --- a/test/test_model/test_model_solver/test_model_solver_dynamic.cc +++ b/test/test_model/test_model_solver/test_model_solver_dynamic.cc @@ -1,544 +1,544 @@ /** * @file test_dof_manager_default.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Wed Feb 24 12:28:44 2016 * * @brief Test default dof manager * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu 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. * * Akantu 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 Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "dof_manager.hh" #include "mesh.hh" #include "mesh_accessor.hh" #include "model_solver.hh" #include "non_linear_solver.hh" #include "sparse_matrix.hh" #include "static_communicator.hh" #include "synchronizer_registry.hh" #include "data_accessor.hh" #include "element_synchronizer.hh" /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ #ifndef EXPLICIT #define EXPLICIT true #endif using namespace akantu; class MyModel; static void genMesh(Mesh & mesh, UInt nb_nodes); /** * =\o-----o-----o-> F * | | * |---- L ----| */ class MyModel : public ModelSolver, public DataAccessor<Element> { public: MyModel(Real F, Mesh & mesh, bool lumped) : ModelSolver(mesh, "model_solver", 0), mesh(mesh), nb_dofs(mesh.getNbNodes()), nb_elements(mesh.getNbElement()), E(1.), A(1.), rho(1.), lumped(lumped), displacement(nb_dofs, 1, "disp"), velocity(nb_dofs, 1, "velo"), acceleration(nb_dofs, 1, "accel"), blocked(nb_dofs, 1, "blocked"), forces(nb_dofs, 1, "force_ext"), internal_forces(nb_dofs, 1, "force_int"), stresses(nb_elements, 1, "stress"), strains(nb_elements, 1, "strain"), initial_lengths(nb_elements, 1, "L0") { this->initDOFManager(); this->getDOFManager().registerDOFs("disp", displacement, _dst_nodal); this->getDOFManager().registerDOFsDerivative("disp", 1, velocity); this->getDOFManager().registerDOFsDerivative("disp", 2, acceleration); this->getDOFManager().registerBlockedDOFs("disp", blocked); this->getDOFManager().getNewMatrix("K", _symmetric); this->getDOFManager().getNewMatrix("M", "K"); this->getDOFManager().getNewMatrix("J", "K"); this->getDOFManager().getNewLumpedMatrix("M"); if (lumped) { this->assembleLumpedMass(); } else { this->assembleMass(); this->assembleStiffness(); } this->assembleJacobian(); displacement.set(0.); velocity.set(0.); acceleration.set(0.); forces.set(0.); blocked.set(false); UInt global_nb_nodes = mesh.getNbGlobalNodes(); for(UInt n = 0; n < nb_dofs; ++n) { if (mesh.getGlobalNodesIds()(n) == (global_nb_nodes -1)) forces(n, _x) = F; if (mesh.getGlobalNodesIds()(n) == 0) blocked(n, _x) = true; } auto cit = this->mesh.getConnectivity(_segment_2).begin(2); auto cend = this->mesh.getConnectivity(_segment_2).end(2); auto L_it = this->initial_lengths.begin(); for (; cit != cend; ++cit, ++L_it) { const Vector<UInt> & conn = *cit; UInt n1 = conn(0); UInt n2 = conn(1); Real p1 = this->mesh.getNodes()(n1, _x); Real p2 = this->mesh.getNodes()(n2, _x); *L_it = std::abs(p2 - p1); } this->registerDataAccessor(*this); this->registerSynchronizer(const_cast<ElementSynchronizer &>(this->mesh.getElementSynchronizer()), _gst_user_1); } void assembleLumpedMass() { Array<Real> & M = this->getDOFManager().getLumpedMatrix("M"); M.clear(); this->assembleLumpedMass(_not_ghost); if (this->mesh.getNbElement(_segment_2, _ghost) > 0) this->assembleLumpedMass(_ghost); } void assembleLumpedMass(const GhostType & ghost_type) { Array<Real> & M = this->getDOFManager().getLumpedMatrix("M"); Array<Real> m_all_el(this->mesh.getNbElement(_segment_2, ghost_type), 2); Array<Real>::vector_iterator m_it = m_all_el.begin(2); auto cit = this->mesh.getConnectivity(_segment_2, ghost_type).begin(2); auto cend = this->mesh.getConnectivity(_segment_2, ghost_type).end(2); for (; cit != cend; ++cit, ++m_it) { const Vector<UInt> & conn = *cit; UInt n1 = conn(0); UInt n2 = conn(1); Real p1 = this->mesh.getNodes()(n1, _x); Real p2 = this->mesh.getNodes()(n2, _x); Real L = std::abs(p2 - p1); Real M_n = rho * A * L / 2; (*m_it)(0) = (*m_it)(1) = M_n; } this->getDOFManager().assembleElementalArrayLocalArray( m_all_el, M, _segment_2, ghost_type); } void assembleMass() { SparseMatrix & M = this->getDOFManager().getMatrix("M"); M.clear(); Array<Real> m_all_el(this->nb_elements, 4); Array<Real>::matrix_iterator m_it = m_all_el.begin(2, 2); auto cit = this->mesh.getConnectivity(_segment_2).begin(2); auto cend = this->mesh.getConnectivity(_segment_2).end(2); Matrix<Real> m(2, 2); m(0, 0) = m(1, 1) = 2; m(0, 1) = m(1, 0) = 1; // under integrated // m(0, 0) = m(1, 1) = 3./2.; // m(0, 1) = m(1, 0) = 3./2.; // lumping the mass matrix // m(0, 0) += m(0, 1); // m(1, 1) += m(1, 0); // m(0, 1) = m(1, 0) = 0; for (; cit != cend; ++cit, ++m_it) { const Vector<UInt> & conn = *cit; UInt n1 = conn(0); UInt n2 = conn(1); Real p1 = this->mesh.getNodes()(n1, _x); Real p2 = this->mesh.getNodes()(n2, _x); Real L = std::abs(p2 - p1); Matrix<Real> & m_el = *m_it; m_el = m; m_el *= rho * A * L / 6.; } this->getDOFManager().assembleElementalMatricesToMatrix( "M", "disp", m_all_el, _segment_2); } void assembleJacobian() {} void assembleStiffness() { SparseMatrix & K = this->getDOFManager().getMatrix("K"); K.clear(); Matrix<Real> k(2, 2); k(0, 0) = k(1, 1) = 1; k(0, 1) = k(1, 0) = -1; Array<Real> k_all_el(this->nb_elements, 4); auto k_it = k_all_el.begin(2, 2); auto cit = this->mesh.getConnectivity(_segment_2).begin(2); auto cend = this->mesh.getConnectivity(_segment_2).end(2); for (; cit != cend; ++cit, ++k_it) { const auto & conn = *cit; UInt n1 = conn(0); UInt n2 = conn(1); Real p1 = this->mesh.getNodes()(n1, _x); Real p2 = this->mesh.getNodes()(n2, _x); Real L = std::abs(p2 - p1); auto & k_el = *k_it; k_el = k; k_el *= E * A / L; } this->getDOFManager().assembleElementalMatricesToMatrix( "K", "disp", k_all_el, _segment_2); } void assembleResidual() { this->getDOFManager().assembleToResidual("disp", forces); internal_forces.clear(); this->assembleResidual(_not_ghost); - this->synchronize(_gst_user_1); + this->synchronize(_gst_user_1); this->getDOFManager().assembleToResidual("disp", internal_forces, -1.); } void assembleResidual(const GhostType & ghost_type) { Array<Real> forces_internal_el( this->mesh.getNbElement(_segment_2, ghost_type), 2); auto cit = this->mesh.getConnectivity(_segment_2, ghost_type).begin(2); auto cend = this->mesh.getConnectivity(_segment_2, ghost_type).end(2); auto f_it = forces_internal_el.begin(2); auto strain_it = this->strains.begin(); auto stress_it = this->stresses.begin(); auto L_it = this->initial_lengths.begin(); for (; cit != cend; ++cit, ++f_it, ++strain_it, ++stress_it, ++L_it) { const auto & conn = *cit; UInt n1 = conn(0); UInt n2 = conn(1); Real u1 = this->displacement(n1, _x); Real u2 = this->displacement(n2, _x); *strain_it = (u2 - u1) / *L_it; *stress_it = E * *strain_it; Real f_n = A * *stress_it; Vector<Real> & f = *f_it; f(0) = -f_n; f(1) = f_n; } this->getDOFManager().assembleElementalArrayLocalArray( forces_internal_el, internal_forces, _segment_2, ghost_type); } Real getPotentialEnergy() { Real res = 0; if (!lumped) { res = this->mulVectMatVect(this->displacement, this->getDOFManager().getMatrix("K"), this->displacement); } else { auto strain_it = this->strains.begin(); auto stress_it = this->stresses.begin(); auto strain_end = this->strains.end(); auto L_it = this->initial_lengths.begin(); for (; strain_it != strain_end; ++strain_it, ++stress_it, ++L_it) { res += *strain_it * *stress_it * A * *L_it; } StaticCommunicator::getStaticCommunicator().allReduce(res, _so_sum); } return res / 2.; } Real getKineticEnergy() { Real res = 0; if (!lumped) { res = this->mulVectMatVect( this->velocity, this->getDOFManager().getMatrix("M"), this->velocity); } else { auto & m = this->getDOFManager().getLumpedMatrix("M"); auto it = velocity.begin(); auto end = velocity.end(); auto m_it = m.begin(); for (UInt node = 0; it != end; ++it, ++m_it, ++node) { if (mesh.isLocalOrMasterNode(node)) res += *m_it * *it * *it; } StaticCommunicator::getStaticCommunicator().allReduce(res, _so_sum); } return res / 2.; } Real getExternalWorkIncrement() { Real res = 0; auto it = velocity.begin(); auto end = velocity.end(); auto if_it = internal_forces.begin(); auto ef_it = forces.begin(); auto b_it = blocked.begin(); for (UInt node = 0; it != end; ++it, ++if_it, ++ef_it, ++b_it, ++node) { if (mesh.isLocalOrMasterNode(node)) res += (*b_it ? - *if_it : *ef_it) * *it; } StaticCommunicator::getStaticCommunicator().allReduce(res, _so_sum); return res * this->getTimeStep(); } Real mulVectMatVect(const Array<Real> & x, const SparseMatrix & A, const Array<Real> & y) { Array<Real> Ay(this->nb_dofs, 1, 0.); A.matVecMul(y, Ay); Real res = 0.; Array<Real>::const_scalar_iterator it = Ay.begin(); Array<Real>::const_scalar_iterator end = Ay.end(); Array<Real>::const_scalar_iterator x_it = x.begin(); for (; it != end; ++it, ++x_it) { res += *x_it * *it; } StaticCommunicator::getStaticCommunicator().allReduce(res, _so_sum); return res; } void predictor() {} void corrector() {} /* ------------------------------------------------------------------------ */ UInt getNbData(const Array<Element> & elements, const SynchronizationTag &) const { return elements.getSize() * sizeof(Real); } void packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) const { if(tag == _gst_user_1) { for(const auto & el : elements) { buffer << this->stresses(el.element); } } } void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) { if(tag == _gst_user_1) { auto cit = this->mesh.getConnectivity(_segment_2, _ghost).begin(2); for(const auto & el : elements) { Real stress; buffer >> stress; Real f = A * stress; Vector<UInt> conn = cit[el.element]; this->internal_forces(conn(0), _x) += -f; this->internal_forces(conn(1), _x) += f; } } } private: Mesh & mesh; UInt nb_dofs; UInt nb_elements; Real E, A, rho; bool lumped; public: Array<Real> displacement; Array<Real> velocity; Array<Real> acceleration; Array<bool> blocked; Array<Real> forces; Array<Real> internal_forces; Array<Real> stresses; Array<Real> strains; Array<Real> initial_lengths; }; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize(argc, argv); UInt prank = StaticCommunicator::getStaticCommunicator().whoAmI(); UInt global_nb_nodes = 201; UInt max_steps = 200; Real time_step = 0.001; Mesh mesh(1); Real F = -9.81; bool _explicit = EXPLICIT; genMesh(mesh, global_nb_nodes); mesh.distribute(); MyModel model(F, mesh, _explicit); if (!_explicit) { model.getNewSolver("dynamic", _tsst_dynamic, _nls_newton_raphson); model.setIntegrationScheme("dynamic", "disp", _ist_trapezoidal_rule_2, IntegrationScheme::_displacement); } else { model.getNewSolver("dynamic", _tsst_dynamic_lumped, _nls_lumped); model.setIntegrationScheme("dynamic", "disp", _ist_central_difference, IntegrationScheme::_acceleration); } model.setTimeStep(time_step); // #if EXPLICIT == true // std::ofstream output("output_dynamic_explicit.csv"); // #else // std::ofstream output("output_dynamic_implicit.csv"); // #endif if (prank == 0) { std::cout << std::scientific; std::cout << std::setw(14) << "time" << "," << std::setw(14) << "wext" << "," << std::setw(14) << "epot" << "," << std::setw(14) << "ekin" << "," << std::setw(14) << "total" << std::endl; } Real wext = 0.; model.assembleResidual(); Real epot = model.getPotentialEnergy(); Real ekin = model.getKineticEnergy(); Real einit = ekin + epot; Real etot = ekin + epot - wext - einit; if (prank == 0) { std::cout << std::setw(14) << 0. << "," << std::setw(14) << wext << "," << std::setw(14) << epot << "," << std::setw(14) << ekin << "," << std::setw(14) << etot << std::endl; } #if EXPLICIT == false NonLinearSolver & solver = model.getDOFManager().getNonLinearSolver("dynamic"); #endif for (UInt i = 1; i < max_steps + 1; ++i) { model.solveStep(); #if EXPLICIT == false UInt nb_iter = solver.get("nb_iterations"); Real error = solver.get("error"); bool converged = solver.get("converged"); std::cout << error << " " << nb_iter << " -> " << converged << std::endl; #endif epot = model.getPotentialEnergy(); ekin = model.getKineticEnergy(); wext += model.getExternalWorkIncrement(); etot = ekin + epot - wext - einit; if (prank == 0) { std::cout << std::setw(14) << time_step * i << "," << std::setw(14) << wext << "," << std::setw(14) << epot << "," << std::setw(14) << ekin << "," << std::setw(14) << etot << std::endl; } if (std::abs(etot) > 1e1) { AKANTU_DEBUG_ERROR("The total energy of the system is not conserved!"); } } // output.close(); finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ void genMesh(Mesh & mesh, UInt nb_nodes) { MeshAccessor mesh_accessor(mesh); Array<Real> & nodes = mesh_accessor.getNodes(); Array<UInt> & conn = mesh_accessor.getConnectivity(_segment_2); nodes.resize(nb_nodes); for (UInt n = 0; n < nb_nodes; ++n) { nodes(n, _x) = n * (1. / (nb_nodes - 1)); } conn.resize(nb_nodes - 1); for (UInt n = 0; n < nb_nodes - 1; ++n) { conn(n, 0) = n; conn(n, 1) = n + 1; } } diff --git a/test/test_synchronizer/CMakeLists.txt b/test/test_synchronizer/CMakeLists.txt index 41a7a450c..208658c9d 100644 --- a/test/test_synchronizer/CMakeLists.txt +++ b/test/test_synchronizer/CMakeLists.txt @@ -1,75 +1,76 @@ #=============================================================================== # @file CMakeLists.txt # # @author Nicolas Richart <nicolas.richart@epfl.ch> # # @date creation: Fri Sep 03 2010 # @date last modification: Wed Jan 20 2016 # # @brief configuration for synchronizer tests # # @section LICENSE # # Copyright (©) 2010-2012, 2014, 2015 EPFL (Ecole Polytechnique Fédérale de # Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des # Solides) # # Akantu 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. # # Akantu 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 Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== add_mesh(test_synchronizer_communication_mesh cube.geo 3 2) register_test(test_synchronizer_communication SOURCES test_synchronizer_communication.cc DEPENDS test_synchronizer_communication_mesh PACKAGE parallel + PARALLEL ) # if(DEFINED AKANTU_DAMAGE_NON_LOCAL) # add_executable(test_grid_synchronizer_check_neighbors test_grid_synchronizer_check_neighbors.cc test_grid_tools.hh) # target_link_libraries(test_grid_synchronizer_check_neighbors akantu) # if(AKANTU_EXTRA_CXX_FLAGS) # set_target_properties(test_grid_synchronizer_check_neighbors PROPERTIES COMPILE_FLAGS ${AKANTU_EXTRA_CXX_FLAGS}) # endif() # endif() # register_test(test_grid_synchronizer # SOURCES test_grid_synchronizer.cc test_data_accessor.hh # DEPENDS test_synchronizer_communication_mesh test_grid_synchronizer_check_neighbors # EXTRA_FILES test_grid_synchronizer_check_neighbors.cc test_grid_tools.hh # PACKAGE damage_non_local # ) # register_test(test_dof_synchronizer # SOURCES test_dof_synchronizer.cc test_data_accessor.hh # FILES_TO_COPY bar.msh # PACKAGE parallel # PARALLEL # ) # register_test(test_dof_synchronizer_communication # SOURCES test_dof_synchronizer_communication.cc test_dof_data_accessor.hh # DEPENDS test_synchronizer_communication_mesh # PACKAGE parallel # ) # register_test(test_data_distribution # SOURCES test_data_distribution.cc # FILES_TO_COPY data_split.msh # PACKAGE parallel # )