Actual source code: vscreate.c

petsc-3.9.4 2018-09-11
Report Typos and Errors

  2: /*
  3:     The VECSCATTER (vec scatter) interface routines, callable by users.
  4: */

  6:  #include <petsc/private/vecimpl.h>
  7:  #include <../src/vec/vec/impls/mpi/pvecimpl.h>

  9: /* Logging support */
 10: PetscClassId VEC_SCATTER_CLASSID;

 12: #define VEC_SEQ_ID 0
 13: #define VEC_MPI_ID 1

 15: #if defined(PETSC_HAVE_MPI_WIN_CREATE_FEATURE)
 16: extern PetscErrorCode VecScatterCreateCommon_PtoS_MPI3(VecScatter_MPI_General*,VecScatter_MPI_General*,VecScatter);
 17: #endif

 19: /* -------------------------------- */
 20: PetscFunctionList VecScatterList              = NULL;
 21: PetscBool         VecScatterRegisterAllCalled = PETSC_FALSE;

 23: /*@C
 24:   VecScatterSetType - Builds a vector scatter, for a particular vector scatter implementation.

 26:   Collective on VecScatter

 28:   Input Parameters:
 29: + vscat - The vector scatter object
 30: - type - The name of the vector scatter type

 32:   Options Database Key:
 33: . -vecscatter_type <type> - Sets the vector scatter type; use -help for a list
 34:                      of available types

 36:   Notes:
 37:   See "petsc/include/petscvec.h" for available vector scatter types (for instance, VECSCATTERMPI1, or VECSCATTERMPI3NODE).

 39:   Use VecScatterDuplicate() to form additional vectors scatter of the same type as an existing vector scatter.

 41:   Level: intermediate

 43: .keywords: vector scatter, set, type
 44: .seealso: VecScatterGetType(), VecScatterCreate()
 45: @*/
 46: PetscErrorCode VecScatterSetType(VecScatter vscat, VecScatterType type)
 47: {
 48:   PetscBool      match;
 50:   PetscErrorCode (*r)(VecScatter);

 54:   PetscObjectTypeCompare((PetscObject)vscat, type, &match);
 55:   if (match) return(0);

 57:   PetscFunctionListFind(VecScatterList,type,&r);
 58:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown vector scatter type: %s",type);

 60:   if (vscat->ops->destroy) {
 61:     (*vscat->ops->destroy)(vscat);
 62:     vscat->ops->destroy = NULL;
 63:   }

 65:   (*r)(vscat);
 66:   return(0);
 67: }

 69: /*@C
 70:   VecScatterGetType - Gets the vector scatter type name (as a string) from the VecScatter.

 72:   Not Collective

 74:   Input Parameter:
 75: . vscat  - The vector scatter

 77:   Output Parameter:
 78: . type - The vector scatter type name

 80:   Level: intermediate

 82: .keywords: vector scatter, get, type, name
 83: .seealso: VecScatterSetType(), VecScatterCreate()
 84: @*/
 85: PetscErrorCode VecScatterGetType(VecScatter vscat, VecScatterType *type)
 86: {

 92:   VecScatterRegisterAll();
 93:   *type = ((PetscObject)vscat)->type_name;
 94:   return(0);
 95: }

 97: /*@
 98:   VecScatterSetFromOptions - Configures the vector scatter from the options database.

100:   Collective on VecScatter

102:   Input Parameter:
103: . vscat - The vector scatter

105:   Notes:  To see all options, run your program with the -help option, or consult the users manual.
106:           Must be called after VecScatterCreate() but before the vector scatter is used.

108:   Level: beginner

110:   Concepts: vectorscatter^setting options
111:   Concepts: vectorscatter^setting type

113: .keywords: VecScatter, set, options, database
114: .seealso: VecScatterCreate()
115: @*/
116: PetscErrorCode VecScatterSetFromOptions(VecScatter vscat)
117: {
119:   PetscBool      opt;
120:   VecScatterType defaultType;
121:   char           typeName[256];
122:   PetscMPIInt    size;


127:   PetscObjectOptionsBegin((PetscObject)vscat);

129:   /* Handle vector type options */
130:   if (((PetscObject)vscat)->type_name) {
131:     defaultType = ((PetscObject)vscat)->type_name;
132:   } else {
133:     MPI_Comm_size(PetscObjectComm((PetscObject)vscat), &size);
134:     if (size > 1) defaultType = VECSCATTERMPI1;
135:     else defaultType = VECSCATTERSEQ;
136:   }

138:   VecScatterRegisterAll();
139:   PetscOptionsFList("-vecscatter_type","Vector Scatter type","VecScatterSetType",VecScatterList,defaultType,typeName,256,&opt);
140:   if (opt) {
141:     VecScatterSetType(vscat,typeName);
142:   } else {
143:     VecScatterSetType(vscat,defaultType);
144:   }

146:   vscat->beginandendtogether = PETSC_FALSE;
147:   PetscOptionsBool("-vecscatter_merge","Use combined (merged) vector scatter begin and end","VecScatterCreate",vscat->beginandendtogether,&vscat->beginandendtogether,NULL);
148:   if (vscat->beginandendtogether) {
149:     PetscInfo(vscat,"Using combined (merged) vector scatter begin and end\n");
150:   }

152:   vscat->packtogether = PETSC_FALSE;
153:   PetscOptionsBool("-vecscatter_packtogether","Pack all messages before sending","VecScatterCreate",vscat->packtogether,&vscat->packtogether,NULL);
154:   if (vscat->packtogether) {
155:     PetscInfo(vscat,"Pack all messages before sending\n");
156:   }
157:   PetscOptionsEnd();
158:   return(0);
159: }

