OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
combuff.C
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
35 #include <cstdlib>
36 #include <cstring> // for memmove
37 
38 #include "combuff.h"
39 #include "intarray.h"
40 #include "floatarray.h"
41 #include "floatmatrix.h"
42 #include "error.h"
43 
44 namespace oofem {
45 #ifdef __USE_MPI
46 MPIBuffer :: MPIBuffer(int size, bool dynamic)
47 {
48  this->size = 0;
49  curr_pos = 0;
50  buff = NULL;
51  isDynamic = dynamic;
52  request = MPI_REQUEST_NULL;
53 
54  this->resize(size);
55 }
56 
57 
59 {
60  this->size = 0;
61  curr_pos = 0;
62  buff = NULL;
63  isDynamic = dynamic;
64  request = MPI_REQUEST_NULL;
65 }
66 
67 #endif
68 
70 {
71  if ( buff ) {
72  free(buff);
73  }
74 }
75 
76 
77 int
78 MPIBuffer :: resize(int newSize)
79 {
80  // do not shrink
81  if ( size >= newSize ) {
82  return 1;
83  }
84 
85 
86  ComBuff_BYTE_TYPE *newBuff;
87 
88  if ( newSize > 0 ) {
89  // allocate new memory
90  if ( ( newBuff = ( ComBuff_BYTE_TYPE * )
91  malloc( newSize * sizeof( ComBuff_BYTE_TYPE ) ) ) == NULL ) {
92  // alloc failed -> memory error
93  OOFEM_ERROR("resize failed");
94  }
95 
96  // copy old buffer into new one
97  memmove(newBuff, this->buff, curr_pos);
98  } else {
99  newBuff = NULL;
100  }
101 
102  // dealocate old buffer
103  if ( this->buff ) {
104  free(this->buff);
105  }
106 
107  this->buff = newBuff;
108  size = newSize;
109 
110  return 1;
111 }
112 
113 void
115 {
116  curr_pos = 0;
117  request = MPI_REQUEST_NULL;
118 }
119 
120 #ifdef __USE_MPI
121 
122 int
123 MPIBuffer :: packArray(MPI_Comm communicator, const void *src, int n, MPI_Datatype type)
124 {
125  int _size;
126  // ask MPI for packing size for integer
127  _size = this->givePackSize(communicator, type, n);
128 
129  if ( ( this->curr_pos + _size > this->size ) ) {
130  // reallocate itself
131  if ( isDynamic ) {
132  if ( this->resize(this->curr_pos + _size + __CommunicationBuffer_ALLOC_CHUNK) == 0 ) {
133  return 0;
134  }
135  } else {
136  OOFEM_WARNING("Resize requested in static mode");
137  return 0;
138  }
139  }
140 
141  void *__src = const_cast< void * >(src); // throw away const
142  return ( MPI_Pack(__src, n, type, this->buff, this->size,
143  & this->curr_pos, communicator) == MPI_SUCCESS );
144 }
145 
146 int
147 MPIBuffer :: unpackArray(MPI_Comm communicator, void *dest, int n, MPI_Datatype type)
148 {
149  return ( MPI_Unpack(this->buff, this->size, & this->curr_pos,
150  dest, n, type, communicator) == MPI_SUCCESS );
151 }
152 
153 int
154 MPIBuffer :: iSend(MPI_Comm communicator, int dest, int tag)
155 {
156  return ( MPI_Isend(this->buff, this->curr_pos, MPI_PACKED, dest, tag,
157  communicator, & this->request) == MPI_SUCCESS );
158 }
159 
160 
161 int
162 MPIBuffer :: iRecv(MPI_Comm communicator, int source, int tag, int count)
163 {
164  if ( count ) {
165  if ( count >= this->size ) {
166  // reallocate itself
167  if ( this->resize(count) == 0 ) {
168  return 0;
169  }
170  }
171  }
172 
173  return ( MPI_Irecv(this->buff, this->size, MPI_PACKED, source, tag,
174  communicator, & this->request) == MPI_SUCCESS );
175 }
176 
177 int
179 {
180  int flag;
181  MPI_Status status;
182 
183  MPI_Test(& this->request, & flag, & status);
184  return flag;
185 }
186 
187 int
188 MPIBuffer :: testCompletion(int &source, int &tag)
189 {
190  int flag;
191  MPI_Status status;
192 
193  MPI_Test(& this->request, & flag, & status);
194 
195  source = status.MPI_SOURCE;
196  tag = status.MPI_TAG;
197 
198  return flag;
199 }
200 
201 int
203 {
204  MPI_Status status;
205 
206  return ( MPI_Wait(& this->request, & status) == MPI_SUCCESS );
207 }
208 
209 
210 int
211 MPIBuffer :: bcast(MPI_Comm communicator, int root)
212 {
213  return MPI_Bcast(this->buff, this->size, MPI_PACKED, root, communicator);
214 }
215 
216 
217 int
218 MPIBuffer :: givePackSize(MPI_Comm communicator, MPI_Datatype type, int size)
219 {
220  int requredSpace;
221  MPI_Pack_size(size, type, communicator, & requredSpace);
222  return requredSpace;
223 }
224 
225 
226 void
228 {
229  for ( int _i = 0; _i < 20; ++_i ) {
230  fprintf(stderr, "%d ", buff [ _i ]);
231  }
232 
233  fprintf(stderr, "\n");
234 }
235 
236 #endif
237 
238 
239 /*
240 int CommunicationBuffer :: read(int *data, int count)
241 {
242 
243 }
244 
245 int CommunicationBuffer :: read(unsigned long *data, int count)
246 int CommunicationBuffer :: read(long *data, int count)
247 int CommunicationBuffer :: read(double *data, int count)
248 int CommunicationBuffer :: read(char *data, int count)
249 
250 int CommunicationBuffer :: write(const int *data, int count)
251 int CommunicationBuffer :: write(const unsigned long *data, int count)
252 int CommunicationBuffer :: write(const long *data, int count)
253 int CommunicationBuffer :: write(const double *data, int count)
254 int CommunicationBuffer :: write(const char *data, int count)
255 */
256 
258 {
259  char val;
260  int ret = this->read(& val, 1);
261  data = val != 0;
262  return ret;
263 }
264 
266 {
267  char val = data;
268  return this->write(& val, 1);
269 }
270 
272 {
273  int requiredSpace;
274  MPI_Pack_size(count, MPI_INT, communicator, & requiredSpace);
275  return requiredSpace;
276 }
277 
279 {
280  int requiredSpace;
281  MPI_Pack_size(count, MPI_DOUBLE, communicator, & requiredSpace);
282  return requiredSpace;
283 }
284 
286 {
287  int requiredSpace;
288  MPI_Pack_size(count, MPI_CHAR, communicator, & requiredSpace);
289  return requiredSpace;
290 }
291 
293 {
294  int requiredSpace;
295  MPI_Pack_size(count, MPI_CHAR, communicator, & requiredSpace);
296  return requiredSpace;
297 }
298 
300 {
301  int requiredSpace;
302  MPI_Pack_size(count, MPI_LONG, communicator, & requiredSpace);
303  return requiredSpace;
304 }
305 
306 } // end namespace oofem
virtual int givePackSizeOfLong(int count)
Definition: combuff.C:299
virtual void init()
Initializes buffer to empty state.
Definition: combuff.C:114
int packArray(MPI_Comm communicator, const void *src, int n, MPI_Datatype type)
Packs array of a values of given type into buffer.
Definition: combuff.C:123
int bcast(MPI_Comm communicator, int root)
Initializes broadcast over collaborating processes.
Definition: combuff.C:211
virtual int givePackSizeOfChar(int count)
Definition: combuff.C:285
int givePackSize(MPI_Comm communicator, MPI_Datatype type, int size)
Returns pack size required to pack array of given type and size (c-style).
Definition: combuff.C:218
char ComBuff_BYTE_TYPE
Type with size equal to one byte (sizeof (ComBuff_BYTE_TYPE) should be 1).
Definition: combuff.h:49
ComBuff_BYTE_TYPE * buff
Buffer. Dynamically allocated.
Definition: combuff.h:59
virtual int iSend(MPI_Comm communicator, int dest, int tag)
Starts standard mode, nonblocking send.
Definition: combuff.C:154
virtual int waitCompletion()
Waits until a completion of a nonblocking communication.
Definition: combuff.C:202
MPI_Request request
MPI request handle.
Definition: combuff.h:65
int resize(int newSize)
Resizes buffer to given size.
Definition: combuff.C:78
virtual int givePackSizeOfInt(int count)
Definition: combuff.C:271
#define OOFEM_ERROR(...)
Definition: error.h:61
int size
Size and current position in buffer in bytes (sizeof(char)).
Definition: combuff.h:55
virtual int write(bool data)
Writes a bool value.
Definition: combuff.C:265
bool isDynamic
Dynamic flag (if true, buffer can grow, but reallocation is needed).
Definition: combuff.h:57
virtual int givePackSizeOfDouble(int count)
Definition: combuff.C:278
virtual int iRecv(MPI_Comm communicator, int source, int tag, int count=0)
Starts standard mode, nonblocking receive.
Definition: combuff.C:162
int testCompletion()
Tests if the operation identified by this->request is complete.
Definition: combuff.C:178
int unpackArray(MPI_Comm communicator, void *dest, int n, MPI_Datatype type)
Unpacks array of values of given type from buffer.
Definition: combuff.C:147
MPIBuffer(int size, bool dynamic=0)
Constructor. Creates buffer of given size, using given communicator for packing.
Definition: combuff.C:46
the oofem namespace is to define a context or scope in which all oofem names are defined.
virtual int read(bool &data)
Reads a bool value from data.
Definition: combuff.C:257
#define __CommunicationBuffer_ALLOC_CHUNK
Definition: combuff.h:44
#define OOFEM_WARNING(...)
Definition: error.h:62
virtual ~MPIBuffer()
Destructor.
Definition: combuff.C:69
virtual int givePackSizeOfBool(int count)
Definition: combuff.C:292

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:27 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011