Code indexing in gitaly is broken and leads to code not being visible to the user. We work on the issue with highest priority.

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • OPAL/src
  • zheng_d/src
  • ext-rogers_c/src
  • ext-wang_c/src
  • cortes_c/src
  • ext-calvo_p/src
  • ext-edelen_a/src
  • albajacas_a/src
  • kraus/src
  • snuverink_j/OPAL-src
  • adelmann/src
  • muralikrishnan/src
  • wyssling_t/src
  • gsell/src
  • ext-piot_p/src
  • OPAL/opal-src-4-opalx-debug
  • winkle_m/src
17 results
Show changes
Showing
with 284 additions and 267 deletions
......@@ -209,12 +209,13 @@ recurseCoordinateVRB(int dim,
{
int d;
#ifndef NOPAssert
// Calculate the total number of vnodes.
int totalVnodes = sizes[0];
for (d=1; d<dim; ++d)
totalVnodes *= sizes[d];
PAssert_GE(totalVnodes, nprocs);
#endif
// Find the number of processors on each side.
int leftProcs = nprocs/2;
int rightProcs = nprocs-leftProcs;
......@@ -375,4 +376,4 @@ main(int argc, char *argv[])
* $RCSfile: VRB.cpp,v $ $Author: adelmann $
* $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:27 $
* IPPL_VERSION_ID: $Id: VRB.cpp,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $
***************************************************************************/
\ No newline at end of file
***************************************************************************/
......@@ -24,12 +24,3 @@ ADD_IPPL_SOURCES (${_SRCS})
ADD_IPPL_HEADERS (${_HDRS})
install (FILES ${_HDRS} DESTINATION include/Index)
# vi: set et ts=4 sw=4 sts=4:
# Local Variables:
# mode: cmake
# cmake-tab-width: 4
# indent-tabs-mode: nil
# require-final-newline: nil
# End:
......@@ -27,9 +27,9 @@
#include "Index/SIndexAssign.h"
#include "Index/SIndex.h"
#include "Field/BrickIterator.h"
#include "Field/Field.h"
#include "Field/IndexedField.h"
#include "Field/Assign.h"
// #include "Field/Field.h"
// #include "Field/IndexedField.h"
// #include "Field/Assign.h"
#include "Utility/IpplInfo.h"
......
......@@ -23,12 +23,3 @@ ADD_IPPL_SOURCES (${_SRCS})
ADD_IPPL_HEADERS (${_HDRS})
install (FILES ${_HDRS} DESTINATION include/Meshes)
# vi: set et ts=4 sw=4 sts=4:
# Local Variables:
# mode: cmake
# cmake-tab-width: 4
# indent-tabs-mode: nil
# require-final-newline: nil
# End:
......@@ -14,7 +14,6 @@
#include "Field/BareField.h"
#include "Field/BrickExpression.h"
#include "Field/LField.h"
#include "Field/Field.h"
#include "Field/Assign.h"
#include "Field/AssignDefs.h"
......
set (_SRCS
CRC.cpp
Communicate.cpp
CommCreator.cpp
CommMPI.cpp
Communicate.cpp
Format.cpp
MessageFunctions.cpp
Formatter.cpp
MsgBuffer.cpp
)
set (_HDRS
CRC.h
CommCreator.h
CommMPI.h
Communicate.h
CRC.h
DataTypes.h
Formatter.h
GlobalComm.hpp
Format.h
GlobalComm.h
Message.hpp
GlobalComm.hpp
Message.h
Message.hpp
MsgBuffer.h
Operations.h
TagMaker.h
Tags.h
......@@ -30,13 +32,4 @@ include_directories (
add_ippl_sources (${_SRCS})
add_ippl_headers (${_HDRS})
install (FILES ${_HDRS} DESTINATION include/Message)
# vi: set et ts=4 sw=4 sts=4:
# Local Variables:
# mode: cmake
# cmake-tab-width: 4
# indent-tabs-mode: nil
# require-final-newline: nil
# End:
install (FILES ${_HDRS} DESTINATION include/Message)
\ No newline at end of file
// -*- C++ -*-
/***************************************************************************
*
* The IPPL Framework
*
* This program was prepared by PSI.
* All rights in the program are reserved by PSI.
* Neither PSI nor the author(s)
* makes any warranty, express or implied, or assumes any liability or
* responsibility for the use of this software
*
* Visit www.amas.web.psi for more details
*
***************************************************************************/
// -*- C++ -*-
/***************************************************************************
*
* The IPPL Framework
*
*
* Visit http://people.web.psi.ch/adelmann/ for more details
*
***************************************************************************/
// include files
//
// CommMPI - MPI-specific communications object for use with the
// Ippl framework.
// Allows user to establish id's for available nodes, establish connections,
// and send/receive data.
//
// Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
//
// All rights reserved
//
// This file is part of OPAL.
//
// OPAL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
//
#include "Message/CommMPI.h"
#include "Message/Message.h"
#include "Utility/IpplInfo.h"
......@@ -103,7 +97,7 @@ CommMPI::CommMPI(int& argc , char**& argv, int procs, bool mpiinit, MPI_Comm mpi
MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided);
INFOMSG("Ippl will be initialized with " <<
omp_get_max_threads() << " OMP threads\n");
if ( provided != MPI_THREAD_FUNNELED )
ERRORMSG("CommMPI: Didn't get requested MPI-OpenMP setting.\n");
#else
......@@ -149,7 +143,7 @@ CommMPI::CommMPI(int& argc , char**& argv, int procs, bool mpiinit, MPI_Comm mpi
std::vector<int> child_ready(TotalNodes);
for (i = 0; i < TotalNodes; child_ready[i++] = 0)
;
INFOMSG("CommMPI: Parent process waiting for children ..." << endl);
INFOMSG(level5 << "CommMPI: Parent process waiting for children ..." << endl);
reported = 1; // since the parent is already ready
while (reported < TotalNodes)
{
......@@ -160,7 +154,7 @@ CommMPI::CommMPI(int& argc , char**& argv, int procs, bool mpiinit, MPI_Comm mpi
{
child_ready[rep_host] = 1;
reported++;
INFOMSG("CommMPI: Child " << rep_host << " ready." << endl);
INFOMSG(level5 << "CommMPI: Child " << rep_host << " ready." << endl);
}
else
{
......@@ -171,7 +165,7 @@ CommMPI::CommMPI(int& argc , char**& argv, int procs, bool mpiinit, MPI_Comm mpi
}
//~ delete [] child_ready;
INFOMSG("CommMPI: Initialization complete." << endl);
INFOMSG(level5 << "CommMPI: Initialization complete." << endl);
}
else // this is a child process; get data from pops
......@@ -180,7 +174,7 @@ CommMPI::CommMPI(int& argc , char**& argv, int procs, bool mpiinit, MPI_Comm mpi
ierror = MPI_Get_processor_name(host_name, &result_len);
if (ierror >= 0)
{
INFOMSG("CommMPI: Started job " << myHost << " on host `");
INFOMSG(level5 << "CommMPI: Started job " << myHost << " on host `");
INFOMSG(host_name << "'." << endl);
}
else
......@@ -623,4 +617,4 @@ int CommMPI::raw_probe_receive(char *&data, int &node, int &tag)
MPI_Recv(data, count, MPI_BYTE, node, tag, communicator, &stat);
return count;
}
}
\ No newline at end of file
// -*- C++ -*-
/***************************************************************************
*
* The IPPL Framework
*
*
* Visit http://people.web.psi.ch/adelmann/ for more details
*
***************************************************************************/
//
// CommMPI - MPI-specific communications object for use with the
// Ippl framework.
// Allows user to establish id's for available nodes, establish connections,
// and send/receive data.
//
// Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
//
// All rights reserved
//
// This file is part of OPAL.
//
// OPAL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
//
#ifndef COMM_MPI_H
#define COMM_MPI_H
/***************************************************************************
* CommMPI.h - MPI-specific communications object for use with the
* Ippl framework.
* Allows user to establish id's for available nodes, establish connections,
* and send/receive data.
***************************************************************************/
// include files
#include "Message/Communicate.h"
#include <mpi.h>
......@@ -31,7 +33,7 @@ public:
// constructor arguments: command-line args, and number of processes
// to start (if < 0, start the 'default' number, i.e. the number of
// hosts in a MPI virtual machine, the number of nodes in an O2K, etc)
CommMPI(int& argc, char**& argv, int procs = (-1), bool mpiinit = true,
CommMPI(int& argc, char**& argv, int procs = (-1), bool mpiinit = true,
MPI_Comm mpicomm = MPI_COMM_WORLD);
virtual ~CommMPI(void);
......@@ -101,4 +103,4 @@ private:
};
#endif // COMM_MPI_H
#endif // COMM_MPI_H
\ No newline at end of file
......@@ -38,7 +38,6 @@
#include "Utility/IpplInfo.h"
#include "Utility/IpplStats.h"
#include "Utility/RandomNumberGen.h"
#include "Utility/PAssert.h"
#include <cstdio>
......@@ -62,7 +61,7 @@ std::ostream& operator<<(std::ostream& o, const Communicate& c)
// Constructor.
// arguments: command-line args, and number of processes
// to start (if < 0, start the 'default' number, i.e. the number of
// hosts
// hosts
// Note: The base-class constructor does not need the argument info or
// the number of nodes, it just by default sets the number of nodes=1
// Also note: the derived classes should erase Contexts and Processes, and
......@@ -84,7 +83,7 @@ Communicate::Communicate(int, char **, int)
// Destructor. Nothing to do at present.
Communicate::~Communicate(void)
{
// delete the cached messages
SentCache_t::iterator cachei = sentMsgCache.begin();
......@@ -158,7 +157,7 @@ Message* Communicate::myreceive(int&, int&, int)
// Default version of virtual barrier function ... here, does nothing.
void Communicate::mybarrier(void)
{
// just return NULL, since we cannot find a message with this function
return;
......@@ -240,7 +239,7 @@ bool Communicate::send(Message *msg, int node, int tag, bool delmsg)
// 2. In receive queue
Message* Communicate::receive(int& node, int& tag)
{
//Inform dbgmsg("Comm::receive", INFORM_ALL_NODES);
//dbgmsg << "Doing receive from node " << node << ", tag " << tag << endl;
......@@ -300,10 +299,10 @@ Message* Communicate::receive(int& node, int& tag)
// A blocking version of receive.
Message *Communicate::receive_block(int& node, int &tag)
{
// process list of resend requests
process_resend_requests();
......@@ -314,13 +313,13 @@ Message *Communicate::receive_block(int& node, int &tag)
// If we haven't already found a message, check the local messages
//dbgmsg << "Checking for queued message ..." << endl;
Message *msg = find_msg(node, tag);
//dbgmsg << "Found one? " << (msg != 0 ? "yes" : "no") << endl;
// keep checking for remote msgs until we get one
if (myNode() != node)
{
while (msg == 0)
......@@ -363,7 +362,7 @@ Message *Communicate::receive_block(int& node, int &tag)
}
}
}
// If we're on just one node, and we did not find a message, this is
// a big problem.
......@@ -439,7 +438,7 @@ int Communicate::broadcast_others(Message *msg, int tag, bool delmsg)
// else to get here before returning to calling function).
void Communicate::barrier()
{
mybarrier();
//INCIPPLSTAT(incBarriers);
......@@ -865,7 +864,7 @@ void Communicate::remove_single_ok_message(MsgNum_t mnum)
// process list of resend requests
void Communicate::process_resend_requests()
{
if (resendList.size() > 0)
if (!resendList.empty())
{
Inform dbgmsg("***Communicate::process_resend_reqs", INFORM_ALL_NODES);
dbgmsg << "Clearing " << sentOKList.size() << " and resending ";
......@@ -873,7 +872,7 @@ void Communicate::process_resend_requests()
}
// clear out OK messages
while (sentOKList.size() > 0)
while (!sentOKList.empty())
{
MsgNum_t mnum = *(sentOKList.begin());
sentOKList.erase(sentOKList.begin());
......@@ -881,7 +880,7 @@ void Communicate::process_resend_requests()
}
// resend a message, if necessary
while (resendList.size() > 0)
while (!resendList.empty())
{
MsgNum_t mnum = *(resendList.begin());
resendList.erase(resendList.begin());
......@@ -889,7 +888,7 @@ void Communicate::process_resend_requests()
}
// inform other nodes that we've received their messages ok
while (informOKList.size() > 0)
while (!informOKList.empty())
{
int node = (*(informOKList.begin())).first;
MsgNum_t mnum = (*(informOKList.begin())).second;
......@@ -898,11 +897,11 @@ void Communicate::process_resend_requests()
}
// request resends from other nodes
while (requestList.size() > 0)
while (!requestList.empty())
{
int node = (*(requestList.begin())).first;
MsgNum_t mnum = (*(requestList.begin())).second;
requestList.erase(requestList.begin());
request_retransmission(node, mnum);
}
}
}
\ No newline at end of file
//
// Class Format
// Format class to allow serializing message objects into plain buffers
// to send directly with mpi calls or similar means
//
// Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
// All rights reserved
//
// This file is part of OPAL.
//
// OPAL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
//
#include "Message/Format.h"
Format::Format(Message *msg)
{
items = msg->size();
size = 0;
format_array.resize(2*items);
for (unsigned int i=0; i<items; ++i)
{
Message::MsgItem &msgitem = msg->item(i);
format_array[2*i+0] = msgitem.numElems();
format_array[2*i+1] = msgitem.numBytes();
size += format_array[2*i+1];
}
}
void Format::print()
{
std::cout << "size: " << size << std::endl;
for (unsigned int i=0; i<items; ++i)
{
std::cout << "entry " << i << ": " << format_array[2*i+0]
<< " elements " << format_array[2*i+1] << " bytes\n";
}
}
\ No newline at end of file
//
// Class Format
// Format class to allow serializing message objects into plain buffers
// to send directly with mpi calls or similar means
//
// Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
// All rights reserved
//
// This file is part of OPAL.
//
// OPAL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
//
#ifndef FORMATTER_H
#define FORMATTER_H
#include <algorithm>
#include <cstring>
#include <vector>
#include "Message/Message.h"
class Format {
public:
Format(Message*);
unsigned int getItemCount() {
return items;
}
unsigned int getSize() {
return size;
}
unsigned int getFormatSize() {
return 2 * items * sizeof(int);
}
unsigned int getItemElems(int i) {
return format_array[2 * i + 0];
}
unsigned int getItemBytes(int i) {
return format_array[2 * i + 1];
}
void print();
private:
unsigned int items, size;
std::vector<unsigned int> format_array;
};
#endif
\ No newline at end of file
// -*- C++ -*-
/***************************************************************************
*
* The IPPL Framework
*
*
* Visit http://people.web.psi.ch/adelmann/ for more details
*
***************************************************************************/
#ifndef FORMATTER_H
#define FORMATTER_H
#include "Message/Message.h"
#include <cstring>
#include <vector>
#include <algorithm>
/*
* Format and MsgBuffer class to allow serializing message objects into plain buffers
* to send directly with mpi calls or similar means
*/
class Format
{
public:
Format(Message*);
unsigned int getItemCount()
{
return items;
}
unsigned int getSize()
{
return size;
}
unsigned int getFormatSize()
{
return 2*items*sizeof(int);
}
unsigned int getItemElems(int i)
{
return format_array[2*i+0];
}
unsigned int getItemBytes(int i)
{
return format_array[2*i+1];
}
void print();
private:
unsigned int items, size;
std::vector<unsigned int> format_array;
};
class MsgBuffer
{
public:
//creates buffer with space to hold count messages of format f
MsgBuffer(Format *f, int count, int offset = 0);
MsgBuffer(Format *f, char* d, int size);
bool add(Message*);
Message* get();
template<class T>
void get(T &v)
{
std::memcpy(&v, data.data()+readpos, sizeof(T));
readpos += sizeof(T);
}
template<class T>
void put(T &v)
{
std::memcpy(data.data()+writepos, &v, sizeof(T));
writepos += sizeof(T);
}
int getSize()
{
return writepos;
}
void* getBuffer()
{
return data.data();
}
Format* getFormat() { return format; }
~MsgBuffer();
private:
Format *format;
unsigned int datasize, writepos, readpos;
std::vector<char> data;
};
#endif // FORMATTER_H
......@@ -31,7 +31,6 @@
* of resolving who needs to free up the storage used for the Message elements.
***************************************************************************/
#include "Utility/Inform.h"
#include <complex>
#include <cstddef>
#include <vector>
......
......@@ -12,7 +12,6 @@
***************************************************************************/
#include "Message/Message.h"
#include "Utility/Inform.h"
#include "Utility/IpplInfo.h"
#include <iterator>
......
#include "Message/Formatter.h"
Format::Format(Message *msg)
{
items = msg->size();
size = 0;
format_array.resize(2*items);
for (unsigned int i=0; i<items; ++i)
{
Message::MsgItem &msgitem = msg->item(i);
format_array[2*i+0] = msgitem.numElems();
format_array[2*i+1] = msgitem.numBytes();
size += format_array[2*i+1];
}
}
void Format::print()
{
std::cout << "size: " << size << std::endl;
for (unsigned int i=0; i<items; ++i)
{
std::cout << "entry " << i << ": " << format_array[2*i+0]
<< " elements " << format_array[2*i+1] << " bytes\n";
}
}
//
// Class MsgBuffer
// MsgBuffer class to allow serializing message objects into plain buffers
// to send directly with mpi calls or similar means
//
// Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
// All rights reserved
//
// This file is part of OPAL.
//
// OPAL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
//
#include "Message/MsgBuffer.h"
#include "Message/Format.h"
MsgBuffer::MsgBuffer(Format *f, int count, int offset)
: format(f), writepos(0), readpos(0)
......@@ -94,4 +89,4 @@ Message* MsgBuffer::get()
}
return msg;
}
}
\ No newline at end of file
//
// Class MsgBuffer
// MsgBuffer class to allow serializing message objects into plain buffers
// to send directly with mpi calls or similar means
//
// Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
// All rights reserved
//
// This file is part of OPAL.
//
// OPAL is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
//
#ifndef MSGBUFFER_H
#define MSGBUFFER_H
#include <algorithm>
#include <cstring>
#include <vector>
#include "Message/Message.h"
class Format;
class MsgBuffer {
public:
// creates buffer with space to hold count messages of format f
MsgBuffer(Format* f, int count, int offset = 0);
MsgBuffer(Format* f, char* d, int size);
bool add(Message*);
Message* get();
template <class T>
void get(T& v) {
std::memcpy(&v, data.data() + readpos, sizeof(T));
readpos += sizeof(T);
}
template <class T>
void put(T& v) {
std::memcpy(data.data() + writepos, &v, sizeof(T));
writepos += sizeof(T);
}
int getSize() {
return writepos;
}
void* getBuffer() {
char* data_ptr = data.empty() ? static_cast<char*>(0) : &(data[0]);
return data_ptr;
}
Format* getFormat() {
return format;
}
~MsgBuffer();
private:
Format* format;
unsigned int datasize, writepos, readpos;
std::vector<char> data;
};
#endif
\ No newline at end of file
......@@ -103,11 +103,3 @@ private:
};
#endif // TAG_MAKER_H
// vi: set et ts=4 sw=4 sts=4:
// Local Variables:
// mode:c
// c-basic-offset: 4
// indent-tabs-mode: nil
// require-final-newline: nil
// End:
......@@ -16,12 +16,3 @@ add_ippl_sources (${_SRCS})
add_ippl_headers (${_HDRS})
install (FILES ${_HDRS} DESTINATION include/PETE)
# vi: set et ts=4 sw=4 sts=4:
# Local Variables:
# mode: cmake
# cmake-tab-width: 4
# indent-tabs-mode: nil
# require-final-newline: nil
# End:
......@@ -22,7 +22,9 @@
#define ABSTRACT_PARTICLE_H
#include "Particle/ParticleLayout.h"
#include "Particle/ParticleAttrib.h"
template<class T> class ParticleAttrib;
class ParticleAttribBase;
template <class T, unsigned Dim>
class AbstractParticle {
......@@ -57,9 +59,6 @@ public:
virtual void setTotalNum(size_t n) = 0;
virtual void setLocalNum(size_t n) = 0;
virtual unsigned int getMinimumNumberOfParticlesPerCore() const = 0;
virtual void setMinimumNumberOfParticlesPerCore(unsigned int n) = 0;
virtual Layout_t& getLayout() = 0;
virtual const Layout_t& getLayout() const = 0;
......
......@@ -14,7 +14,8 @@
#include "Message/Message.h"
#include "Message/Communicate.h"
#include "Message/Formatter.h"
#include "Message/Format.h"
#include "Message/MsgBuffer.h"
template <class T, unsigned Dim, class Mesh, class CachingPolicy> class ParticleSpatialLayout;
......@@ -35,7 +36,7 @@ public:
{
std::fill(boxDimension, boxDimension+Dim, length);
}
template<class C>
template<class C>
void updateCacheInformation(
ParticleSpatialLayout<T, Dim, Mesh, C > &PLayout
)
......@@ -128,8 +129,9 @@ template<class C>
dom[d].last() - onoff[d]*offset[d]);
tmpoffset[d] = onoff[d]*offset[d];
}
regions[node].push_back(std::make_pair(dom,tmpoffset));
regions[node].push_back(std::make_pair(dom,tmpoffset));
}
//generate next combinations. this is basically a binary incrementer
......@@ -149,7 +151,7 @@ template<class C>
}
}
template<class C>
template<class C>
void updateGhostParticles(
IpplParticleBase< ParticleSpatialLayout<T,Dim,Mesh,C > > &PData,
ParticleSpatialLayout<T, Dim, Mesh, C > &/*PLayout*/
......@@ -233,7 +235,8 @@ template<class C>
}
//wait for communication to finish and clean up buffers
MPI_Waitall(requests.size(), &(requests[0]), MPI_STATUSES_IGNORE);
MPI_Request* requests_ptr = requests.empty()? static_cast<MPI_Request*>(0): &(requests[0]);
MPI_Waitall(requests.size(), requests_ptr, MPI_STATUSES_IGNORE);
for (unsigned int j = 0; j<buffers.size(); ++j)
{
delete buffers[j]->getFormat();
......@@ -259,4 +262,4 @@ private:
std::map<unsigned, std::list<std::pair<NDRegion<T,Dim>, Offset_t> > > regions;
};
#endif
\ No newline at end of file
#endif