161: /*@C
162:   VecScatterRegister -  Adds a new vector scatter component implementation

164:   Not Collective

166:   Input Parameters:
167: + name        - The name of a new user-defined creation routine
168: - create_func - The creation routine itself

170:   Notes:
171:   VecScatterRegister() may be called multiple times to add several user-defined vectors

173:   Sample usage:
174: .vb
175:     VecScatterRegister("my_vecscatter",MyVecScatterCreate);
176: .ve

178:   Then, your vector scatter type can be chosen with the procedural interface via
179: .vb
180:     VecScatterCreate(MPI_Comm, VecScatter *);
181:     VecScatterSetType(VecScatter,"my_vectorscatter_name");
182: .ve
183:    or at runtime via the option
184: .vb
185:     -vecscatter_type my_vectorscatter_name
186: .ve

188:   Level: advanced

190: .keywords: VecScatter, Register

192: .seealso: VecScatterRegisterAll(), VecScatterRegisterDestroy()
193: @*/
194: PetscErrorCode VecScatterRegister(const char sname[], PetscErrorCode (*function)(VecScatter))
195: {

199:   PetscFunctionListAdd(&VecScatterList,sname,function);
200:   return(0);
201: }

203: /* VecScatterCreate() will be renamed as VecScatterCreateWithVecs() */
204: /* ---------------------------------------------------------------- */
205: /*@C
206:    VecScatterCreate - Creates a vector scatter context.

208:    Collective on Vec

210:    Input Parameters:
211: +  xin - a vector that defines the shape (parallel data layout of the vector)
212:          of vectors from which we scatter
213: .  yin - a vector that defines the shape (parallel data layout of the vector)
214:          of vectors to which we scatter
215: .  ix - the indices of xin to scatter (if NULL scatters all values)
216: -  iy - the indices of yin to hold results (if NULL fills entire vector yin)

218:    Output Parameter:
219: .  newctx - location to store the new scatter context

221:    Options Database Keys: (uses regular MPI_Sends by default)
222: .  -vecscatter_view         - Prints detail of communications
223: .  -vecscatter_view ::ascii_info    - Print less details about communication
224: .  -vecscatter_ssend        - Uses MPI_Ssend_init() instead of MPI_Send_init()
225: .  -vecscatter_rsend           - use ready receiver mode for MPI sends
226: .  -vecscatter_merge        - VecScatterBegin() handles all of the communication, VecScatterEnd() is a nop
227:                               eliminates the chance for overlap of computation and communication
228: .  -vecscatter_sendfirst    - Posts sends before receives
229: .  -vecscatter_packtogether - Pack all messages before sending, receive all messages before unpacking
230: .  -vecscatter_alltoall     - Uses MPI all to all communication for scatter
231: .  -vecscatter_window       - Use MPI 2 window operations to move data
232: .  -vecscatter_nopack       - Avoid packing to work vector when possible (if used with -vecscatter_alltoall then will use MPI_Alltoallw()
233: -  -vecscatter_reproduce    - insure that the order of the communications are done the same for each scatter, this under certain circumstances
234:                               will make the results of scatters deterministic when otherwise they are not (it may be slower also).

236: $
237: $                                                                                    --When packing is used--
238: $                               MPI Datatypes (no packing)  sendfirst   merge        packtogether  persistent*
239: $                                _nopack                   _sendfirst    _merge      _packtogether                -vecscatter_
240: $ ----------------------------------------------------------------------------------------------------------------------------
241: $    Message passing    Send       p                           X            X           X         always
242: $                      Ssend       p                           X            X           X         always          _ssend
243: $                      Rsend       p                        nonsense        X           X         always          _rsend
244: $    AlltoAll  v or w              X                        nonsense     always         X         nonsense        _alltoall
245: $    MPI_Win                       p                        nonsense        p           p         nonsense        _window
246: $
247: $   Since persistent sends and receives require a constant memory address they can only be used when data is packed into the work vector
248: $   because the in and out array may be different for each call to VecScatterBegin/End().
249: $
250: $    p indicates possible, but not implemented. X indicates implemented
251: $

253:     Level: intermediate

255:   Notes:
256:    In calls to VecScatter() you can use different vectors than the xin and
257:    yin you used above; BUT they must have the same parallel data layout, for example,
258:    they could be obtained from VecDuplicate().
259:    A VecScatter context CANNOT be used in two or more simultaneous scatters;
260:    that is you cannot call a second VecScatterBegin() with the same scatter
261:    context until the VecScatterEnd() has been called on the first VecScatterBegin().
262:    In this case a separate VecScatter is needed for each concurrent scatter.

264:    Currently the MPI_Send(), MPI_Ssend() and MPI_Rsend() all use PERSISTENT versions.
265:    (this unfortunately requires that the same in and out arrays be used for each use, this
266:     is why when not using MPI_alltoallw() we always need to pack the input into the work array before sending
267:     and unpack upon receeving instead of using MPI datatypes to avoid the packing/unpacking).

269:    Both ix and iy cannot be NULL at the same time.

271:    Concepts: scatter^between vectors
272:    Concepts: gather^between vectors

274: .seealso: VecScatterDestroy(), VecScatterCreateToAll(), VecScatterCreateToZero()
275: @*/
276: PetscErrorCode VecScatterCreate(Vec xin,IS ix,Vec yin,IS iy,VecScatter *newctx)
277: {
278:   VecScatter        ctx;
279:   PetscErrorCode    ierr;
280:   PetscMPIInt       size;
281:   MPI_Comm          comm,ycomm;

284:   if (!ix && !iy) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_SUP,"Cannot pass default in for both input and output indices");
286:   *newctx = NULL;
287:   VecScatterInitializePackage();

