1 2 /* 3 Some useful vector utility functions. 4 */ 5 #include <../src/vec/vec/impls/mpi/pvecimpl.h> /*I "petscvec.h" I*/ 6 7 /*@ 8 VecStrideSet - Sets a subvector of a vector defined 9 by a starting point and a stride with a given value 10 11 Logically Collective on Vec 12 13 Input Parameters: 14 + v - the vector 15 . start - starting point of the subvector (defined by a stride) 16 - s - value to set for each entry in that subvector 17 18 Notes: 19 One must call VecSetBlockSize() before this routine to set the stride 20 information, or use a vector created from a multicomponent DMDA. 21 22 This will only work if the desire subvector is a stride subvector 23 24 Level: advanced 25 26 .seealso: `VecNorm()`, `VecStrideGather()`, `VecStrideScatter()`, `VecStrideMin()`, `VecStrideMax()`, `VecStrideScale()` 27 @*/ 28 PetscErrorCode VecStrideSet(Vec v, PetscInt start, PetscScalar s) { 29 PetscInt i, n, bs; 30 PetscScalar *x; 31 32 PetscFunctionBegin; 33 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 34 PetscCall(VecGetLocalSize(v, &n)); 35 PetscCall(VecGetBlockSize(v, &bs)); 36 PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative start %" PetscInt_FMT, start); 37 PetscCheck(start < bs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Start of stride subvector (%" PetscInt_FMT ") is too large for stride\n Have you set the vector blocksize (%" PetscInt_FMT ") correctly with VecSetBlockSize()?", start, bs); 38 PetscCall(VecGetArray(v, &x)); 39 for (i = start; i < n; i += bs) x[i] = s; 40 PetscCall(VecRestoreArray(v, &x)); 41 PetscFunctionReturn(0); 42 } 43 44 /*@ 45 VecStrideScale - Scales a subvector of a vector defined 46 by a starting point and a stride. 47 48 Logically Collective on Vec 49 50 Input Parameters: 51 + v - the vector 52 . start - starting point of the subvector (defined by a stride) 53 - scale - value to multiply each subvector entry by 54 55 Notes: 56 One must call VecSetBlockSize() before this routine to set the stride 57 information, or use a vector created from a multicomponent DMDA. 58 59 This will only work if the desire subvector is a stride subvector 60 61 Level: advanced 62 63 .seealso: `VecNorm()`, `VecStrideGather()`, `VecStrideScatter()`, `VecStrideMin()`, `VecStrideMax()`, `VecStrideScale()` 64 @*/ 65 PetscErrorCode VecStrideScale(Vec v, PetscInt start, PetscScalar scale) { 66 PetscInt i, n, bs; 67 PetscScalar *x; 68 69 PetscFunctionBegin; 70 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 71 PetscCall(VecGetLocalSize(v, &n)); 72 PetscCall(VecGetBlockSize(v, &bs)); 73 PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative start %" PetscInt_FMT, start); 74 PetscCheck(start < bs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Start of stride subvector (%" PetscInt_FMT ") is too large for stride\n Have you set the vector blocksize (%" PetscInt_FMT ") correctly with VecSetBlockSize()?", start, bs); 75 PetscCall(VecGetArray(v, &x)); 76 for (i = start; i < n; i += bs) x[i] *= scale; 77 PetscCall(VecRestoreArray(v, &x)); 78 PetscFunctionReturn(0); 79 } 80 81 /*@ 82 VecStrideNorm - Computes the norm of subvector of a vector defined 83 by a starting point and a stride. 84 85 Collective on Vec 86 87 Input Parameters: 88 + v - the vector 89 . start - starting point of the subvector (defined by a stride) 90 - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY 91 92 Output Parameter: 93 . norm - the norm 94 95 Notes: 96 One must call VecSetBlockSize() before this routine to set the stride 97 information, or use a vector created from a multicomponent DMDA. 98 99 If x is the array representing the vector x then this computes the norm 100 of the array (x[start],x[start+stride],x[start+2*stride], ....) 101 102 This is useful for computing, say the norm of the pressure variable when 103 the pressure is stored (interlaced) with other variables, say density etc. 104 105 This will only work if the desire subvector is a stride subvector 106 107 Level: advanced 108 109 .seealso: `VecNorm()`, `VecStrideGather()`, `VecStrideScatter()`, `VecStrideMin()`, `VecStrideMax()` 110 @*/ 111 PetscErrorCode VecStrideNorm(Vec v, PetscInt start, NormType ntype, PetscReal *nrm) { 112 PetscInt i, n, bs; 113 const PetscScalar *x; 114 PetscReal tnorm; 115 116 PetscFunctionBegin; 117 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 118 PetscValidLogicalCollectiveEnum(v, ntype, 3); 119 PetscValidRealPointer(nrm, 4); 120 PetscCall(VecGetLocalSize(v, &n)); 121 PetscCall(VecGetBlockSize(v, &bs)); 122 PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative start %" PetscInt_FMT, start); 123 PetscCheck(start < bs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Start of stride subvector (%" PetscInt_FMT ") is too large for stride\n Have you set the vector blocksize (%" PetscInt_FMT ") correctly with VecSetBlockSize()?", start, bs); 124 PetscCall(VecGetArrayRead(v, &x)); 125 if (ntype == NORM_2) { 126 PetscScalar sum = 0.0; 127 for (i = start; i < n; i += bs) sum += x[i] * (PetscConj(x[i])); 128 tnorm = PetscRealPart(sum); 129 PetscCall(MPIU_Allreduce(&tnorm, nrm, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)v))); 130 *nrm = PetscSqrtReal(*nrm); 131 } else if (ntype == NORM_1) { 132 tnorm = 0.0; 133 for (i = start; i < n; i += bs) tnorm += PetscAbsScalar(x[i]); 134 PetscCall(MPIU_Allreduce(&tnorm, nrm, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)v))); 135 } else if (ntype == NORM_INFINITY) { 136 tnorm = 0.0; 137 for (i = start; i < n; i += bs) { 138 if (PetscAbsScalar(x[i]) > tnorm) tnorm = PetscAbsScalar(x[i]); 139 } 140 PetscCall(MPIU_Allreduce(&tnorm, nrm, 1, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)v))); 141 } else SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown norm type"); 142 PetscCall(VecRestoreArrayRead(v, &x)); 143 PetscFunctionReturn(0); 144 } 145 146 /*@ 147 VecStrideMax - Computes the maximum of subvector of a vector defined 148 by a starting point and a stride and optionally its location. 149 150 Collective on Vec 151 152 Input Parameters: 153 + v - the vector 154 - start - starting point of the subvector (defined by a stride) 155 156 Output Parameters: 157 + idex - the location where the maximum occurred (pass NULL if not required) 158 - nrm - the maximum value in the subvector 159 160 Notes: 161 One must call VecSetBlockSize() before this routine to set the stride 162 information, or use a vector created from a multicomponent DMDA. 163 164 If xa is the array representing the vector x, then this computes the max 165 of the array (xa[start],xa[start+stride],xa[start+2*stride], ....) 166 167 This is useful for computing, say the maximum of the pressure variable when 168 the pressure is stored (interlaced) with other variables, e.g., density, etc. 169 This will only work if the desire subvector is a stride subvector. 170 171 Level: advanced 172 173 .seealso: `VecMax()`, `VecStrideNorm()`, `VecStrideGather()`, `VecStrideScatter()`, `VecStrideMin()` 174 @*/ 175 PetscErrorCode VecStrideMax(Vec v, PetscInt start, PetscInt *idex, PetscReal *nrm) { 176 PetscInt i, n, bs, id = -1; 177 const PetscScalar *x; 178 PetscReal max = PETSC_MIN_REAL; 179 180 PetscFunctionBegin; 181 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 182 PetscValidRealPointer(nrm, 4); 183 PetscCall(VecGetLocalSize(v, &n)); 184 PetscCall(VecGetBlockSize(v, &bs)); 185 PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative start %" PetscInt_FMT, start); 186 PetscCheck(start < bs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Start of stride subvector (%" PetscInt_FMT ") is too large for stride\n Have you set the vector blocksize (%" PetscInt_FMT ") correctly with VecSetBlockSize()?", start, bs); 187 PetscCall(VecGetArrayRead(v, &x)); 188 for (i = start; i < n; i += bs) { 189 if (PetscRealPart(x[i]) > max) { 190 max = PetscRealPart(x[i]); 191 id = i; 192 } 193 } 194 PetscCall(VecRestoreArrayRead(v, &x)); 195 #if defined(PETSC_HAVE_MPIUNI) 196 *nrm = max; 197 if (idex) *idex = id; 198 #else 199 if (!idex) { 200 PetscCall(MPIU_Allreduce(&max, nrm, 1, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)v))); 201 } else { 202 struct { 203 PetscReal v; 204 PetscInt i; 205 } in, out; 206 PetscInt rstart; 207 208 PetscCall(VecGetOwnershipRange(v, &rstart, NULL)); 209 in.v = max; 210 in.i = rstart + id; 211 PetscCall(MPIU_Allreduce(&in, &out, 1, MPIU_REAL_INT, MPIU_MAXLOC, PetscObjectComm((PetscObject)v))); 212 *nrm = out.v; 213 *idex = out.i; 214 } 215 #endif 216 PetscFunctionReturn(0); 217 } 218 219 /*@ 220 VecStrideMin - Computes the minimum of subvector of a vector defined 221 by a starting point and a stride and optionally its location. 222 223 Collective on Vec 224 225 Input Parameters: 226 + v - the vector 227 - start - starting point of the subvector (defined by a stride) 228 229 Output Parameters: 230 + idex - the location where the minimum occurred. (pass NULL if not required) 231 - nrm - the minimum value in the subvector 232 233 Level: advanced 234 235 Notes: 236 One must call VecSetBlockSize() before this routine to set the stride 237 information, or use a vector created from a multicomponent DMDA. 238 239 If xa is the array representing the vector x, then this computes the min 240 of the array (xa[start],xa[start+stride],xa[start+2*stride], ....) 241 242 This is useful for computing, say the minimum of the pressure variable when 243 the pressure is stored (interlaced) with other variables, e.g., density, etc. 244 This will only work if the desire subvector is a stride subvector. 245 246 .seealso: `VecMin()`, `VecStrideNorm()`, `VecStrideGather()`, `VecStrideScatter()`, `VecStrideMax()` 247 @*/ 248 PetscErrorCode VecStrideMin(Vec v, PetscInt start, PetscInt *idex, PetscReal *nrm) { 249 PetscInt i, n, bs, id = -1; 250 const PetscScalar *x; 251 PetscReal min = PETSC_MAX_REAL; 252 253 PetscFunctionBegin; 254 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 255 PetscValidRealPointer(nrm, 4); 256 PetscCall(VecGetLocalSize(v, &n)); 257 PetscCall(VecGetBlockSize(v, &bs)); 258 PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative start %" PetscInt_FMT, start); 259 PetscCheck(start < bs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Start of stride subvector (%" PetscInt_FMT ") is too large for stride\nHave you set the vector blocksize (%" PetscInt_FMT ") correctly with VecSetBlockSize()?", start, bs); 260 PetscCall(VecGetArrayRead(v, &x)); 261 for (i = start; i < n; i += bs) { 262 if (PetscRealPart(x[i]) < min) { 263 min = PetscRealPart(x[i]); 264 id = i; 265 } 266 } 267 PetscCall(VecRestoreArrayRead(v, &x)); 268 #if defined(PETSC_HAVE_MPIUNI) 269 *nrm = min; 270 if (idex) *idex = id; 271 #else 272 if (!idex) { 273 PetscCall(MPIU_Allreduce(&min, nrm, 1, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)v))); 274 } else { 275 struct { 276 PetscReal v; 277 PetscInt i; 278 } in, out; 279 PetscInt rstart; 280 281 PetscCall(VecGetOwnershipRange(v, &rstart, NULL)); 282 in.v = min; 283 in.i = rstart + id; 284 PetscCall(MPIU_Allreduce(&in, &out, 1, MPIU_REAL_INT, MPIU_MINLOC, PetscObjectComm((PetscObject)v))); 285 *nrm = out.v; 286 *idex = out.i; 287 } 288 #endif 289 PetscFunctionReturn(0); 290 } 291 292 /*@ 293 VecStrideSum - Computes the sum of subvector of a vector defined 294 by a starting point and a stride. 295 296 Collective on v 297 298 Input Parameters: 299 + v - the vector 300 - start - starting point of the subvector (defined by a stride) 301 302 Output Parameter: 303 . sum - the sum 304 305 Notes: 306 One must call `VecSetBlockSize()` before this routine to set the stride 307 information, or use a vector created from a multicomponent `DMDA`. 308 309 If x is the array representing the vector x then this computes the sum 310 of the array (x[start],x[start+stride],x[start+2*stride], ....) 311 312 Level: advanced 313 314 .seealso: `VecSum()`, `VecStrideGather()`, `VecStrideScatter()`, `VecStrideMin()`, `VecStrideMax()` 315 @*/ 316 PetscErrorCode VecStrideSum(Vec v, PetscInt start, PetscScalar *sum) { 317 PetscInt i, n, bs; 318 const PetscScalar *x; 319 PetscScalar local_sum = 0.0; 320 321 PetscFunctionBegin; 322 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 323 PetscValidScalarPointer(sum, 3); 324 PetscCall(VecGetLocalSize(v, &n)); 325 PetscCall(VecGetBlockSize(v, &bs)); 326 PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative start %" PetscInt_FMT, start); 327 PetscCheck(start < bs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Start of stride subvector (%" PetscInt_FMT ") is too large for stride\n Have you set the vector blocksize (%" PetscInt_FMT ") correctly with VecSetBlockSize()?", start, bs); 328 PetscCall(VecGetArrayRead(v, &x)); 329 for (i = start; i < n; i += bs) local_sum += x[i]; 330 PetscCall(MPIU_Allreduce(&local_sum, sum, 1, MPIU_SCALAR, MPIU_SUM, PetscObjectComm((PetscObject)v))); 331 PetscCall(VecRestoreArrayRead(v, &x)); 332 PetscFunctionReturn(0); 333 } 334 335 /*@ 336 VecStrideScaleAll - Scales the subvectors of a vector defined 337 by a starting point and a stride. 338 339 Logically Collective on Vec 340 341 Input Parameters: 342 + v - the vector 343 - scales - values to multiply each subvector entry by 344 345 Notes: 346 One must call VecSetBlockSize() before this routine to set the stride 347 information, or use a vector created from a multicomponent DMDA. 348 349 The dimension of scales must be the same as the vector block size 350 351 Level: advanced 352 353 .seealso: `VecNorm()`, `VecStrideScale()`, `VecScale()`, `VecStrideGather()`, `VecStrideScatter()`, `VecStrideMin()`, `VecStrideMax()` 354 @*/ 355 PetscErrorCode VecStrideScaleAll(Vec v, const PetscScalar *scales) { 356 PetscInt i, j, n, bs; 357 PetscScalar *x; 358 359 PetscFunctionBegin; 360 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 361 PetscValidScalarPointer(scales, 2); 362 PetscCall(VecGetLocalSize(v, &n)); 363 PetscCall(VecGetBlockSize(v, &bs)); 364 PetscCall(VecGetArray(v, &x)); 365 /* need to provide optimized code for each bs */ 366 for (i = 0; i < n; i += bs) { 367 for (j = 0; j < bs; j++) x[i + j] *= scales[j]; 368 } 369 PetscCall(VecRestoreArray(v, &x)); 370 PetscFunctionReturn(0); 371 } 372 373 /*@ 374 VecStrideNormAll - Computes the norms of subvectors of a vector defined 375 by a starting point and a stride. 376 377 Collective on Vec 378 379 Input Parameters: 380 + v - the vector 381 - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY 382 383 Output Parameter: 384 . nrm - the norms 385 386 Notes: 387 One must call VecSetBlockSize() before this routine to set the stride 388 information, or use a vector created from a multicomponent DMDA. 389 390 If x is the array representing the vector x then this computes the norm 391 of the array (x[start],x[start+stride],x[start+2*stride], ....) for each start < stride 392 393 The dimension of nrm must be the same as the vector block size 394 395 This will only work if the desire subvector is a stride subvector 396 397 Level: advanced 398 399 .seealso: `VecNorm()`, `VecStrideGather()`, `VecStrideScatter()`, `VecStrideMin()`, `VecStrideMax()` 400 @*/ 401 PetscErrorCode VecStrideNormAll(Vec v, NormType ntype, PetscReal nrm[]) { 402 PetscInt i, j, n, bs; 403 const PetscScalar *x; 404 PetscReal tnorm[128]; 405 MPI_Comm comm; 406 407 PetscFunctionBegin; 408 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 409 PetscValidLogicalCollectiveEnum(v, ntype, 2); 410 PetscValidRealPointer(nrm, 3); 411 PetscCall(VecGetLocalSize(v, &n)); 412 PetscCall(VecGetArrayRead(v, &x)); 413 PetscCall(PetscObjectGetComm((PetscObject)v, &comm)); 414 415 PetscCall(VecGetBlockSize(v, &bs)); 416 PetscCheck(bs <= 128, comm, PETSC_ERR_SUP, "Currently supports only blocksize up to 128"); 417 418 if (ntype == NORM_2) { 419 PetscScalar sum[128]; 420 for (j = 0; j < bs; j++) sum[j] = 0.0; 421 for (i = 0; i < n; i += bs) { 422 for (j = 0; j < bs; j++) sum[j] += x[i + j] * (PetscConj(x[i + j])); 423 } 424 for (j = 0; j < bs; j++) tnorm[j] = PetscRealPart(sum[j]); 425 426 PetscCall(MPIU_Allreduce(tnorm, nrm, bs, MPIU_REAL, MPIU_SUM, comm)); 427 for (j = 0; j < bs; j++) nrm[j] = PetscSqrtReal(nrm[j]); 428 } else if (ntype == NORM_1) { 429 for (j = 0; j < bs; j++) tnorm[j] = 0.0; 430 431 for (i = 0; i < n; i += bs) { 432 for (j = 0; j < bs; j++) tnorm[j] += PetscAbsScalar(x[i + j]); 433 } 434 435 PetscCall(MPIU_Allreduce(tnorm, nrm, bs, MPIU_REAL, MPIU_SUM, comm)); 436 } else if (ntype == NORM_INFINITY) { 437 PetscReal tmp; 438 for (j = 0; j < bs; j++) tnorm[j] = 0.0; 439 440 for (i = 0; i < n; i += bs) { 441 for (j = 0; j < bs; j++) { 442 if ((tmp = PetscAbsScalar(x[i + j])) > tnorm[j]) tnorm[j] = tmp; 443 /* check special case of tmp == NaN */ 444 if (tmp != tmp) { 445 tnorm[j] = tmp; 446 break; 447 } 448 } 449 } 450 PetscCall(MPIU_Allreduce(tnorm, nrm, bs, MPIU_REAL, MPIU_MAX, comm)); 451 } else SETERRQ(comm, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown norm type"); 452 PetscCall(VecRestoreArrayRead(v, &x)); 453 PetscFunctionReturn(0); 454 } 455 456 /*@ 457 VecStrideMaxAll - Computes the maximums of subvectors of a vector defined 458 by a starting point and a stride and optionally its location. 459 460 Collective on Vec 461 462 Input Parameter: 463 . v - the vector 464 465 Output Parameters: 466 + index - the location where the maximum occurred (not supported, pass NULL, 467 if you need this, send mail to petsc-maint@mcs.anl.gov to request it) 468 - nrm - the maximum values of each subvector 469 470 Notes: 471 One must call VecSetBlockSize() before this routine to set the stride 472 information, or use a vector created from a multicomponent DMDA. 473 474 The dimension of nrm must be the same as the vector block size 475 476 Level: advanced 477 478 .seealso: `VecMax()`, `VecStrideNorm()`, `VecStrideGather()`, `VecStrideScatter()`, `VecStrideMin()` 479 @*/ 480 PetscErrorCode VecStrideMaxAll(Vec v, PetscInt idex[], PetscReal nrm[]) { 481 PetscInt i, j, n, bs; 482 const PetscScalar *x; 483 PetscReal max[128], tmp; 484 MPI_Comm comm; 485 486 PetscFunctionBegin; 487 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 488 PetscValidRealPointer(nrm, 3); 489 PetscCheck(!idex, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it"); 490 PetscCall(VecGetLocalSize(v, &n)); 491 PetscCall(VecGetArrayRead(v, &x)); 492 PetscCall(PetscObjectGetComm((PetscObject)v, &comm)); 493 494 PetscCall(VecGetBlockSize(v, &bs)); 495 PetscCheck(bs <= 128, comm, PETSC_ERR_SUP, "Currently supports only blocksize up to 128"); 496 497 if (!n) { 498 for (j = 0; j < bs; j++) max[j] = PETSC_MIN_REAL; 499 } else { 500 for (j = 0; j < bs; j++) max[j] = PetscRealPart(x[j]); 501 502 for (i = bs; i < n; i += bs) { 503 for (j = 0; j < bs; j++) { 504 if ((tmp = PetscRealPart(x[i + j])) > max[j]) max[j] = tmp; 505 } 506 } 507 } 508 PetscCall(MPIU_Allreduce(max, nrm, bs, MPIU_REAL, MPIU_MAX, comm)); 509 510 PetscCall(VecRestoreArrayRead(v, &x)); 511 PetscFunctionReturn(0); 512 } 513 514 /*@ 515 VecStrideMinAll - Computes the minimum of subvector of a vector defined 516 by a starting point and a stride and optionally its location. 517 518 Collective on Vec 519 520 Input Parameter: 521 . v - the vector 522 523 Output Parameters: 524 + idex - the location where the minimum occurred (not supported, pass NULL, 525 if you need this, send mail to petsc-maint@mcs.anl.gov to request it) 526 - nrm - the minimums of each subvector 527 528 Level: advanced 529 530 Notes: 531 One must call VecSetBlockSize() before this routine to set the stride 532 information, or use a vector created from a multicomponent DMDA. 533 534 The dimension of nrm must be the same as the vector block size 535 536 .seealso: `VecMin()`, `VecStrideNorm()`, `VecStrideGather()`, `VecStrideScatter()`, `VecStrideMax()` 537 @*/ 538 PetscErrorCode VecStrideMinAll(Vec v, PetscInt idex[], PetscReal nrm[]) { 539 PetscInt i, n, bs, j; 540 const PetscScalar *x; 541 PetscReal min[128], tmp; 542 MPI_Comm comm; 543 544 PetscFunctionBegin; 545 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 546 PetscValidRealPointer(nrm, 3); 547 PetscCheck(!idex, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it"); 548 PetscCall(VecGetLocalSize(v, &n)); 549 PetscCall(VecGetArrayRead(v, &x)); 550 PetscCall(PetscObjectGetComm((PetscObject)v, &comm)); 551 552 PetscCall(VecGetBlockSize(v, &bs)); 553 PetscCheck(bs <= 128, comm, PETSC_ERR_SUP, "Currently supports only blocksize up to 128"); 554 555 if (!n) { 556 for (j = 0; j < bs; j++) min[j] = PETSC_MAX_REAL; 557 } else { 558 for (j = 0; j < bs; j++) min[j] = PetscRealPart(x[j]); 559 560 for (i = bs; i < n; i += bs) { 561 for (j = 0; j < bs; j++) { 562 if ((tmp = PetscRealPart(x[i + j])) < min[j]) min[j] = tmp; 563 } 564 } 565 } 566 PetscCall(MPIU_Allreduce(min, nrm, bs, MPIU_REAL, MPIU_MIN, comm)); 567 568 PetscCall(VecRestoreArrayRead(v, &x)); 569 PetscFunctionReturn(0); 570 } 571 572 /*@ 573 VecStrideSumAll - Computes the sums of subvectors of a vector defined by a stride. 574 575 Collective on Vec 576 577 Input Parameter: 578 . v - the vector 579 580 Output Parameter: 581 . sums - the sums 582 583 Notes: 584 One must call `VecSetBlockSize()` before this routine to set the stride 585 information, or use a vector created from a multicomponent `DMDA`. 586 587 If x is the array representing the vector x then this computes the sum 588 of the array (x[start],x[start+stride],x[start+2*stride], ....) for each start < stride 589 590 Level: advanced 591 592 .seealso: `VecSum()`, `VecStrideGather()`, `VecStrideScatter()`, `VecStrideMin()`, `VecStrideMax()` 593 @*/ 594 PetscErrorCode VecStrideSumAll(Vec v, PetscScalar sums[]) { 595 PetscInt i, j, n, bs; 596 const PetscScalar *x; 597 PetscScalar local_sums[128]; 598 MPI_Comm comm; 599 600 PetscFunctionBegin; 601 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 602 PetscValidScalarPointer(sums, 2); 603 PetscCall(VecGetLocalSize(v, &n)); 604 PetscCall(VecGetArrayRead(v, &x)); 605 PetscCall(PetscObjectGetComm((PetscObject)v, &comm)); 606 607 PetscCall(VecGetBlockSize(v, &bs)); 608 PetscCheck(bs <= 128, comm, PETSC_ERR_SUP, "Currently supports only blocksize up to 128"); 609 610 for (j = 0; j < bs; j++) local_sums[j] = 0.0; 611 for (i = 0; i < n; i += bs) { 612 for (j = 0; j < bs; j++) local_sums[j] += x[i + j]; 613 } 614 PetscCall(MPIU_Allreduce(local_sums, sums, bs, MPIU_SCALAR, MPIU_SUM, comm)); 615 616 PetscCall(VecRestoreArrayRead(v, &x)); 617 PetscFunctionReturn(0); 618 } 619 620 /*----------------------------------------------------------------------------------------------*/ 621 /*@ 622 VecStrideGatherAll - Gathers all the single components from a multi-component vector into 623 separate vectors. 624 625 Collective on Vec 626 627 Input Parameters: 628 + v - the vector 629 - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES 630 631 Output Parameter: 632 . s - the location where the subvectors are stored 633 634 Notes: 635 One must call VecSetBlockSize() before this routine to set the stride 636 information, or use a vector created from a multicomponent DMDA. 637 638 If x is the array representing the vector x then this gathers 639 the arrays (x[start],x[start+stride],x[start+2*stride], ....) 640 for start=0,1,2,...bs-1 641 642 The parallel layout of the vector and the subvector must be the same; 643 i.e., nlocal of v = stride*(nlocal of s) 644 645 Not optimized; could be easily 646 647 Level: advanced 648 649 .seealso: `VecStrideNorm()`, `VecStrideScatter()`, `VecStrideMin()`, `VecStrideMax()`, `VecStrideGather()`, 650 `VecStrideScatterAll()` 651 @*/ 652 PetscErrorCode VecStrideGatherAll(Vec v, Vec s[], InsertMode addv) { 653 PetscInt i, n, n2, bs, j, k, *bss = NULL, nv, jj, nvc; 654 PetscScalar **y; 655 const PetscScalar *x; 656 657 PetscFunctionBegin; 658 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 659 PetscValidPointer(s, 2); 660 PetscValidHeaderSpecific(*s, VEC_CLASSID, 2); 661 PetscCall(VecGetLocalSize(v, &n)); 662 PetscCall(VecGetLocalSize(s[0], &n2)); 663 PetscCall(VecGetArrayRead(v, &x)); 664 PetscCall(VecGetBlockSize(v, &bs)); 665 PetscCheck(bs > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Input vector does not have a valid blocksize set"); 666 667 PetscCall(PetscMalloc2(bs, &y, bs, &bss)); 668 nv = 0; 669 nvc = 0; 670 for (i = 0; i < bs; i++) { 671 PetscCall(VecGetBlockSize(s[i], &bss[i])); 672 if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */ 673 PetscCall(VecGetArray(s[i], &y[i])); 674 nvc += bss[i]; 675 nv++; 676 PetscCheck(nvc <= bs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of subvectors in subvectors > number of vectors in main vector"); 677 if (nvc == bs) break; 678 } 679 680 n = n / bs; 681 682 jj = 0; 683 if (addv == INSERT_VALUES) { 684 for (j = 0; j < nv; j++) { 685 for (k = 0; k < bss[j]; k++) { 686 for (i = 0; i < n; i++) y[j][i * bss[j] + k] = x[bs * i + jj + k]; 687 } 688 jj += bss[j]; 689 } 690 } else if (addv == ADD_VALUES) { 691 for (j = 0; j < nv; j++) { 692 for (k = 0; k < bss[j]; k++) { 693 for (i = 0; i < n; i++) y[j][i * bss[j] + k] += x[bs * i + jj + k]; 694 } 695 jj += bss[j]; 696 } 697 #if !defined(PETSC_USE_COMPLEX) 698 } else if (addv == MAX_VALUES) { 699 for (j = 0; j < nv; j++) { 700 for (k = 0; k < bss[j]; k++) { 701 for (i = 0; i < n; i++) y[j][i * bss[j] + k] = PetscMax(y[j][i * bss[j] + k], x[bs * i + jj + k]); 702 } 703 jj += bss[j]; 704 } 705 #endif 706 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown insert type"); 707 708 PetscCall(VecRestoreArrayRead(v, &x)); 709 for (i = 0; i < nv; i++) PetscCall(VecRestoreArray(s[i], &y[i])); 710 711 PetscCall(PetscFree2(y, bss)); 712 PetscFunctionReturn(0); 713 } 714 715 /*@ 716 VecStrideScatterAll - Scatters all the single components from separate vectors into 717 a multi-component vector. 718 719 Collective on Vec 720 721 Input Parameters: 722 + s - the location where the subvectors are stored 723 - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES 724 725 Output Parameter: 726 . v - the multicomponent vector 727 728 Notes: 729 One must call VecSetBlockSize() before this routine to set the stride 730 information, or use a vector created from a multicomponent DMDA. 731 732 The parallel layout of the vector and the subvector must be the same; 733 i.e., nlocal of v = stride*(nlocal of s) 734 735 Not optimized; could be easily 736 737 Level: advanced 738 739 .seealso: `VecStrideNorm()`, `VecStrideScatter()`, `VecStrideMin()`, `VecStrideMax()`, `VecStrideGather()`, 740 `VecStrideScatterAll()` 741 @*/ 742 PetscErrorCode VecStrideScatterAll(Vec s[], Vec v, InsertMode addv) { 743 PetscInt i, n, n2, bs, j, jj, k, *bss = NULL, nv, nvc; 744 PetscScalar *x; 745 PetscScalar const **y; 746 747 PetscFunctionBegin; 748 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 749 PetscValidPointer(s, 1); 750 PetscValidHeaderSpecific(*s, VEC_CLASSID, 1); 751 PetscCall(VecGetLocalSize(v, &n)); 752 PetscCall(VecGetLocalSize(s[0], &n2)); 753 PetscCall(VecGetArray(v, &x)); 754 PetscCall(VecGetBlockSize(v, &bs)); 755 PetscCheck(bs > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Input vector does not have a valid blocksize set"); 756 757 PetscCall(PetscMalloc2(bs, (PetscScalar ***)&y, bs, &bss)); 758 nv = 0; 759 nvc = 0; 760 for (i = 0; i < bs; i++) { 761 PetscCall(VecGetBlockSize(s[i], &bss[i])); 762 if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */ 763 PetscCall(VecGetArrayRead(s[i], &y[i])); 764 nvc += bss[i]; 765 nv++; 766 PetscCheck(nvc <= bs, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of subvectors in subvectors > number of vectors in main vector"); 767 if (nvc == bs) break; 768 } 769 770 n = n / bs; 771 772 jj = 0; 773 if (addv == INSERT_VALUES) { 774 for (j = 0; j < nv; j++) { 775 for (k = 0; k < bss[j]; k++) { 776 for (i = 0; i < n; i++) x[bs * i + jj + k] = y[j][i * bss[j] + k]; 777 } 778 jj += bss[j]; 779 } 780 } else if (addv == ADD_VALUES) { 781 for (j = 0; j < nv; j++) { 782 for (k = 0; k < bss[j]; k++) { 783 for (i = 0; i < n; i++) x[bs * i + jj + k] += y[j][i * bss[j] + k]; 784 } 785 jj += bss[j]; 786 } 787 #if !defined(PETSC_USE_COMPLEX) 788 } else if (addv == MAX_VALUES) { 789 for (j = 0; j < nv; j++) { 790 for (k = 0; k < bss[j]; k++) { 791 for (i = 0; i < n; i++) x[bs * i + jj + k] = PetscMax(x[bs * i + jj + k], y[j][i * bss[j] + k]); 792 } 793 jj += bss[j]; 794 } 795 #endif 796 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown insert type"); 797 798 PetscCall(VecRestoreArray(v, &x)); 799 for (i = 0; i < nv; i++) PetscCall(VecRestoreArrayRead(s[i], &y[i])); 800 PetscCall(PetscFree2(*(PetscScalar ***)&y, bss)); 801 PetscFunctionReturn(0); 802 } 803 804 /*@ 805 VecStrideGather - Gathers a single component from a multi-component vector into 806 another vector. 807 808 Collective on Vec 809 810 Input Parameters: 811 + v - the vector 812 . start - starting point of the subvector (defined by a stride) 813 - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES 814 815 Output Parameter: 816 . s - the location where the subvector is stored 817 818 Notes: 819 One must call VecSetBlockSize() before this routine to set the stride 820 information, or use a vector created from a multicomponent DMDA. 821 822 If x is the array representing the vector x then this gathers 823 the array (x[start],x[start+stride],x[start+2*stride], ....) 824 825 The parallel layout of the vector and the subvector must be the same; 826 i.e., nlocal of v = stride*(nlocal of s) 827 828 Not optimized; could be easily 829 830 Level: advanced 831 832 .seealso: `VecStrideNorm()`, `VecStrideScatter()`, `VecStrideMin()`, `VecStrideMax()`, `VecStrideGatherAll()`, 833 `VecStrideScatterAll()` 834 @*/ 835 PetscErrorCode VecStrideGather(Vec v, PetscInt start, Vec s, InsertMode addv) { 836 PetscFunctionBegin; 837 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 838 PetscValidHeaderSpecific(s, VEC_CLASSID, 3); 839 PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative start %" PetscInt_FMT, start); 840 PetscCheck(start < v->map->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Start of stride subvector (%" PetscInt_FMT ") is too large for stride\n Have you set the vector blocksize (%" PetscInt_FMT ") correctly with VecSetBlockSize()?", start, 841 v->map->bs); 842 PetscUseTypeMethod(v, stridegather, start, s, addv); 843 PetscFunctionReturn(0); 844 } 845 846 /*@ 847 VecStrideScatter - Scatters a single component from a vector into a multi-component vector. 848 849 Collective on Vec 850 851 Input Parameters: 852 + s - the single-component vector 853 . start - starting point of the subvector (defined by a stride) 854 - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES 855 856 Output Parameter: 857 . v - the location where the subvector is scattered (the multi-component vector) 858 859 Notes: 860 One must call VecSetBlockSize() on the multi-component vector before this 861 routine to set the stride information, or use a vector created from a multicomponent DMDA. 862 863 The parallel layout of the vector and the subvector must be the same; 864 i.e., nlocal of v = stride*(nlocal of s) 865 866 Not optimized; could be easily 867 868 Level: advanced 869 870 .seealso: `VecStrideNorm()`, `VecStrideGather()`, `VecStrideMin()`, `VecStrideMax()`, `VecStrideGatherAll()`, 871 `VecStrideScatterAll()`, `VecStrideSubSetScatter()`, `VecStrideSubSetGather()` 872 @*/ 873 PetscErrorCode VecStrideScatter(Vec s, PetscInt start, Vec v, InsertMode addv) { 874 PetscFunctionBegin; 875 PetscValidHeaderSpecific(s, VEC_CLASSID, 1); 876 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 877 PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Negative start %" PetscInt_FMT, start); 878 PetscCheck(start < v->map->bs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Start of stride subvector (%" PetscInt_FMT ") is too large for stride\n Have you set the vector blocksize (%" PetscInt_FMT ") correctly with VecSetBlockSize()?", start, 879 v->map->bs); 880 PetscCall((*v->ops->stridescatter)(s, start, v, addv)); 881 PetscFunctionReturn(0); 882 } 883 884 /*@ 885 VecStrideSubSetGather - Gathers a subset of components from a multi-component vector into 886 another vector. 887 888 Collective on Vec 889 890 Input Parameters: 891 + v - the vector 892 . nidx - the number of indices 893 . idxv - the indices of the components 0 <= idxv[0] ...idxv[nidx-1] < bs(v), they need not be sorted 894 . idxs - the indices of the components 0 <= idxs[0] ...idxs[nidx-1] < bs(s), they need not be sorted, may be null if nidx == bs(s) or is PETSC_DETERMINE 895 - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES 896 897 Output Parameter: 898 . s - the location where the subvector is stored 899 900 Notes: 901 One must call VecSetBlockSize() on both vectors before this routine to set the stride 902 information, or use a vector created from a multicomponent DMDA. 903 904 The parallel layout of the vector and the subvector must be the same; 905 906 Not optimized; could be easily 907 908 Level: advanced 909 910 .seealso: `VecStrideNorm()`, `VecStrideScatter()`, `VecStrideGather()`, `VecStrideSubSetScatter()`, `VecStrideMin()`, `VecStrideMax()`, `VecStrideGatherAll()`, 911 `VecStrideScatterAll()` 912 @*/ 913 PetscErrorCode VecStrideSubSetGather(Vec v, PetscInt nidx, const PetscInt idxv[], const PetscInt idxs[], Vec s, InsertMode addv) { 914 PetscFunctionBegin; 915 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 916 PetscValidHeaderSpecific(s, VEC_CLASSID, 5); 917 if (nidx == PETSC_DETERMINE) nidx = s->map->bs; 918 PetscUseTypeMethod(v, stridesubsetgather, nidx, idxv, idxs, s, addv); 919 PetscFunctionReturn(0); 920 } 921 922 /*@ 923 VecStrideSubSetScatter - Scatters components from a vector into a subset of components of a multi-component vector. 924 925 Collective on Vec 926 927 Input Parameters: 928 + s - the smaller-component vector 929 . nidx - the number of indices in idx 930 . idxs - the indices of the components in the smaller-component vector, 0 <= idxs[0] ...idxs[nidx-1] < bs(s) they need not be sorted, may be null if nidx == bs(s) or is PETSC_DETERMINE 931 . idxv - the indices of the components in the larger-component vector, 0 <= idx[0] ...idx[nidx-1] < bs(v) they need not be sorted 932 - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES 933 934 Output Parameter: 935 . v - the location where the subvector is into scattered (the multi-component vector) 936 937 Notes: 938 One must call VecSetBlockSize() on the vectors before this 939 routine to set the stride information, or use a vector created from a multicomponent DMDA. 940 941 The parallel layout of the vector and the subvector must be the same; 942 943 Not optimized; could be easily 944 945 Level: advanced 946 947 .seealso: `VecStrideNorm()`, `VecStrideGather()`, `VecStrideGather()`, `VecStrideSubSetGather()`, `VecStrideMin()`, `VecStrideMax()`, `VecStrideGatherAll()`, 948 `VecStrideScatterAll()` 949 @*/ 950 PetscErrorCode VecStrideSubSetScatter(Vec s, PetscInt nidx, const PetscInt idxs[], const PetscInt idxv[], Vec v, InsertMode addv) { 951 PetscFunctionBegin; 952 PetscValidHeaderSpecific(s, VEC_CLASSID, 1); 953 PetscValidHeaderSpecific(v, VEC_CLASSID, 5); 954 if (nidx == PETSC_DETERMINE) nidx = s->map->bs; 955 PetscCall((*v->ops->stridesubsetscatter)(s, nidx, idxs, idxv, v, addv)); 956 PetscFunctionReturn(0); 957 } 958 959 PetscErrorCode VecStrideGather_Default(Vec v, PetscInt start, Vec s, InsertMode addv) { 960 PetscInt i, n, bs, ns; 961 const PetscScalar *x; 962 PetscScalar *y; 963 964 PetscFunctionBegin; 965 PetscCall(VecGetLocalSize(v, &n)); 966 PetscCall(VecGetLocalSize(s, &ns)); 967 PetscCall(VecGetArrayRead(v, &x)); 968 PetscCall(VecGetArray(s, &y)); 969 970 bs = v->map->bs; 971 PetscCheck(n == ns * bs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Subvector length * blocksize %" PetscInt_FMT " not correct for gather from original vector %" PetscInt_FMT, ns * bs, n); 972 x += start; 973 n = n / bs; 974 975 if (addv == INSERT_VALUES) { 976 for (i = 0; i < n; i++) y[i] = x[bs * i]; 977 } else if (addv == ADD_VALUES) { 978 for (i = 0; i < n; i++) y[i] += x[bs * i]; 979 #if !defined(PETSC_USE_COMPLEX) 980 } else if (addv == MAX_VALUES) { 981 for (i = 0; i < n; i++) y[i] = PetscMax(y[i], x[bs * i]); 982 #endif 983 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown insert type"); 984 985 PetscCall(VecRestoreArrayRead(v, &x)); 986 PetscCall(VecRestoreArray(s, &y)); 987 PetscFunctionReturn(0); 988 } 989 990 PetscErrorCode VecStrideScatter_Default(Vec s, PetscInt start, Vec v, InsertMode addv) { 991 PetscInt i, n, bs, ns; 992 PetscScalar *x; 993 const PetscScalar *y; 994 995 PetscFunctionBegin; 996 PetscCall(VecGetLocalSize(v, &n)); 997 PetscCall(VecGetLocalSize(s, &ns)); 998 PetscCall(VecGetArray(v, &x)); 999 PetscCall(VecGetArrayRead(s, &y)); 1000 1001 bs = v->map->bs; 1002 PetscCheck(n == ns * bs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Subvector length * blocksize %" PetscInt_FMT " not correct for scatter to multicomponent vector %" PetscInt_FMT, ns * bs, n); 1003 x += start; 1004 n = n / bs; 1005 1006 if (addv == INSERT_VALUES) { 1007 for (i = 0; i < n; i++) x[bs * i] = y[i]; 1008 } else if (addv == ADD_VALUES) { 1009 for (i = 0; i < n; i++) x[bs * i] += y[i]; 1010 #if !defined(PETSC_USE_COMPLEX) 1011 } else if (addv == MAX_VALUES) { 1012 for (i = 0; i < n; i++) x[bs * i] = PetscMax(y[i], x[bs * i]); 1013 #endif 1014 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown insert type"); 1015 1016 PetscCall(VecRestoreArray(v, &x)); 1017 PetscCall(VecRestoreArrayRead(s, &y)); 1018 PetscFunctionReturn(0); 1019 } 1020 1021 PetscErrorCode VecStrideSubSetGather_Default(Vec v, PetscInt nidx, const PetscInt idxv[], const PetscInt idxs[], Vec s, InsertMode addv) { 1022 PetscInt i, j, n, bs, bss, ns; 1023 const PetscScalar *x; 1024 PetscScalar *y; 1025 1026 PetscFunctionBegin; 1027 PetscCall(VecGetLocalSize(v, &n)); 1028 PetscCall(VecGetLocalSize(s, &ns)); 1029 PetscCall(VecGetArrayRead(v, &x)); 1030 PetscCall(VecGetArray(s, &y)); 1031 1032 bs = v->map->bs; 1033 bss = s->map->bs; 1034 n = n / bs; 1035 1036 if (PetscDefined(USE_DEBUG)) { 1037 PetscCheck(n == ns / bss, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible layout of vectors"); 1038 for (j = 0; j < nidx; j++) { 1039 PetscCheck(idxv[j] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "idx[%" PetscInt_FMT "] %" PetscInt_FMT " is negative", j, idxv[j]); 1040 PetscCheck(idxv[j] < bs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "idx[%" PetscInt_FMT "] %" PetscInt_FMT " is greater than or equal to vector blocksize %" PetscInt_FMT, j, idxv[j], bs); 1041 } 1042 PetscCheck(idxs || bss == nidx, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must provide idxs when not gathering into all locations"); 1043 } 1044 1045 if (addv == INSERT_VALUES) { 1046 if (!idxs) { 1047 for (i = 0; i < n; i++) { 1048 for (j = 0; j < bss; j++) y[bss * i + j] = x[bs * i + idxv[j]]; 1049 } 1050 } else { 1051 for (i = 0; i < n; i++) { 1052 for (j = 0; j < bss; j++) y[bss * i + idxs[j]] = x[bs * i + idxv[j]]; 1053 } 1054 } 1055 } else if (addv == ADD_VALUES) { 1056 if (!idxs) { 1057 for (i = 0; i < n; i++) { 1058 for (j = 0; j < bss; j++) y[bss * i + j] += x[bs * i + idxv[j]]; 1059 } 1060 } else { 1061 for (i = 0; i < n; i++) { 1062 for (j = 0; j < bss; j++) y[bss * i + idxs[j]] += x[bs * i + idxv[j]]; 1063 } 1064 } 1065 #if !defined(PETSC_USE_COMPLEX) 1066 } else if (addv == MAX_VALUES) { 1067 if (!idxs) { 1068 for (i = 0; i < n; i++) { 1069 for (j = 0; j < bss; j++) y[bss * i + j] = PetscMax(y[bss * i + j], x[bs * i + idxv[j]]); 1070 } 1071 } else { 1072 for (i = 0; i < n; i++) { 1073 for (j = 0; j < bss; j++) y[bss * i + idxs[j]] = PetscMax(y[bss * i + idxs[j]], x[bs * i + idxv[j]]); 1074 } 1075 } 1076 #endif 1077 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown insert type"); 1078 1079 PetscCall(VecRestoreArrayRead(v, &x)); 1080 PetscCall(VecRestoreArray(s, &y)); 1081 PetscFunctionReturn(0); 1082 } 1083 1084 PetscErrorCode VecStrideSubSetScatter_Default(Vec s, PetscInt nidx, const PetscInt idxs[], const PetscInt idxv[], Vec v, InsertMode addv) { 1085 PetscInt j, i, n, bs, ns, bss; 1086 PetscScalar *x; 1087 const PetscScalar *y; 1088 1089 PetscFunctionBegin; 1090 PetscCall(VecGetLocalSize(v, &n)); 1091 PetscCall(VecGetLocalSize(s, &ns)); 1092 PetscCall(VecGetArray(v, &x)); 1093 PetscCall(VecGetArrayRead(s, &y)); 1094 1095 bs = v->map->bs; 1096 bss = s->map->bs; 1097 n = n / bs; 1098 1099 if (PetscDefined(USE_DEBUG)) { 1100 PetscCheck(n == ns / bss, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Incompatible layout of vectors"); 1101 for (j = 0; j < bss; j++) { 1102 if (idxs) { 1103 PetscCheck(idxs[j] >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "idx[%" PetscInt_FMT "] %" PetscInt_FMT " is negative", j, idxs[j]); 1104 PetscCheck(idxs[j] < bs, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "idx[%" PetscInt_FMT "] %" PetscInt_FMT " is greater than or equal to vector blocksize %" PetscInt_FMT, j, idxs[j], bs); 1105 } 1106 } 1107 PetscCheck(idxs || bss == nidx, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must provide idxs when not scattering from all locations"); 1108 } 1109 1110 if (addv == INSERT_VALUES) { 1111 if (!idxs) { 1112 for (i = 0; i < n; i++) { 1113 for (j = 0; j < bss; j++) x[bs * i + idxv[j]] = y[bss * i + j]; 1114 } 1115 } else { 1116 for (i = 0; i < n; i++) { 1117 for (j = 0; j < bss; j++) x[bs * i + idxv[j]] = y[bss * i + idxs[j]]; 1118 } 1119 } 1120 } else if (addv == ADD_VALUES) { 1121 if (!idxs) { 1122 for (i = 0; i < n; i++) { 1123 for (j = 0; j < bss; j++) x[bs * i + idxv[j]] += y[bss * i + j]; 1124 } 1125 } else { 1126 for (i = 0; i < n; i++) { 1127 for (j = 0; j < bss; j++) x[bs * i + idxv[j]] += y[bss * i + idxs[j]]; 1128 } 1129 } 1130 #if !defined(PETSC_USE_COMPLEX) 1131 } else if (addv == MAX_VALUES) { 1132 if (!idxs) { 1133 for (i = 0; i < n; i++) { 1134 for (j = 0; j < bss; j++) x[bs * i + idxv[j]] = PetscMax(y[bss * i + j], x[bs * i + idxv[j]]); 1135 } 1136 } else { 1137 for (i = 0; i < n; i++) { 1138 for (j = 0; j < bss; j++) x[bs * i + idxv[j]] = PetscMax(y[bss * i + idxs[j]], x[bs * i + idxv[j]]); 1139 } 1140 } 1141 #endif 1142 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown insert type"); 1143 1144 PetscCall(VecRestoreArray(v, &x)); 1145 PetscCall(VecRestoreArrayRead(s, &y)); 1146 PetscFunctionReturn(0); 1147 } 1148 1149 PetscErrorCode VecReciprocal_Default(Vec v) { 1150 PetscInt i, n; 1151 PetscScalar *x; 1152 1153 PetscFunctionBegin; 1154 PetscCall(VecGetLocalSize(v, &n)); 1155 PetscCall(VecGetArray(v, &x)); 1156 for (i = 0; i < n; i++) { 1157 if (x[i] != (PetscScalar)0.0) x[i] = (PetscScalar)1.0 / x[i]; 1158 } 1159 PetscCall(VecRestoreArray(v, &x)); 1160 PetscFunctionReturn(0); 1161 } 1162 1163 /*@ 1164 VecExp - Replaces each component of a vector by e^x_i 1165 1166 Not collective 1167 1168 Input Parameter: 1169 . v - The vector 1170 1171 Output Parameter: 1172 . v - The vector of exponents 1173 1174 Level: beginner 1175 1176 .seealso: `VecLog()`, `VecAbs()`, `VecSqrtAbs()`, `VecReciprocal()` 1177 1178 @*/ 1179 PetscErrorCode VecExp(Vec v) { 1180 PetscScalar *x; 1181 PetscInt i, n; 1182 1183 PetscFunctionBegin; 1184 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1185 if (v->ops->exp) PetscUseTypeMethod(v, exp); 1186 else { 1187 PetscCall(VecGetLocalSize(v, &n)); 1188 PetscCall(VecGetArray(v, &x)); 1189 for (i = 0; i < n; i++) x[i] = PetscExpScalar(x[i]); 1190 PetscCall(VecRestoreArray(v, &x)); 1191 } 1192 PetscFunctionReturn(0); 1193 } 1194 1195 /*@ 1196 VecLog - Replaces each component of a vector by log(x_i), the natural logarithm 1197 1198 Not collective 1199 1200 Input Parameter: 1201 . v - The vector 1202 1203 Output Parameter: 1204 . v - The vector of logs 1205 1206 Level: beginner 1207 1208 .seealso: `VecExp()`, `VecAbs()`, `VecSqrtAbs()`, `VecReciprocal()` 1209 1210 @*/ 1211 PetscErrorCode VecLog(Vec v) { 1212 PetscScalar *x; 1213 PetscInt i, n; 1214 1215 PetscFunctionBegin; 1216 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1217 if (v->ops->log) PetscUseTypeMethod(v, log); 1218 else { 1219 PetscCall(VecGetLocalSize(v, &n)); 1220 PetscCall(VecGetArray(v, &x)); 1221 for (i = 0; i < n; i++) x[i] = PetscLogScalar(x[i]); 1222 PetscCall(VecRestoreArray(v, &x)); 1223 } 1224 PetscFunctionReturn(0); 1225 } 1226 1227 /*@ 1228 VecSqrtAbs - Replaces each component of a vector by the square root of its magnitude. 1229 1230 Not collective 1231 1232 Input Parameter: 1233 . v - The vector 1234 1235 Output Parameter: 1236 . v - The vector square root 1237 1238 Level: beginner 1239 1240 Note: The actual function is sqrt(|x_i|) 1241 1242 .seealso: `VecLog()`, `VecExp()`, `VecReciprocal()`, `VecAbs()` 1243 1244 @*/ 1245 PetscErrorCode VecSqrtAbs(Vec v) { 1246 PetscScalar *x; 1247 PetscInt i, n; 1248 1249 PetscFunctionBegin; 1250 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1251 if (v->ops->sqrt) PetscUseTypeMethod(v, sqrt); 1252 else { 1253 PetscCall(VecGetLocalSize(v, &n)); 1254 PetscCall(VecGetArray(v, &x)); 1255 for (i = 0; i < n; i++) x[i] = PetscSqrtReal(PetscAbsScalar(x[i])); 1256 PetscCall(VecRestoreArray(v, &x)); 1257 } 1258 PetscFunctionReturn(0); 1259 } 1260 1261 /*@ 1262 VecDotNorm2 - computes the inner product of two vectors and the 2-norm squared of the second vector 1263 1264 Collective on Vec 1265 1266 Input Parameters: 1267 + s - first vector 1268 - t - second vector 1269 1270 Output Parameters: 1271 + dp - s'conj(t) 1272 - nm - t'conj(t) 1273 1274 Level: advanced 1275 1276 Notes: 1277 conj(x) is the complex conjugate of x when x is complex 1278 1279 .seealso: `VecDot()`, `VecNorm()`, `VecDotBegin()`, `VecNormBegin()`, `VecDotEnd()`, `VecNormEnd()` 1280 1281 @*/ 1282 PetscErrorCode VecDotNorm2(Vec s, Vec t, PetscScalar *dp, PetscReal *nm) { 1283 const PetscScalar *sx, *tx; 1284 PetscScalar dpx = 0.0, nmx = 0.0, work[2], sum[2]; 1285 PetscInt i, n; 1286 1287 PetscFunctionBegin; 1288 PetscValidHeaderSpecific(s, VEC_CLASSID, 1); 1289 PetscValidHeaderSpecific(t, VEC_CLASSID, 2); 1290 PetscValidScalarPointer(dp, 3); 1291 PetscValidRealPointer(nm, 4); 1292 PetscValidType(s, 1); 1293 PetscValidType(t, 2); 1294 PetscCheckSameTypeAndComm(s, 1, t, 2); 1295 PetscCheck(s->map->N == t->map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Incompatible vector global lengths"); 1296 PetscCheck(s->map->n == t->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Incompatible vector local lengths"); 1297 1298 PetscCall(PetscLogEventBegin(VEC_DotNorm2, s, t, 0, 0)); 1299 if (s->ops->dotnorm2) { 1300 PetscUseTypeMethod(s, dotnorm2, t, dp, &dpx); 1301 *nm = PetscRealPart(dpx); 1302 } else { 1303 PetscCall(VecGetLocalSize(s, &n)); 1304 PetscCall(VecGetArrayRead(s, &sx)); 1305 PetscCall(VecGetArrayRead(t, &tx)); 1306 1307 for (i = 0; i < n; i++) { 1308 dpx += sx[i] * PetscConj(tx[i]); 1309 nmx += tx[i] * PetscConj(tx[i]); 1310 } 1311 work[0] = dpx; 1312 work[1] = nmx; 1313 1314 PetscCall(MPIU_Allreduce(work, sum, 2, MPIU_SCALAR, MPIU_SUM, PetscObjectComm((PetscObject)s))); 1315 *dp = sum[0]; 1316 *nm = PetscRealPart(sum[1]); 1317 1318 PetscCall(VecRestoreArrayRead(t, &tx)); 1319 PetscCall(VecRestoreArrayRead(s, &sx)); 1320 PetscCall(PetscLogFlops(4.0 * n)); 1321 } 1322 PetscCall(PetscLogEventEnd(VEC_DotNorm2, s, t, 0, 0)); 1323 PetscFunctionReturn(0); 1324 } 1325 1326 /*@ 1327 VecSum - Computes the sum of all the components of a vector. 1328 1329 Collective on Vec 1330 1331 Input Parameter: 1332 . v - the vector 1333 1334 Output Parameter: 1335 . sum - the result 1336 1337 Level: beginner 1338 1339 .seealso: `VecMean()`, `VecNorm()` 1340 @*/ 1341 PetscErrorCode VecSum(Vec v, PetscScalar *sum) { 1342 PetscInt i, n; 1343 const PetscScalar *x; 1344 1345 PetscFunctionBegin; 1346 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1347 PetscValidScalarPointer(sum, 2); 1348 *sum = 0.0; 1349 if (v->ops->sum) { 1350 PetscUseTypeMethod(v, sum, sum); 1351 } else { 1352 PetscCall(VecGetLocalSize(v, &n)); 1353 PetscCall(VecGetArrayRead(v, &x)); 1354 for (i = 0; i < n; i++) *sum += x[i]; 1355 PetscCall(VecRestoreArrayRead(v, &x)); 1356 } 1357 PetscCall(MPIU_Allreduce(MPI_IN_PLACE, sum, 1, MPIU_SCALAR, MPIU_SUM, PetscObjectComm((PetscObject)v))); 1358 PetscFunctionReturn(0); 1359 } 1360 1361 /*@ 1362 VecMean - Computes the arithmetic mean of all the components of a vector. 1363 1364 Collective on Vec 1365 1366 Input Parameter: 1367 . v - the vector 1368 1369 Output Parameter: 1370 . mean - the result 1371 1372 Level: beginner 1373 1374 .seealso: `VecSum()`, `VecNorm()` 1375 @*/ 1376 PetscErrorCode VecMean(Vec v, PetscScalar *mean) { 1377 PetscInt n; 1378 1379 PetscFunctionBegin; 1380 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1381 PetscValidScalarPointer(mean, 2); 1382 PetscCall(VecGetSize(v, &n)); 1383 PetscCall(VecSum(v, mean)); 1384 *mean /= n; 1385 PetscFunctionReturn(0); 1386 } 1387 1388 /*@ 1389 VecImaginaryPart - Replaces a complex vector with its imginary part 1390 1391 Collective on Vec 1392 1393 Input Parameter: 1394 . v - the vector 1395 1396 Level: beginner 1397 1398 .seealso: `VecNorm()`, `VecRealPart()` 1399 @*/ 1400 PetscErrorCode VecImaginaryPart(Vec v) { 1401 PetscInt i, n; 1402 PetscScalar *x; 1403 1404 PetscFunctionBegin; 1405 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1406 PetscCall(VecGetLocalSize(v, &n)); 1407 PetscCall(VecGetArray(v, &x)); 1408 for (i = 0; i < n; i++) x[i] = PetscImaginaryPart(x[i]); 1409 PetscCall(VecRestoreArray(v, &x)); 1410 PetscFunctionReturn(0); 1411 } 1412 1413 /*@ 1414 VecRealPart - Replaces a complex vector with its real part 1415 1416 Collective on Vec 1417 1418 Input Parameter: 1419 . v - the vector 1420 1421 Level: beginner 1422 1423 .seealso: `VecNorm()`, `VecImaginaryPart()` 1424 @*/ 1425 PetscErrorCode VecRealPart(Vec v) { 1426 PetscInt i, n; 1427 PetscScalar *x; 1428 1429 PetscFunctionBegin; 1430 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1431 PetscCall(VecGetLocalSize(v, &n)); 1432 PetscCall(VecGetArray(v, &x)); 1433 for (i = 0; i < n; i++) x[i] = PetscRealPart(x[i]); 1434 PetscCall(VecRestoreArray(v, &x)); 1435 PetscFunctionReturn(0); 1436 } 1437 1438 /*@ 1439 VecShift - Shifts all of the components of a vector by computing 1440 x[i] = x[i] + shift. 1441 1442 Logically Collective on Vec 1443 1444 Input Parameters: 1445 + v - the vector 1446 - shift - the shift 1447 1448 Level: intermediate 1449 1450 @*/ 1451 PetscErrorCode VecShift(Vec v, PetscScalar shift) { 1452 PetscInt i, n; 1453 PetscScalar *x; 1454 1455 PetscFunctionBegin; 1456 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1457 PetscValidLogicalCollectiveScalar(v, shift, 2); 1458 PetscCall(VecSetErrorIfLocked(v, 1)); 1459 if (shift == 0.0) PetscFunctionReturn(0); 1460 1461 if (v->ops->shift) PetscUseTypeMethod(v, shift, shift); 1462 else { 1463 PetscCall(VecGetLocalSize(v, &n)); 1464 PetscCall(VecGetArray(v, &x)); 1465 for (i = 0; i < n; i++) x[i] += shift; 1466 PetscCall(VecRestoreArray(v, &x)); 1467 } 1468 PetscFunctionReturn(0); 1469 } 1470 1471 /*@ 1472 VecAbs - Replaces every element in a vector with its absolute value. 1473 1474 Logically Collective on Vec 1475 1476 Input Parameters: 1477 . v - the vector 1478 1479 Level: intermediate 1480 1481 @*/ 1482 PetscErrorCode VecAbs(Vec v) { 1483 PetscInt i, n; 1484 PetscScalar *x; 1485 1486 PetscFunctionBegin; 1487 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1488 PetscCall(VecSetErrorIfLocked(v, 1)); 1489 1490 if (v->ops->abs) { 1491 PetscUseTypeMethod(v, abs); 1492 } else { 1493 PetscCall(VecGetLocalSize(v, &n)); 1494 PetscCall(VecGetArray(v, &x)); 1495 for (i = 0; i < n; i++) x[i] = PetscAbsScalar(x[i]); 1496 PetscCall(VecRestoreArray(v, &x)); 1497 } 1498 PetscFunctionReturn(0); 1499 } 1500 1501 /*@ 1502 VecPermute - Permutes a vector in place using the given ordering. 1503 1504 Input Parameters: 1505 + vec - The vector 1506 . order - The ordering 1507 - inv - The flag for inverting the permutation 1508 1509 Level: beginner 1510 1511 Note: This function does not yet support parallel Index Sets with non-local permutations 1512 1513 .seealso: `MatPermute()` 1514 @*/ 1515 PetscErrorCode VecPermute(Vec x, IS row, PetscBool inv) { 1516 const PetscScalar *array; 1517 PetscScalar *newArray; 1518 const PetscInt *idx; 1519 PetscInt i, rstart, rend; 1520 1521 PetscFunctionBegin; 1522 PetscValidHeaderSpecific(x, VEC_CLASSID, 1); 1523 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 1524 PetscCall(VecSetErrorIfLocked(x, 1)); 1525 PetscCall(VecGetOwnershipRange(x, &rstart, &rend)); 1526 PetscCall(ISGetIndices(row, &idx)); 1527 PetscCall(VecGetArrayRead(x, &array)); 1528 PetscCall(PetscMalloc1(x->map->n, &newArray)); 1529 if (PetscDefined(USE_DEBUG)) { 1530 for (i = 0; i < x->map->n; i++) PetscCheck(!(idx[i] < rstart) && !(idx[i] >= rend), PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Permutation index %" PetscInt_FMT " is out of bounds: %" PetscInt_FMT, i, idx[i]); 1531 } 1532 if (!inv) { 1533 for (i = 0; i < x->map->n; i++) newArray[i] = array[idx[i] - rstart]; 1534 } else { 1535 for (i = 0; i < x->map->n; i++) newArray[idx[i] - rstart] = array[i]; 1536 } 1537 PetscCall(VecRestoreArrayRead(x, &array)); 1538 PetscCall(ISRestoreIndices(row, &idx)); 1539 PetscCall(VecReplaceArray(x, newArray)); 1540 PetscFunctionReturn(0); 1541 } 1542 1543 /*@ 1544 VecEqual - Compares two vectors. Returns true if the two vectors are either pointing to the same memory buffer, 1545 or if the two vectors have the same local and global layout as well as bitwise equality of all entries. 1546 Does NOT take round-off errors into account. 1547 1548 Collective on Vec 1549 1550 Input Parameters: 1551 + vec1 - the first vector 1552 - vec2 - the second vector 1553 1554 Output Parameter: 1555 . flg - PETSC_TRUE if the vectors are equal; PETSC_FALSE otherwise. 1556 1557 Level: intermediate 1558 @*/ 1559 PetscErrorCode VecEqual(Vec vec1, Vec vec2, PetscBool *flg) { 1560 const PetscScalar *v1, *v2; 1561 PetscInt n1, n2, N1, N2; 1562 PetscBool flg1; 1563 1564 PetscFunctionBegin; 1565 PetscValidHeaderSpecific(vec1, VEC_CLASSID, 1); 1566 PetscValidHeaderSpecific(vec2, VEC_CLASSID, 2); 1567 PetscValidBoolPointer(flg, 3); 1568 if (vec1 == vec2) *flg = PETSC_TRUE; 1569 else { 1570 PetscCall(VecGetSize(vec1, &N1)); 1571 PetscCall(VecGetSize(vec2, &N2)); 1572 if (N1 != N2) flg1 = PETSC_FALSE; 1573 else { 1574 PetscCall(VecGetLocalSize(vec1, &n1)); 1575 PetscCall(VecGetLocalSize(vec2, &n2)); 1576 if (n1 != n2) flg1 = PETSC_FALSE; 1577 else { 1578 PetscCall(VecGetArrayRead(vec1, &v1)); 1579 PetscCall(VecGetArrayRead(vec2, &v2)); 1580 PetscCall(PetscArraycmp(v1, v2, n1, &flg1)); 1581 PetscCall(VecRestoreArrayRead(vec1, &v1)); 1582 PetscCall(VecRestoreArrayRead(vec2, &v2)); 1583 } 1584 } 1585 /* combine results from all processors */ 1586 PetscCall(MPIU_Allreduce(&flg1, flg, 1, MPIU_BOOL, MPI_MIN, PetscObjectComm((PetscObject)vec1))); 1587 } 1588 PetscFunctionReturn(0); 1589 } 1590 1591 /*@ 1592 VecUniqueEntries - Compute the number of unique entries, and those entries 1593 1594 Collective on Vec 1595 1596 Input Parameter: 1597 . vec - the vector 1598 1599 Output Parameters: 1600 + n - The number of unique entries 1601 - e - The entries 1602 1603 Level: intermediate 1604 1605 @*/ 1606 PetscErrorCode VecUniqueEntries(Vec vec, PetscInt *n, PetscScalar **e) { 1607 const PetscScalar *v; 1608 PetscScalar *tmp, *vals; 1609 PetscMPIInt *N, *displs, l; 1610 PetscInt ng, m, i, j, p; 1611 PetscMPIInt size; 1612 1613 PetscFunctionBegin; 1614 PetscValidHeaderSpecific(vec, VEC_CLASSID, 1); 1615 PetscValidIntPointer(n, 2); 1616 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)vec), &size)); 1617 PetscCall(VecGetLocalSize(vec, &m)); 1618 PetscCall(VecGetArrayRead(vec, &v)); 1619 PetscCall(PetscMalloc2(m, &tmp, size, &N)); 1620 for (i = 0, j = 0, l = 0; i < m; ++i) { 1621 /* Can speed this up with sorting */ 1622 for (j = 0; j < l; ++j) { 1623 if (v[i] == tmp[j]) break; 1624 } 1625 if (j == l) { 1626 tmp[j] = v[i]; 1627 ++l; 1628 } 1629 } 1630 PetscCall(VecRestoreArrayRead(vec, &v)); 1631 /* Gather serial results */ 1632 PetscCallMPI(MPI_Allgather(&l, 1, MPI_INT, N, 1, MPI_INT, PetscObjectComm((PetscObject)vec))); 1633 for (p = 0, ng = 0; p < size; ++p) ng += N[p]; 1634 PetscCall(PetscMalloc2(ng, &vals, size + 1, &displs)); 1635 for (p = 1, displs[0] = 0; p <= size; ++p) displs[p] = displs[p - 1] + N[p - 1]; 1636 PetscCallMPI(MPI_Allgatherv(tmp, l, MPIU_SCALAR, vals, N, displs, MPIU_SCALAR, PetscObjectComm((PetscObject)vec))); 1637 /* Find unique entries */ 1638 #ifdef PETSC_USE_COMPLEX 1639 SETERRQ(PetscObjectComm((PetscObject)vec), PETSC_ERR_SUP, "Does not work with complex numbers"); 1640 #else 1641 *n = displs[size]; 1642 PetscCall(PetscSortRemoveDupsReal(n, (PetscReal *)vals)); 1643 if (e) { 1644 PetscValidPointer(e, 3); 1645 PetscCall(PetscMalloc1(*n, e)); 1646 for (i = 0; i < *n; ++i) (*e)[i] = vals[i]; 1647 } 1648 PetscCall(PetscFree2(vals, displs)); 1649 PetscCall(PetscFree2(tmp, N)); 1650 PetscFunctionReturn(0); 1651 #endif 1652 } 1653