Actual source code: dacorn.c

  1: /*
  2:   Code for manipulating distributed regular arrays in parallel.
  3: */

 5:  #include src/dm/da/daimpl.h

  9: /*@
 10:    DASetCoordinates - Sets into the DA a vector that indicates the 
 11:       coordinates of the local nodes (NOT including ghost nodes).

 13:    Not Collective

 15:    Input Parameter:
 16: +  da - the distributed array
 17: -  c - coordinate vector

 19:    Note:
 20:     The coordinates should NOT include those for all ghost points

 22:      Does NOT increase the reference count of this vector, so caller should NOT
 23:   destroy the vector.

 25:   Level: intermediate

 27: .keywords: distributed array, get, corners, nodes, local indices, coordinates

 29: .seealso: DAGetGhostCorners(), DAGetCoordinates(), DASetUniformCoordinates(). DAGetGhostCoordinates(), DAGetCoordinateDA()
 30: @*/
 31: PetscErrorCode DASetCoordinates(DA da,Vec c)
 32: {

 38:   da->coordinates = c;
 39:   VecSetBlockSize(c,da->dim);
 40:   return(0);
 41: }

 45: /*@
 46:    DAGetCoordinates - Gets the node coordinates associated with a DA.

 48:    Not Collective

 50:    Input Parameter:
 51: .  da - the distributed array

 53:    Output Parameter:
 54: .  c - coordinate vector

 56:    Note:
 57:     Each process has only the coordinates for its local nodes (does NOT have the
 58:   coordinates for the ghost nodes).

 60:     For two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
 61:     and (x_0,y_0,z_0,x_1,y_1,z_1...)

 63:     You should not destroy or keep around this vector after the DA is destroyed.

 65:   Level: intermediate

 67: .keywords: distributed array, get, corners, nodes, local indices, coordinates

 69: .seealso: DAGetGhostCorners(), DASetCoordinates(), DASetUniformCoordinates(), DAGetCoordinates(), DAGetCoordinateDA()
 70: @*/
 71: PetscErrorCode DAGetCoordinates(DA da,Vec *c)
 72: {
 74: 
 77:   *c = da->coordinates;
 78:   return(0);
 79: }

 83: /*@
 84:    DAGetCoordinateDA - Gets the DA that scatters between global and local DA coordinates

 86:    Collective on DA

 88:    Input Parameter:
 89: .  da - the distributed array

 91:    Output Parameter:
 92: .  dac - coordinate DA

 94:    Note: You should not destroy or keep around this vector after the DA is destroyed.

 96:   Level: intermediate

 98: .keywords: distributed array, get, corners, nodes, local indices, coordinates

100: .seealso: DAGetGhostCorners(), DASetCoordinates(), DASetUniformCoordinates(), DAGetCoordinates(), DAGetGhostedCoordinates()
101: @*/
102: PetscErrorCode DAGetCoordinateDA(DA da,DA *cda)
103: {
104:   DAStencilType  st;
106:   PetscMPIInt    size;

109:   if (da->da_coordinates) {
110:     *cda = da->da_coordinates;
111:     return(0);
112:   }
113:   MPI_Comm_size(da->comm,&size);
114:   if (da->dim == 1) {
115:     if (da->w == 1) {
116:       da->da_coordinates = da;
117:     } else {
118:       PetscInt            s,m,*lc,l;
119:       DAPeriodicType pt;
120:       DAGetInfo(da,0,&m,0,0,0,0,0,0,&s,&pt,0);
121:       DAGetCorners(da,0,0,0,&l,0,0);
122:       PetscMalloc(size*sizeof(PetscInt),&lc);
123:       MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,da->comm);
124:       DACreate1d(da->comm,pt,m,1,s,lc,&da->da_coordinates);
125:       PetscFree(lc);
126:     }
127:   } else if (da->dim == 2) {
128:     DAGetInfo(da,0,0,0,0,0,0,0,0,0,0,&st);
129:     if (da->w == 2 && st == DA_STENCIL_BOX) {
130:       da->da_coordinates = da;
131:     } else {
132:       PetscInt            i,s,m,*lc,*ld,l,k,n,M,N;
133:       DAPeriodicType pt;
134:       DAGetInfo(da,0,&m,&n,0,&M,&N,0,0,&s,&pt,0);
135:       DAGetCorners(da,0,0,0,&l,&k,0);
136:       PetscMalloc(size*sizeof(PetscInt),&lc);
137:       PetscMalloc(size*sizeof(PetscInt),&ld);
138:       /* only first M values in lc matter */
139:       MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,da->comm);
140:       /* every Mth value in ld matters */
141:       MPI_Allgather(&k,1,MPIU_INT,ld,1,MPIU_INT,da->comm);
142:       for ( i=0; i<N; i++) {
143:         ld[i] = ld[M*i];
144:       }
145:       DACreate2d(da->comm,pt,DA_STENCIL_BOX,m,n,M,N,2,s,lc,ld,&da->da_coordinates);
146:       PetscFree(lc);
147:       PetscFree(ld);
148:     }
149:   } else if (da->dim == 3) {
150:     DAGetInfo(da,0,0,0,0,0,0,0,0,0,0,&st);
151:     if (da->w == 3 && st == DA_STENCIL_BOX) {
152:       da->da_coordinates = da;
153:     } else {
154:       PetscInt            i,s,m,*lc,*ld,*le,l,k,q,n,M,N,P,p;
155:       DAPeriodicType pt;
156:       DAGetInfo(da,0,&m,&n,&p,&M,&N,&P,0,&s,&pt,0);
157:       DAGetCorners(da,0,0,0,&l,&k,&q);
158:       PetscMalloc(size*sizeof(PetscInt),&lc);
159:       PetscMalloc(size*sizeof(PetscInt),&ld);
160:       PetscMalloc(size*sizeof(PetscInt),&le);
161:       /* only first M values in lc matter */
162:       MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,da->comm);
163:       /* every Mth value in ld matters */
164:       MPI_Allgather(&k,1,MPIU_INT,ld,1,MPIU_INT,da->comm);
165:       for ( i=0; i<N; i++) {
166:         ld[i] = ld[M*i];
167:       }
168:       MPI_Allgather(&q,1,MPIU_INT,le,1,MPIU_INT,da->comm);
169:       for ( i=0; i<P; i++) {
170:         le[i] = le[M*N*i];
171:       }
172:       DACreate3d(da->comm,pt,DA_STENCIL_BOX,m,n,p,M,N,P,3,s,lc,ld,le,&da->da_coordinates);
173:       PetscFree(lc);
174:       PetscFree(ld);
175:       PetscFree(le);
176:     }
177:   }
178:   *cda = da->da_coordinates;
179:   return(0);
180: }


