MADNESS  0.10.1
worldmpi.h
Go to the documentation of this file.
1 /*
2  This file is part of MADNESS.
3 
4  Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20  For more information please contact:
21 
22  Robert J. Harrison
23  Oak Ridge National Laboratory
24  One Bethel Valley Road
25  P.O. Box 2008, MS-6367
26 
27  email: harrisonrj@ornl.gov
28  tel: 865-241-3937
29  fax: 865-572-0680
30 */
31 
32 #ifndef MADNESS_WORLD_WORLDMPI_H__INCLUDED
33 #define MADNESS_WORLD_WORLDMPI_H__INCLUDED
34 
35 /**
36  \file worldmpi.h
37  \brief Implements \c WorldMpiInterface.
38  \ingroup mpi
39 */
40 
41 /*
42 // If include mpi.h BEFORE stdio/iostream should not need undefs
43 #ifdef SEEK_CUR
44 #undef SEEK_CUR
45 #endif
46 #ifdef SEEK_SET
47 #undef SEEK_SET
48 #endif
49 #ifdef SEEK_END
50 #undef SEEK_END
51 #endif
52 */
53 
54 #include <type_traits>
55 #include <madness/world/safempi.h>
57 #include <cstdlib>
58 
59 /// \addtogroup mpi
60 /// @{
61 
62 #ifdef MADNESS_USE_BSEND_ACKS
63 /// \todo Verify: Size of the acknowledgment buffer.
64 #define MADNESS_ACK_BUFF_SIZE 1000
65 #endif // MADNESS_USE_BSEND_ACKS
66 
67 /// String description of the MPI thread level.
68 
69 /// \param[in] level The MPI thread level.
70 /// \return A string description of the thread level.
71 #define MPI_THREAD_STRING(level) \
72  ( level==MPI_THREAD_SERIALIZED ? "THREAD_SERIALIZED" : \
73  ( level==MPI_THREAD_MULTIPLE ? "THREAD_MULTIPLE" : \
74  ( level==MPI_THREAD_FUNNELED ? "THREAD_FUNNELED" : \
75  ( level==MPI_THREAD_SINGLE ? "THREAD_SINGLE" : "THREAD_UNKNOWN" ) ) ) )
76 
77 namespace madness {
78 
79  // Forward declarations
80  class World;
81  World& initialize(int&, char**&, const SafeMPI::Intracomm&, bool);
82  void finalize();
83 
84  /// \todo Brief description needed.
85  static const Tag DYNAMIC_TAG_BASE = 1024;
86 
87  namespace detail {
88 
89  class WorldMpiRuntime;
90 
91  /// MPI singleton that manages MPI setup and teardown for MADNESS.
92 
93  /// MADNESS will call \c WorldMpi::initialize and \c WorldMpi::finalize
94  /// to setup and teardown the MPI runtime.
95  class WorldMpi {
96  private:
97  // Friends of MpiWorld
98  friend class WorldMpiRuntime;
99 
100  /// Pointer to help MADNESS manage MPI.
101 
102  /// This shared pointer is used to manage the lifetime of the MPI
103  /// within MADNESS. It ensures that MPI is destroyed only after the
104  /// last world object is destroyed.
105  static std::shared_ptr<WorldMpi> world_mpi;
106  static bool own_mpi; ///< \todo Brief description needed.
107 
108 #ifdef MADNESS_USE_BSEND_ACKS
109  /// Acknowledgment buffer.
110  static char* mpi_ack_buffer[MADNESS_ACK_BUFF_SIZE];
111 #endif // MADNESS_USE_BSEND_ACKS
112 
113  /// \c WorldMpi constructor.
114 
115  /// Initialize the MPI runtime for MADNESS.
116  /// \note This constructor is private to prevent incorrect
117  /// initialization. The user should call \c initialize.
118  /// \param[in,out] argc The number of command-line arguments to process.
119  /// \param[in,out] argv The command-line arguments.
120  /// \param requested The requested thread support for MPI runtime
121  WorldMpi(int& argc, char**& argv, int requested) {
122  if(own_mpi) {
123  // Assume that MADNESS is managing MPI.
124  SafeMPI::Init_thread(argc, argv, requested);
125  } else {
126  // MPI has already been initialized, so it is the user's
127  // responsibility to manage MPI and MADNESS world objects.
129  }
130 
131 #ifdef MADNESS_USE_BSEND_ACKS
132  // Register the acknowlegement buffer for RMI
133  SafeMPI::Attach_buffer(mpi_ack_buffer, MADNESS_ACK_BUFF_SIZE);
134 #endif // MADNESS_USE_BSEND_ACKS
135  }
136 
137  // Not allowed
138  WorldMpi(const WorldMpi&) = delete;
139  WorldMpi& operator=(const WorldMpi&) = delete;
140 
141  public:
142 
143  /// \c WorldMpi destructor.
144 
145  /// This will teardown the MPI, SafeMPI.
147 #ifdef MADNESS_USE_BSEND_ACKS
148  // Unregister the acknowlegement buffer for RMI
149  void* buff = nullptr;
151 #endif // MADNESS_USE_BSEND_ACKS
152 
153  // Teardown MPI/SafeMPI
154  if(own_mpi) {
155  const int result = SafeMPI::Finalize();
156 
157  // Check that MPI exited cleanly.
158  if(result != MPI_SUCCESS) {
159  // Print the error message returned by MPI_Finalize().
160  char mpi_error_string[MPI_MAX_ERROR_STRING];
161  int len = 0;
162  if(MPI_Error_string(result, mpi_error_string, &len) != MPI_SUCCESS) {
163  std::strncpy(mpi_error_string, "UNKNOWN MPI ERROR!", MPI_MAX_ERROR_STRING);
164  }
165  std::cout << "!! MPI Error: " << mpi_error_string << "\n";
166  }
167  }
168  }
169 
170  /// Initialize the MPI runtime.
171 
172  /// This function starts the MPI runtime. If MPI is already running,
173  /// then MADNESS delegate responsibility for MPI to the user. In
174  /// either case, MPI thread support is checked to make sure MPI will
175  /// play nice with MADNESS.
176  ///
177  /// \throw madness::Exception When MADNESS has already been initialized.
178  /// \throw madness::Exception When MPI has already been finalized.
179  /// \throw SafeMPI::Exception When an MPI error occurs.
180  ///
181  /// \param[in,out] argc The number of command line arguments.
182  /// \param[in,out] argv The values of command line arguments.
183  /// \param[in] requested The requested thread support for MPI runtime.
184  static void initialize(int& argc, char**& argv, int requested) {
185  // Check that world_mpi has not been initialized yet and that
186  // MPI has not been finalized
189 
190  // Check for ownership of MPI (user or MADNESS runtime).
192 
193  // Initialize the MPI runtime
194  world_mpi.reset(new WorldMpi(argc, argv, requested));
195 
196  // Check that the thread support provided by MPI matches the
197  // requested and required thread support.
198  const int provided = SafeMPI::Query_thread();
199  const int rank = SafeMPI::COMM_WORLD.Get_rank();
200  if((provided < requested) && (rank == 0)) {
201  std::cout << "!! Error: MPI_Init_thread did not provide requested functionality: "
202  << MPI_THREAD_STRING(requested) << " (" << MPI_THREAD_STRING(provided) << "). \n"
203  << "!! Error: The MPI standard makes no guarantee about the correctness of a program in such circumstances. \n"
204  << "!! Error: Please reconfigure your MPI to provide the proper thread support. \n"
205  << std::endl;
207  } else if((provided > requested) && (rank == 0)) {
208  std::cout << "!! Warning: MPI_Init_thread provided more than the requested functionality: "
209  << MPI_THREAD_STRING(requested) << " (" << MPI_THREAD_STRING(provided) << "). \n"
210  << "!! Warning: You are likely using an MPI implementation with mediocre thread support. \n"
211  << std::endl;
212  }
213 
214 #if defined(MVAPICH2_VERSION)
215  // Check that MVAPICH2 has has the correct thread affinity
216  char * mv2_string = nullptr;
217  int mv2_affinity = 1; /* this is the default behavior of MVAPICH2 */
218 
219  if ((mv2_string = getenv("MV2_ENABLE_AFFINITY")) != nullptr) {
220  mv2_affinity = atoi(mv2_string);
221  }
222 
223  if (mv2_affinity!=0) {
224  std::cout << "!! Error: You are using MVAPICH2 with affinity enabled, probably by default. \n"
225  << "!! Error: This will cause catastrophic performance issues in MADNESS. \n"
226  << "!! Error: Rerun your job with MV2_ENABLE_AFFINITY=0 \n"
227  << std::endl;
229  }
230 #endif // defined(MVAPICH2_VERSION)
231  }
232 
233  /// Finalize the MPI runtime.
234 
235  /// This function starts the teardown process of the MPI runtime.
236  /// The actual \c MPI_Finalize will only be called when all the
237  /// objects using MPI have been destroyed.
238  static void finalize() {
239  world_mpi.reset();
240  }
241  }; // class WorldMpi
242 
243  /// MPI runtime reference counter.
244 
245  /// This object is used to manage the lifetime of the MPI runtime by
246  /// holding a reference to the `WorldMpi::world_mpi` pointer.
248  private:
249  /// A pointer to `WorldMpi::world_mpi`. Used to help manage the lifetime of MPI.
250  std::shared_ptr<WorldMpi> world_mpi;
251 
252  public:
253  /// Constructor.
255 
256  /// Destructor.
258  }; // class WorldMpiInstance
259 
260  } // namespace detail
261 
262 
263  /// This class wraps/extends the MPI interface for \c World.
266  {
267 
268  // Not allowed
271 
272  public:
273  /// Constructs an interface in the specified \c SafeMPI communicator.
274 
275  /// \todo Verify this documentation.
276  /// \param[in] comm The communicator.
279  { }
280 
281  ~WorldMpiInterface() = default;
282 
283  /// Returns the associated \c SafeMPI communicator.
284 
285  /// \return The associated \c SafeMPI communicator.
287  return *static_cast<SafeMPI::Intracomm*>(this);
288  }
289 
295 
296  // !! All of the routines below call the protected interfaces provided above.
297  // !! Please ensure any additional routines follow this convention.
298 
299  /// Isend one element.
300 
301  /// \note Disabled for pointers to reduce accidental misuse.
302  /// \tparam T The type of data to send.
303  /// \param[in] datum The element to send.
304  /// \param[in] dest The destination process.
305  /// \param[in] tag The MPI tag.
306  template <typename T>
307  typename std::enable_if<!std::is_pointer<T>::value, SafeMPI::Request>::type
308  Isend(const T& datum, int dest, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const {
309  return SafeMPI::Intracomm::Isend(&datum, sizeof(T), MPI_BYTE, dest, tag);
310  }
311 
312  /// Async receive data of up to \c count elements from process \c source.
313 
314  /// \tparam T The type of data to receive.
315  /// \param[out] buf Where to put the received data.
316  /// \param[in] count The number of data elements to receive.
317  /// \param[in] source The source process.
318  /// \param[in] tag The MPI tag.
319  template <typename T>
321  Irecv(T* buf, int count, int source, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const {
322  return SafeMPI::Intracomm::Irecv(buf, count*sizeof(T), MPI_BYTE, source, tag);
323  }
324 
325 
326  /// Async receive datum from process \c source with default `tag=1`.
327 
328  /// \tparam T The type of data to receive.
329  /// \param[out] buf Where to put the received datum.
330  /// \param[in] source The source process.
331  /// \param[in] tag The MPI tag.
332  template <typename T>
333  typename std::enable_if<!std::is_pointer<T>::value, SafeMPI::Request>::type
334  Irecv(T& buf, int source, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const {
335  return SafeMPI::Intracomm::Irecv(&buf, sizeof(T), MPI_BYTE, source, tag);
336  }
337 
338 
339  /// Send array of \c lenbuf elements to process \c dest.
340 
341  /// \tparam T The type of data to send.
342  /// \param[in] buf Pointer to the data.
343  /// \param[in] lenbuf The number of data elements to send.
344  /// \param[in] dest The destination process.
345  /// \param[in] tag The MPI tag.
346  template <class T>
347  void Send(const T* buf, long lenbuf, int dest, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const {
348  SafeMPI::Intracomm::Send((void*)buf, lenbuf*sizeof(T), MPI_BYTE, dest, tag);
349  }
350 
351 
352  /// Send element to process \c dest with default `tag=1001`.
353 
354  /// \note Disabled for pointers to reduce accidental misuse.
355  /// \tparam T The type of data to send.
356  /// \param[in] datum The data element to send.
357  /// \param[in] dest The destination process.
358  /// \param[in] tag The MPI tag.
359  template <typename T>
360  typename std::enable_if<!std::is_pointer<T>::value, void>::type
361  Send(const T& datum, int dest, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const {
362  SafeMPI::Intracomm::Send((void*)&datum, sizeof(T), MPI_BYTE, dest, tag);
363  }
364 
365 
366  /// Receive data of up to \c lenbuf elements from process \c src.
367 
368  /// \tparam T The type of data to receive.
369  /// \param[out] buf Where to put the received data.
370  /// \param[in] lenbuf The maximum number of data elements to receive.
371  /// \param[in] src The source process.
372  /// \param[in] tag The MPI tag.
373  template <typename T>
374  void Recv(T* buf, long lenbuf, int src, int tag) const {
375  SafeMPI::Intracomm::Recv(buf, lenbuf*sizeof(T), MPI_BYTE, src, tag);
376  }
377 
378  /// Receive data of up to \c lenbuf elements from process \c dest with \c status.
379 
380  /// \tparam T The type of data to receive.
381  /// \param[out] buf Where to put the received data.
382  /// \param[in] lenbuf The maximum number of data elements to receive.
383  /// \param[in] src The source process.
384  /// \param[in] tag The MPI tag.
385  /// \param[in] status The status.
386  template <typename T>
387  void Recv(T* buf, long lenbuf, int src, int tag, SafeMPI::Status& status) const {
388  SafeMPI::Intracomm::Recv(buf, lenbuf*sizeof(T), MPI_BYTE, src, tag, status);
389  }
390 
391 
392  /// Receive datum from process \c src.
393 
394  /// \tparam T The type of data to receive.
395  /// \param[out] buf The received datum.
396  /// \param[in] src The source process.
397  /// \param[in] tag The MPI tag.
398  template <typename T>
399  typename std::enable_if<!std::is_pointer<T>::value, void>::type
400  Recv(T& buf, int src, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const {
401  SafeMPI::Intracomm::Recv(&buf, sizeof(T), MPI_BYTE, src, tag);
402  }
403 
404 
405  /// MPI broadcast an array of \c count elements.
406 
407  /// \note Read documentation about interaction of MPI collectives and
408  /// AM/task handling.
409  /// \tparam T The type of data to broadcast.
410  /// \param[in,out] buffer The data to send (if this is the \c root
411  /// process); otherwise, a buffer to receive the data.
412  /// \param[in] count The number of data elements being broadcast.
413  /// \param[in] root The process that is sending the data to other
414  /// processes.
415  template <typename T>
416  void Bcast(T* buffer, int count, int root) const {
417  SafeMPI::Intracomm::Bcast(buffer,count*sizeof(T),MPI_BYTE,root);
418  }
419 
420 
421  /// MPI broadcast a datum.
422 
423  /// \note Read documentation about interaction of MPI collectives and
424  /// AM/task handling.
425  /// \tparam T The type of data to broadcast.
426  /// \param[in,out] buffer The datum to send (if this is the \c root
427  /// process); otherwise, the received datum.
428  /// \param[in] root The process that is sending the data to other
429  /// processes.
430  template <typename T>
431  typename std::enable_if<!std::is_pointer<T>::value, void>::type
432  Bcast(T& buffer, int root) const {
433  SafeMPI::Intracomm::Bcast(&buffer, sizeof(T), MPI_BYTE, root);
434  }
435 
436  /// Access the rank of this process.
437 
438  /// \return The rank of this process.
439  int rank() const { return SafeMPI::Intracomm::Get_rank(); }
440 
441  /// Access the total number of processes.
442 
443  /// \return The number of processes.
444  int nproc() const { return SafeMPI::Intracomm::Get_size(); }
445 
446  /// Access the total number of processes.
447 
448  /// \return The number of processes.
449  int size() const { return SafeMPI::Intracomm::Get_size(); }
450  }; // class WorldMpiInterface
451 
452 }
453 
454 /// @}
455 
456 #endif // MADNESS_WORLD_WORLDMPI_H__INCLUDED
Wrapper around MPI_Comm. Has a shallow copy constructor; use Create(Get_group()) for deep copy.
Definition: safempi.h:490
Request Irecv(void *buf, const int count, const MPI_Datatype datatype, const int src, const int tag) const
Definition: safempi.h:740
void Bcast(void *buf, size_t count, const MPI_Datatype datatype, const int root) const
Definition: safempi.h:775
Request Isend(const void *buf, const int count, const MPI_Datatype datatype, const int dest, const int tag) const
Definition: safempi.h:724
int Get_rank() const
Definition: safempi.h:714
void Send(const void *buf, const int count, const MPI_Datatype datatype, int dest, int tag) const
Definition: safempi.h:748
void Recv(void *buf, const int count, const MPI_Datatype datatype, const int source, const int tag, MPI_Status &status) const
Definition: safempi.h:763
int Get_size() const
Definition: safempi.h:719
Intracomm()
Definition: safempi.h:573
Definition: safempi.h:289
Definition: safempi.h:224
This class wraps/extends the MPI interface for World.
Definition: worldmpi.h:266
void Recv(T *buf, long lenbuf, int src, int tag, SafeMPI::Status &status) const
Receive data of up to lenbuf elements from process dest with status.
Definition: worldmpi.h:387
int nproc() const
Access the total number of processes.
Definition: worldmpi.h:444
std::enable_if<!std::is_pointer< T >::value, SafeMPI::Request >::type Isend(const T &datum, int dest, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const
Isend one element.
Definition: worldmpi.h:308
void Bcast(T *buffer, int count, int root) const
MPI broadcast an array of count elements.
Definition: worldmpi.h:416
SafeMPI::Request Irecv(T *buf, int count, int source, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const
Async receive data of up to count elements from process source.
Definition: worldmpi.h:321
std::enable_if<!std::is_pointer< T >::value, SafeMPI::Request >::type Irecv(T &buf, int source, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const
Async receive datum from process source with default tag=1.
Definition: worldmpi.h:334
std::enable_if<!std::is_pointer< T >::value, void >::type Bcast(T &buffer, int root) const
MPI broadcast a datum.
Definition: worldmpi.h:432
WorldMpiInterface(const WorldMpiInterface &)=delete
std::enable_if<!std::is_pointer< T >::value, void >::type Send(const T &datum, int dest, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const
Send element to process dest with default tag=1001.
Definition: worldmpi.h:361
std::enable_if<!std::is_pointer< T >::value, void >::type Recv(T &buf, int src, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const
Receive datum from process src.
Definition: worldmpi.h:400
int size() const
Access the total number of processes.
Definition: worldmpi.h:449
void Send(const T *buf, long lenbuf, int dest, int tag=SafeMPI::DEFAULT_SEND_RECV_TAG) const
Send array of lenbuf elements to process dest.
Definition: worldmpi.h:347
int rank() const
Access the rank of this process.
Definition: worldmpi.h:439
void Recv(T *buf, long lenbuf, int src, int tag) const
Receive data of up to lenbuf elements from process src.
Definition: worldmpi.h:374
WorldMpiInterface(const SafeMPI::Intracomm &comm)
Constructs an interface in the specified SafeMPI communicator.
Definition: worldmpi.h:277
WorldMpiInterface & operator=(const WorldMpiInterface &)=delete
SafeMPI::Intracomm & comm()
Returns the associated SafeMPI communicator.
Definition: worldmpi.h:286
MPI runtime reference counter.
Definition: worldmpi.h:247
std::shared_ptr< WorldMpi > world_mpi
A pointer to WorldMpi::world_mpi. Used to help manage the lifetime of MPI.
Definition: worldmpi.h:250
WorldMpiRuntime()
Constructor.
Definition: worldmpi.h:254
~WorldMpiRuntime()
Destructor.
Definition: worldmpi.h:257
MPI singleton that manages MPI setup and teardown for MADNESS.
Definition: worldmpi.h:95
WorldMpi(int &argc, char **&argv, int requested)
WorldMpi constructor.
Definition: worldmpi.h:121
static void initialize(int &argc, char **&argv, int requested)
Initialize the MPI runtime.
Definition: worldmpi.h:184
static void finalize()
Finalize the MPI runtime.
Definition: worldmpi.h:238
WorldMpi(const WorldMpi &)=delete
~WorldMpi()
WorldMpi destructor.
Definition: worldmpi.h:146
WorldMpi & operator=(const WorldMpi &)=delete
char * strncpy()
auto T(World &world, response_space &f) -> response_space
Definition: global_functions.cc:34
#define MPI_THREAD_STRING(level)
String description of the MPI thread level.
Definition: worldmpi.h:71
static bool own_mpi
Flag storing if MADNESS is responsible for MPI.
Definition: worldmpi.h:106
static std::shared_ptr< WorldMpi > world_mpi
Pointer to help MADNESS manage MPI.
Definition: worldmpi.h:105
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition: madness_exception.h:134
void init_comm_world()
Initialize SafeMPI::COMM_WORLD.
Definition: safempi.h:863
Definition: safempi.cc:35
Intracomm COMM_WORLD
Definition: safempi.cc:67
int Init_thread(int &argc, char **&argv, int requested)
Analogous to MPI_Init_thread.
Definition: safempi.h:878
void Attach_buffer(void *buffer, int size)
Set buffer for Bsend .
Definition: safempi.h:942
int Query_thread()
Analogous to MPI_Query_thread.
Definition: safempi.h:927
int Finalize()
Analogous to MPI_Finalize.
Definition: safempi.h:918
bool Is_initialized()
Check MPI initialization status.
Definition: safempi.h:116
static const int DEFAULT_SEND_RECV_TAG
Definition: safempi.h:106
int Detach_buffer(void *&buffer)
Unset the Bsend buffer.
Definition: safempi.h:949
bool Is_finalized()
Check MPI finalization status.
Definition: safempi.h:125
File holds all helper structures necessary for the CC_Operator and CC2 class.
Definition: DFParameters.h:10
void finalize()
Call this once at the very end of your main program instead of MPI_Finalize().
Definition: world.cc:232
static const Tag DYNAMIC_TAG_BASE
Definition: worldmpi.h:85
std::string type(const PairType &n)
Definition: PNOParameters.h:18
World & initialize(int &argc, char **&argv, bool quiet)
Definition: world.cc:145
Serializes calls to MPI in case it does not support THREAD_MULTIPLE.
#define MPI_SUCCESS
Definition: stubmpi.h:33
int MPI_Error_string(int errorcode, char *string, int *resultlen)
Definition: stubmpi.h:228
#define MPI_COMM_WORLD
Definition: stubmpi.h:24
#define MPI_BYTE
Definition: stubmpi.h:74
int MPI_Abort(MPI_Comm, int code)
Definition: stubmpi.h:198
#define MPI_MAX_ERROR_STRING
Definition: stubmpi.h:38
double source(const coordT &r)
Definition: testperiodic.cc:48
const char * status[2]
Definition: testperiodic.cc:43
Defines types used by the parallel runtime.
int Tag
Used to clearly identify message tag/type.
Definition: worldtypes.h:44