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