185: /*@
186:    DAGetGhostedCoordinates - Gets the node coordinates associated with a DA.

188:    Collective on DA the first time it is called

190:    Input Parameter:
191: .  da - the distributed array

193:    Output Parameter:
194: .  c - coordinate vector

196:    Note:
197:     Each process has only the coordinates for its local AND ghost nodes

199:     For two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
200:     and (x_0,y_0,z_0,x_1,y_1,z_1...)

202:     You should not destroy or keep around this vector after the DA is destroyed.

204:   Level: intermediate

206: .keywords: distributed array, get, corners, nodes, local indices, coordinates

208: .seealso: DAGetGhostCorners(), DASetCoordinates(), DASetUniformCoordinates(), DAGetCoordinates(), DAGetCoordinateDA()
209: @*/
210: PetscErrorCode DAGetGhostedCoordinates(DA da,Vec *c)
211: {
213: 
216:   if (!da->coordinates) SETERRQ(PETSC_ERR_ORDER,"You must call DASetCoordinates() before this call");
217:   if (!da->ghosted_coordinates) {
218:     DA  dac;
220:     DAGetCoordinateDA(da,&dac);
221:     DACreateLocalVector(dac,&da->ghosted_coordinates);
222:     if (dac == da) {PetscObjectDereference((PetscObject)dac);}
223:     DAGlobalToLocalBegin(dac,da->coordinates,INSERT_VALUES,da->ghosted_coordinates);
224:     DAGlobalToLocalEnd(dac,da->coordinates,INSERT_VALUES,da->ghosted_coordinates);
225:   }
226:   *c = da->ghosted_coordinates;
227:   return(0);
228: }

