Actual source code: vscreate.c
petsc-3.9.4 2018-09-11
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: }