289:   /* Get comm from xin and yin */
290:   PetscObjectGetComm((PetscObject)xin,&comm);
291:   MPI_Comm_size(comm,&size);

293:   PetscObjectGetComm((PetscObject)yin,&ycomm);
294:   MPI_Comm_size(ycomm,&size);
295:   if (size > 1) comm = ycomm;

297:   PetscHeaderCreate(ctx,VEC_SCATTER_CLASSID,"VecScatter","Vector Scatter","VecScatter",comm,VecScatterDestroy,VecScatterView);

299:   ctx->from_v = xin; ctx->to_v = yin;
300:   ctx->from_is = ix; ctx->to_is = iy;
301:   ctx->inuse        = PETSC_FALSE;
302:   ctx->is_duplicate = PETSC_FALSE;

304:   VecGetLocalSize(xin,&ctx->from_n);
305:   VecGetLocalSize(yin,&ctx->to_n);
306:   *newctx = ctx;

308:   /* Set default scatter type */
309:   MPI_Comm_size(comm,&size);
310:   if (size == 1) {
311:     VecScatterSetType(ctx,VECSCATTERSEQ);
312:   } else {
313:     VecScatterSetType(ctx,VECSCATTERMPI1);
314:   }
315:   VecScatterSetFromOptions(ctx);
316:   return(0);
317: }