232: /*@C
233:    DASetFieldName - Sets the names of individual field components in multicomponent
234:    vectors associated with a DA.

236:    Not Collective

238:    Input Parameters:
239: +  da - the distributed array
240: .  nf - field number for the DA (0, 1, ... dof-1), where dof indicates the 
241:         number of degrees of freedom per node within the DA
242: -  names - the name of the field (component)

244:   Level: intermediate

246: .keywords: distributed array, get, component name

248: .seealso: DAGetFieldName()
249: @*/
250: PetscErrorCode DASetFieldName(DA da,PetscInt nf,const char name[])
251: {

255: 
257:   if (nf < 0 || nf >= da->w) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number: %D",nf);
258:   if (da->fieldname[nf]) {PetscFree(da->fieldname[nf]);}
259: 
260:   PetscStrallocpy(name,&da->fieldname[nf]);
261:   return(0);
262: }

266: /*@C
267:    DAGetFieldName - Gets the names of individual field components in multicomponent
268:    vectors associated with a DA.

270:    Not Collective

272:    Input Parameter:
273: +  da - the distributed array
274: -  nf - field number for the DA (0, 1, ... dof-1), where dof indicates the 
275:         number of degrees of freedom per node within the DA

277:    Output Parameter:
278: .  names - the name of the field (component)

280:   Level: intermediate

282: .keywords: distributed array, get, component name

284: .seealso: DASetFieldName()
285: @*/
286: PetscErrorCode DAGetFieldName(DA da,PetscInt nf,char **name)
287: {
289: 
292:   if (nf < 0 || nf >= da->w) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number: %D",nf);
293:   *name = da->fieldname[nf];
294:   return(0);
295: }

299: /*@
300:    DAGetCorners - Returns the global (x,y,z) indices of the lower left
301:    corner of the local region, excluding ghost points.

303:    Not Collective

305:    Input Parameter:
306: .  da - the distributed array

308:    Output Parameters:
309: +  x,y,z - the corner indices (where y and z are optional; these are used
310:            for 2D and 3D problems)
311: -  m,n,p - widths in the corresponding directions (where n and p are optional;
312:            these are used for 2D and 3D problems)

314:    Note:
315:    The corner information is independent of the number of degrees of 
316:    freedom per node set with the DACreateXX() routine. Thus the x, y, z, and
317:    m, n, p can be thought of as coordinates on a logical grid, where each
318:    grid point has (potentially) several degrees of freedom.
319:    Any of y, z, n, and p can be passed in as PETSC_NULL if not needed.

321:   Level: beginner

323: .keywords: distributed array, get, corners, nodes, local indices

325: .seealso: DAGetGhostCorners()
326: @*/
327: PetscErrorCode DAGetCorners(DA da,PetscInt *x,PetscInt *y,PetscInt *z,PetscInt *m,PetscInt *n,PetscInt *p)
328: {
329:   PetscInt w;

333:   /* since the xs, xe ... have all been multiplied by the number of degrees 
334:      of freedom per cell, w = da->w, we divide that out before returning.*/
335:   w = da->w;
336:   if (x) *x = da->xs/w; if(m) *m = (da->xe - da->xs)/w;
337:   /* the y and z have NOT been multiplied by w */
338:   if (y) *y = da->ys;   if (n) *n = (da->ye - da->ys);
339:   if (z) *z = da->zs;   if (p) *p = (da->ze - da->zs);
340:   return(0);
341: }