3#ifndef DUNE_COMMON_PARALLEL_VARIABLESIZECOMMUNICATOR_HH
4#define DUNE_COMMON_PARALLEL_VARIABLESIZECOMMUNICATOR_HH
45template<
class T,
class Allocator=std::allocator<T> >
53 explicit MessageBuffer(
int size)
54 : buffer_(new T[size]), size_(size), position_(0)
60 explicit MessageBuffer(
const MessageBuffer& o)
61 : buffer_(new T[o.size_]), size_(o.size_), position_(o.position_)
73 void write(
const T& data)
75 buffer_[position_++]=data;
84 data=buffer_[position_++];
103 return position_==size_;
111 bool hasSpaceForItems(
int noItems)
113 return position_+noItems<=size_;
119 std::size_t size()
const
144 std::size_t position_;
150class InterfaceTracker
158 InterfaceTracker(
int rank, InterfaceInformation info, std::size_t fixedsize=0,
159 bool allocateSizes=
false)
160 :
fixedSize(fixedsize),rank_(rank), index_(), interface_(info), sizes_()
164 sizes_.resize(info.size());
171 void moveToNextIndex()
174 assert(index_<=interface_.size());
181 void increment(std::size_t i)
184 assert(index_<=interface_.size());
190 bool finished()
const
192 return index_==interface_.size();
195 void skipZeroIndices()
198 while(sizes_.size() && index_!=interface_.size() &&!size())
206 std::size_t index()
const
208 return interface_[index_];
213 std::size_t size()
const
215 assert(sizes_.size());
216 return sizes_[index_];
221 std::size_t* getSizesPointer()
231 return !interface_.size();
238 std::size_t indicesLeft()
const
240 return interface_.size()-index_;
256 std::size_t offset()
const
266 InterfaceInformation interface_;
267 std::vector<std::size_t> sizes_;
310template<
class Allocator=std::allocator<std::pair<InterfaceInformation,InterfaceInformation> > >
318 typedef std::map<int,std::pair<InterfaceInformation,InterfaceInformation>,
320 typename std::allocator_traits<Allocator>::template rebind_alloc< std::pair<const int,std::pair<InterfaceInformation,InterfaceInformation> > > >
InterfaceMap;
322#ifndef DUNE_PARALLEL_MAX_COMMUNICATION_BUFFER_SIZE
330 : maxBufferSize_(32768), interface_(&inf)
332 MPI_Comm_dup(comm, &communicator_);
339 : maxBufferSize_(32768), interface_(&inf.interfaces())
351 : maxBufferSize_(DUNE_PARALLEL_MAX_COMMUNICATION_BUFFER_SIZE),
354 MPI_Comm_dup(comm, &communicator_);
361 : maxBufferSize_(DUNE_PARALLEL_MAX_COMMUNICATION_BUFFER_SIZE),
362 interface_(&inf.interfaces())
364 MPI_Comm_dup(inf.communicator(), &communicator_);
374 : maxBufferSize_(max_buffer_size), interface_(&inf)
376 MPI_Comm_dup(comm, &communicator_);
385 : maxBufferSize_(max_buffer_size), interface_(&inf.interfaces())
392 MPI_Comm_free(&communicator_);
400 maxBufferSize_ = other.maxBufferSize_;
401 interface_ = other.interface_;
402 MPI_Comm_dup(other.communicator_, &communicator_);
413 maxBufferSize_ = other.maxBufferSize_;
414 interface_ = other.interface_;
415 MPI_Comm_free(&communicator_);
416 MPI_Comm_dup(other.communicator_, &communicator_);
440 template<
class DataHandle>
443 communicate<true>(handle);
465 template<
class DataHandle>
468 communicate<false>(handle);
472 template<
bool FORWARD,
class DataHandle>
473 void communicateSizes(DataHandle& handle,
474 std::vector<InterfaceTracker>& recv_trackers);
482 template<
bool forward,
class DataHandle>
483 void communicate(DataHandle& handle);
493 template<
bool FORWARD,
class DataHandle>
494 void setupInterfaceTrackers(DataHandle& handle,
495 std::vector<InterfaceTracker>& send_trackers,
496 std::vector<InterfaceTracker>& recv_trackers);
504 template<
bool FORWARD,
class DataHandle>
505 void communicateFixedSize(DataHandle& handle);
513 template<
bool FORWARD,
class DataHandle>
514 void communicateVariableSize(DataHandle& handle);
521 std::size_t maxBufferSize_;
535 MPI_Comm communicator_;
544template<
class DataHandle>
548 typedef std::size_t DataType;
550 SizeDataHandle(DataHandle& data,
551 std::vector<InterfaceTracker>& trackers)
552 : data_(data), trackers_(trackers), index_()
558 std::size_t size(std::size_t i)
564 void gather(B& buf,
int i)
566 buf.write(data_.size(i));
568 void setReceivingIndex(std::size_t i)
572 std::size_t* getSizesPointer()
574 return trackers_[index_].getSizesPointer();
579 std::vector<InterfaceTracker>& trackers_;
584void setReceivingIndex(T&,
int)
588void setReceivingIndex(SizeDataHandle<T>& t,
int i)
590 t.setReceivingIndex(i);
599template<
bool FORWARD>
600struct InterfaceInformationChooser
605 static const InterfaceInformation&
606 getSend(
const std::pair<InterfaceInformation,InterfaceInformation>& info)
614 static const InterfaceInformation&
615 getReceive(
const std::pair<InterfaceInformation,InterfaceInformation>& info)
622struct InterfaceInformationChooser<false>
624 static const InterfaceInformation&
625 getSend(
const std::pair<InterfaceInformation,InterfaceInformation>& info)
630 static const InterfaceInformation&
631 getReceive(
const std::pair<InterfaceInformation,InterfaceInformation>& info)
642template<
class DataHandle>
646 int operator()(DataHandle& handle, InterfaceTracker& tracker,
647 MessageBuffer<typename DataHandle::DataType>& buffer,
651 return operator()(handle,tracker,buffer);
661 int operator()(DataHandle& handle, InterfaceTracker& tracker,
662 MessageBuffer<typename DataHandle::DataType>& buffer)
const
664 if(tracker.fixedSize)
667 std::size_t noIndices=
std::min(buffer.size()/tracker.fixedSize, tracker.indicesLeft());
668 for(std::size_t i=0; i< noIndices; ++i)
670 handle.gather(buffer, tracker.index());
671 tracker.moveToNextIndex();
673 return noIndices*tracker.fixedSize;
678 tracker.skipZeroIndices();
679 while(!tracker.finished())
680 if(buffer.hasSpaceForItems(handle.size(tracker.index())))
682 handle.gather(buffer, tracker.index());
683 packed+=handle.size(tracker.index());
684 tracker.moveToNextIndex();
698template<
class DataHandle>
708 bool operator()(DataHandle& handle, InterfaceTracker& tracker,
709 MessageBuffer<typename DataHandle::DataType>& buffer,
712 if(tracker.fixedSize)
714 std::size_t noIndices=
std::min(buffer.size()/tracker.fixedSize, tracker.indicesLeft());
716 for(std::size_t i=0; i< noIndices; ++i)
718 handle.scatter(buffer, tracker.index(), tracker.fixedSize);
719 tracker.moveToNextIndex();
721 return tracker.finished();
726 for(
int unpacked=0;unpacked<count;)
728 assert(!tracker.finished());
729 assert(buffer.hasSpaceForItems(tracker.size()));
730 handle.scatter(buffer, tracker.index(), tracker.size());
731 unpacked+=tracker.size();
732 tracker.moveToNextIndex();
734 return tracker.finished();
743template<
class DataHandle>
744struct UnpackSizeEntries{
753 bool operator()(SizeDataHandle<DataHandle>& handle, InterfaceTracker& tracker,
754 MessageBuffer<
typename SizeDataHandle<DataHandle>::DataType>& buffer)
const
756 std::size_t noIndices=
std::min(buffer.size(), tracker.indicesLeft());
757 std::copy(
static_cast<std::size_t*
>(buffer),
static_cast<std::size_t*
>(buffer)+noIndices,
758 handle.getSizesPointer()+tracker.offset());
759 tracker.increment(noIndices);
762 bool operator()(SizeDataHandle<DataHandle>& handle, InterfaceTracker& tracker,
763 MessageBuffer<
typename SizeDataHandle<DataHandle>::DataType>& buffer,
int)
const
765 return operator()(handle,tracker,buffer);
776void sendFixedSize(std::vector<InterfaceTracker>& send_trackers,
777 std::vector<MPI_Request>& send_requests,
778 std::vector<InterfaceTracker>& recv_trackers,
779 std::vector<MPI_Request>& recv_requests,
780 MPI_Comm communicator)
782 typedef std::vector<InterfaceTracker>::iterator TIter;
783 std::vector<MPI_Request>::iterator mIter=recv_requests.begin();
785 for(TIter iter=recv_trackers.begin(), end=recv_trackers.end(); iter!=end;
788 MPI_Irecv(&(iter->fixedSize), 1, MPITraits<std::size_t>::getType(),
789 iter->rank(), 933881, communicator, &(*mIter));
793 std::vector<MPI_Request>::iterator mIter1=send_requests.begin();
794 for(TIter iter=send_trackers.begin(), end=send_trackers.end();
798 MPI_Issend(&(iter->fixedSize), 1, MPITraits<std::size_t>::getType(),
799 iter->rank(), 933881, communicator, &(*mIter1));
808template<
class DataHandle>
809struct SetupSendRequest{
810 void operator()(DataHandle& handle,
811 InterfaceTracker& tracker,
812 MessageBuffer<typename DataHandle::DataType>& buffer,
813 MPI_Request& request,
817 int size=PackEntries<DataHandle>()(handle, tracker, buffer);
819 while(!tracker.finished() && !handle.size(tracker.index()))
820 tracker.moveToNextIndex();
822 MPI_Issend(buffer, size, MPITraits<typename DataHandle::DataType>::getType(),
823 tracker.rank(), 933399, comm, &request);
832template<
class DataHandle>
833struct SetupRecvRequest{
834 void operator()(DataHandle& ,
835 InterfaceTracker& tracker,
836 MessageBuffer<typename DataHandle::DataType>& buffer,
837 MPI_Request& request,
841 if(tracker.indicesLeft())
842 MPI_Irecv(buffer, buffer.size(), MPITraits<typename DataHandle::DataType>::getType(),
843 tracker.rank(), 933399, comm, &request);
850template<
class DataHandle>
851struct NullPackUnpackFunctor
853 int operator()(DataHandle&, InterfaceTracker&,
854 MessageBuffer<typename DataHandle::DataType>&,
int)
858 int operator()(DataHandle&, InterfaceTracker&,
859 MessageBuffer<typename DataHandle::DataType>&)
879template<
class DataHandle,
class BufferFunctor,
class CommunicationFunctor>
880std::size_t checkAndContinue(DataHandle& handle,
881 std::vector<InterfaceTracker>& trackers,
882 std::vector<MPI_Request>& requests,
883 std::vector<MPI_Request>& requests2,
884 std::vector<MessageBuffer<typename DataHandle::DataType> >& buffers,
886 BufferFunctor buffer_func,
887 CommunicationFunctor comm_func,
891 std::size_t size=requests.size();
892 std::vector<MPI_Status> statuses(size);
894 std::vector<int> indices(size, -1);
896 MPI_Testsome(size, &(requests[0]), &no_completed, &(indices[0]), &(statuses[0]));
897 indices.resize(no_completed);
898 for(std::vector<int>::iterator index=indices.begin(), end=indices.end();
901 InterfaceTracker& tracker=trackers[*index];
902 setReceivingIndex(handle, *index);
907 MPI_Get_count(&(statuses[index-indices.begin()]),
908 MPITraits<typename DataHandle::DataType>::getType(),
911 buffer_func(handle, tracker, buffers[*index], count);
913 buffer_func(handle, tracker, buffers[*index]);
914 tracker.skipZeroIndices();
915 if(!tracker.finished()){
917 comm_func(handle, tracker, buffers[*index], requests2[*index], comm);
918 tracker.skipZeroIndices();
936template<
class DataHandle>
937std::size_t receiveSizeAndSetupReceive(DataHandle& handle,
938 std::vector<InterfaceTracker>& trackers,
939 std::vector<MPI_Request>& size_requests,
940 std::vector<MPI_Request>& data_requests,
941 std::vector<MessageBuffer<typename DataHandle::DataType> >& buffers,
944 return checkAndContinue(handle, trackers, size_requests, data_requests, buffers, comm,
945 NullPackUnpackFunctor<DataHandle>(), SetupRecvRequest<DataHandle>(),
false);
956template<
class DataHandle>
957std::size_t checkSendAndContinueSending(DataHandle& handle,
958 std::vector<InterfaceTracker>& trackers,
959 std::vector<MPI_Request>& requests,
960 std::vector<MessageBuffer<typename DataHandle::DataType> >& buffers,
963 return checkAndContinue(handle, trackers, requests, requests, buffers, comm,
964 NullPackUnpackFunctor<DataHandle>(), SetupSendRequest<DataHandle>());
975template<
class DataHandle>
976std::size_t checkReceiveAndContinueReceiving(DataHandle& handle,
977 std::vector<InterfaceTracker>& trackers,
978 std::vector<MPI_Request>& requests,
979 std::vector<MessageBuffer<typename DataHandle::DataType> >& buffers,
982 return checkAndContinue(handle, trackers, requests, requests, buffers, comm,
983 UnpackEntries<DataHandle>(), SetupRecvRequest<DataHandle>(),
984 true, !handle.fixedsize());
988bool validRecvRequests(
const std::vector<MPI_Request> reqs)
990 for(std::vector<MPI_Request>::const_iterator i=reqs.begin(), end=reqs.end();
992 if(*i!=MPI_REQUEST_NULL)
1007template<
class DataHandle,
class Functor>
1008std::size_t setupRequests(DataHandle& handle,
1009 std::vector<InterfaceTracker>& trackers,
1010 std::vector<MessageBuffer<typename DataHandle::DataType> >& buffers,
1011 std::vector<MPI_Request>& requests,
1012 const Functor& setupFunctor,
1013 MPI_Comm communicator)
1015 typedef typename std::vector<InterfaceTracker>::iterator TIter;
1016 typename std::vector<MessageBuffer<typename DataHandle::DataType> >::iterator
1017 biter=buffers.begin();
1018 typename std::vector<MPI_Request>::iterator riter=requests.begin();
1019 std::size_t complete=0;
1020 for(TIter titer=trackers.begin(), end=trackers.end(); titer!=end; ++titer, ++biter, ++riter)
1022 setupFunctor(handle, *titer, *biter, *riter, communicator);
1023 complete+=titer->finished();
1029template<
class Allocator>
1030template<
bool FORWARD,
class DataHandle>
1031void VariableSizeCommunicator<Allocator>::setupInterfaceTrackers(DataHandle& handle,
1032 std::vector<InterfaceTracker>& send_trackers,
1033 std::vector<InterfaceTracker>& recv_trackers)
1035 if(interface_->
size()==0)
1037 send_trackers.reserve(interface_->
size());
1038 recv_trackers.reserve(interface_->
size());
1041 if(handle.fixedsize())
1045 typedef typename InterfaceMap::const_iterator IIter;
1046 for(IIter inf=interface_->begin(), end=interface_->end(); inf!=end; ++inf)
1049 if(handle.fixedsize() && InterfaceInformationChooser<FORWARD>::getSend(inf->second).size())
1050 fixedsize=handle.size(InterfaceInformationChooser<FORWARD>::getSend(inf->second)[0]);
1051 assert(!handle.fixedsize()||fixedsize>0);
1052 send_trackers.push_back(InterfaceTracker(inf->first,
1053 InterfaceInformationChooser<FORWARD>::getSend(inf->second), fixedsize));
1054 recv_trackers.push_back(InterfaceTracker(inf->first,
1055 InterfaceInformationChooser<FORWARD>::getReceive(inf->second), fixedsize, fixedsize==0));
1059template<
class Allocator>
1060template<
bool FORWARD,
class DataHandle>
1061void VariableSizeCommunicator<Allocator>::communicateFixedSize(DataHandle& handle)
1063 std::vector<MPI_Request> size_send_req(interface_->
size());
1064 std::vector<MPI_Request> size_recv_req(interface_->
size());
1066 std::vector<InterfaceTracker> send_trackers;
1067 std::vector<InterfaceTracker> recv_trackers;
1068 setupInterfaceTrackers<FORWARD>(handle,send_trackers, recv_trackers);
1069 sendFixedSize(send_trackers, size_send_req, recv_trackers, size_recv_req, communicator_);
1071 std::vector<MPI_Request> data_send_req(interface_->
size(), MPI_REQUEST_NULL);
1072 std::vector<MPI_Request> data_recv_req(interface_->
size(), MPI_REQUEST_NULL);
1073 typedef typename DataHandle::DataType DataType;
1074 std::vector<MessageBuffer<DataType> > send_buffers(interface_->
size(), MessageBuffer<DataType>(maxBufferSize_)),
1075 recv_buffers(interface_->
size(), MessageBuffer<DataType>(maxBufferSize_));
1078 setupRequests(handle, send_trackers, send_buffers, data_send_req,
1079 SetupSendRequest<DataHandle>(), communicator_);
1081 std::size_t no_size_to_recv, no_to_send, no_to_recv, old_size;
1082 no_size_to_recv = no_to_send = no_to_recv = old_size = interface_->
size();
1085 typedef typename std::vector<InterfaceTracker>::const_iterator Iter;
1086 for(Iter i=recv_trackers.begin(), end=recv_trackers.end(); i!=end; ++i)
1089 for(Iter i=send_trackers.begin(), end=send_trackers.end(); i!=end; ++i)
1093 while(no_size_to_recv+no_to_send+no_to_recv)
1097 no_size_to_recv -= receiveSizeAndSetupReceive(handle,recv_trackers, size_recv_req,
1098 data_recv_req, recv_buffers,
1103 no_to_send -= checkSendAndContinueSending(handle, send_trackers, data_send_req,
1104 send_buffers, communicator_);
1105 if(validRecvRequests(data_recv_req))
1107 no_to_recv -= checkReceiveAndContinueReceiving(handle, recv_trackers, data_recv_req,
1108 recv_buffers, communicator_);
1113 MPI_Waitall(size_send_req.size(), &(size_send_req[0]), MPI_STATUSES_IGNORE);
1117template<
class Allocator>
1118template<
bool FORWARD,
class DataHandle>
1119void VariableSizeCommunicator<Allocator>::communicateSizes(DataHandle& handle,
1120 std::vector<InterfaceTracker>& data_recv_trackers)
1122 std::vector<InterfaceTracker> send_trackers;
1123 std::vector<InterfaceTracker> recv_trackers;
1124 std::size_t size = interface_->
size();
1125 std::vector<MPI_Request> send_requests(size, MPI_REQUEST_NULL);
1126 std::vector<MPI_Request> recv_requests(size, MPI_REQUEST_NULL);
1127 std::vector<MessageBuffer<std::size_t> >
1128 send_buffers(size, MessageBuffer<std::size_t>(maxBufferSize_)),
1129 recv_buffers(size, MessageBuffer<std::size_t>(maxBufferSize_));
1130 SizeDataHandle<DataHandle> size_handle(handle,data_recv_trackers);
1131 setupInterfaceTrackers<FORWARD>(size_handle,send_trackers, recv_trackers);
1132 setupRequests(size_handle, send_trackers, send_buffers, send_requests,
1133 SetupSendRequest<SizeDataHandle<DataHandle> >(), communicator_);
1134 setupRequests(size_handle, recv_trackers, recv_buffers, recv_requests,
1135 SetupRecvRequest<SizeDataHandle<DataHandle> >(), communicator_);
1138 auto valid_req_func =
1139 [](
const MPI_Request& req) {
return req != MPI_REQUEST_NULL; };
1141 auto size_to_send = std::count_if(send_requests.begin(), send_requests.end(),
1143 auto size_to_recv = std::count_if(recv_requests.begin(), recv_requests.end(),
1146 while(size_to_send+size_to_recv)
1150 checkSendAndContinueSending(size_handle, send_trackers, send_requests,
1151 send_buffers, communicator_);
1157 checkAndContinue(size_handle, recv_trackers, recv_requests, recv_requests,
1158 recv_buffers, communicator_, UnpackSizeEntries<DataHandle>(),
1159 SetupRecvRequest<SizeDataHandle<DataHandle> >());
1163template<
class Allocator>
1164template<
bool FORWARD,
class DataHandle>
1165void VariableSizeCommunicator<Allocator>::communicateVariableSize(DataHandle& handle)
1168 std::vector<InterfaceTracker> send_trackers;
1169 std::vector<InterfaceTracker> recv_trackers;
1170 setupInterfaceTrackers<FORWARD>(handle, send_trackers, recv_trackers);
1172 std::vector<MPI_Request> send_requests(interface_->
size(), MPI_REQUEST_NULL);
1173 std::vector<MPI_Request> recv_requests(interface_->
size(), MPI_REQUEST_NULL);
1174 typedef typename DataHandle::DataType DataType;
1175 std::vector<MessageBuffer<DataType> >
1176 send_buffers(interface_->
size(), MessageBuffer<DataType>(maxBufferSize_)),
1177 recv_buffers(interface_->
size(), MessageBuffer<DataType>(maxBufferSize_));
1179 communicateSizes<FORWARD>(handle, recv_trackers);
1181 setupRequests(handle, send_trackers, send_buffers, send_requests,
1182 SetupSendRequest<DataHandle>(), communicator_);
1183 setupRequests(handle, recv_trackers, recv_buffers, recv_requests,
1184 SetupRecvRequest<DataHandle>(), communicator_);
1187 auto valid_req_func =
1188 [](
const MPI_Request& req) {
return req != MPI_REQUEST_NULL;};
1190 auto no_to_send = std::count_if(send_requests.begin(), send_requests.end(),
1192 auto no_to_recv = std::count_if(recv_requests.begin(), recv_requests.end(),
1194 while(no_to_send+no_to_recv)
1198 no_to_send -= checkSendAndContinueSending(handle, send_trackers, send_requests,
1199 send_buffers, communicator_);
1202 no_to_recv -= checkReceiveAndContinueReceiving(handle, recv_trackers, recv_requests,
1203 recv_buffers, communicator_);
1207template<
class Allocator>
1208template<
bool FORWARD,
class DataHandle>
1209void VariableSizeCommunicator<Allocator>::communicate(DataHandle& handle)
1211 if( interface_->
size() == 0)
1216 if(handle.fixedsize())
1217 communicateFixedSize<FORWARD>(handle);
1219 communicateVariableSize<FORWARD>(handle);
Communication interface between remote and local indices.
Definition: interface.hh:207
A buffered communicator where the amount of data sent does not have to be known a priori.
Definition: variablesizecommunicator.hh:312
VariableSizeCommunicator(const Interface &inf, std::size_t max_buffer_size)
Creates a communicator with a specific maximum buffer size.
Definition: variablesizecommunicator.hh:384
void backward(DataHandle &handle)
Communicate backwards.
Definition: variablesizecommunicator.hh:466
VariableSizeCommunicator(MPI_Comm comm, const InterfaceMap &inf, std::size_t max_buffer_size)
Creates a communicator with a specific maximum buffer size.
Definition: variablesizecommunicator.hh:373
VariableSizeCommunicator(const VariableSizeCommunicator &other)
Copy-constructs a communicator.
Definition: variablesizecommunicator.hh:399
void forward(DataHandle &handle)
Communicate forward.
Definition: variablesizecommunicator.hh:441
VariableSizeCommunicator & operator=(const VariableSizeCommunicator &other)
Copy-assignes a communicator.
Definition: variablesizecommunicator.hh:409
std::map< int, std::pair< InterfaceInformation, InterfaceInformation >, std::less< int >, typename std::allocator_traits< Allocator >::template rebind_alloc< std::pair< const int, std::pair< InterfaceInformation, InterfaceInformation > > > > InterfaceMap
The type of the map from process number to InterfaceInformation for sending and receiving to and from...
Definition: variablesizecommunicator.hh:320
VariableSizeCommunicator(MPI_Comm comm, const InterfaceMap &inf)
Creates a communicator with the default maximum buffer size.
Definition: variablesizecommunicator.hh:329
VariableSizeCommunicator(const Interface &inf)
Creates a communicator with the default maximum buffer size.
Definition: variablesizecommunicator.hh:338
Provides classes for building the communication interface between remote indices.
MPI_Comm communicator() const
Get the MPI Communicator.
Definition: interface.hh:415
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentionally unused function parameters with.
Definition: unused.hh:25
auto min(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::min()
Definition: defaults.hh:87
Traits classes for mapping types onto MPI_Datatype.
Dune namespace.
Definition: alignedallocator.hh:14
Definition of the DUNE_UNUSED macro for the case that config.h is not available.
std::size_t fixedSize
The number of data items per index if it is fixed, 0 otherwise.
Definition: variablesizecommunicator.hh:245