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