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(VecApplyUnary_Private(v, dctx, VecAsyncFnName(Reciprocal), v->ops->reciprocal, ScalarReciprocal_Function)); 1226 PetscFunctionReturn(PETSC_SUCCESS); 1227 } 1228 1229 PetscErrorCode VecReciprocal_Default(Vec v) 1230 { 1231 PetscFunctionBegin; 1232 PetscCall(VecApplyUnary_Private(v, NULL, NULL, NULL, ScalarReciprocal_Function)); 1233 PetscFunctionReturn(PETSC_SUCCESS); 1234 } 1235 1236 static PetscScalar ScalarExp_Function(PetscScalar x) 1237 { 1238 return PetscExpScalar(x); 1239 } 1240 1241 PetscErrorCode VecExpAsync_Private(Vec v, PetscDeviceContext dctx) 1242 { 1243 PetscFunctionBegin; 1244 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1245 PetscCall(VecApplyUnary_Private(v, dctx, VecAsyncFnName(Exp), v->ops->exp, ScalarExp_Function)); 1246 PetscFunctionReturn(PETSC_SUCCESS); 1247 } 1248 1249 /*@ 1250 VecExp - Replaces each component of a vector by e^x_i 1251 1252 Not Collective 1253 1254 Input Parameter: 1255 . v - The vector 1256 1257 Output Parameter: 1258 . v - The vector of exponents 1259 1260 Level: beginner 1261 1262 .seealso: `Vec`, `VecLog()`, `VecAbs()`, `VecSqrtAbs()`, `VecReciprocal()` 1263 1264 @*/ 1265 PetscErrorCode VecExp(Vec v) 1266 { 1267 PetscFunctionBegin; 1268 PetscCall(VecExpAsync_Private(v, NULL)); 1269 PetscFunctionReturn(PETSC_SUCCESS); 1270 } 1271 1272 static PetscScalar ScalarLog_Function(PetscScalar x) 1273 { 1274 return PetscLogScalar(x); 1275 } 1276 1277 PetscErrorCode VecLogAsync_Private(Vec v, PetscDeviceContext dctx) 1278 { 1279 PetscFunctionBegin; 1280 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1281 PetscCall(VecApplyUnary_Private(v, dctx, VecAsyncFnName(Log), v->ops->log, ScalarLog_Function)); 1282 PetscFunctionReturn(PETSC_SUCCESS); 1283 } 1284 1285 /*@ 1286 VecLog - Replaces each component of a vector by log(x_i), the natural logarithm 1287 1288 Not Collective 1289 1290 Input Parameter: 1291 . v - The vector 1292 1293 Output Parameter: 1294 . v - The vector of logs 1295 1296 Level: beginner 1297 1298 .seealso: `Vec`, `VecExp()`, `VecAbs()`, `VecSqrtAbs()`, `VecReciprocal()` 1299 1300 @*/ 1301 PetscErrorCode VecLog(Vec v) 1302 { 1303 PetscFunctionBegin; 1304 PetscCall(VecLogAsync_Private(v, NULL)); 1305 PetscFunctionReturn(PETSC_SUCCESS); 1306 } 1307 1308 static PetscScalar ScalarAbs_Function(PetscScalar x) 1309 { 1310 return PetscAbsScalar(x); 1311 } 1312 1313 PetscErrorCode VecAbsAsync_Private(Vec v, PetscDeviceContext dctx) 1314 { 1315 PetscFunctionBegin; 1316 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1317 PetscCall(VecApplyUnary_Private(v, dctx, VecAsyncFnName(Abs), v->ops->abs, ScalarAbs_Function)); 1318 PetscFunctionReturn(PETSC_SUCCESS); 1319 } 1320 1321 /*@ 1322 VecAbs - Replaces every element in a vector with its absolute value. 1323 1324 Logically Collective 1325 1326 Input Parameter: 1327 . v - the vector 1328 1329 Level: intermediate 1330 1331 .seealso: `Vec`, `VecExp()`, `VecSqrtAbs()`, `VecReciprocal()`, `VecLog()` 1332 @*/ 1333 PetscErrorCode VecAbs(Vec v) 1334 { 1335 PetscFunctionBegin; 1336 PetscCall(VecAbsAsync_Private(v, NULL)); 1337 PetscFunctionReturn(PETSC_SUCCESS); 1338 } 1339 1340 static PetscScalar ScalarConjugate_Function(PetscScalar x) 1341 { 1342 return PetscConj(x); 1343 } 1344 1345 PetscErrorCode VecConjugateAsync_Private(Vec v, PetscDeviceContext dctx) 1346 { 1347 PetscFunctionBegin; 1348 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1349 if (PetscDefined(USE_COMPLEX)) PetscCall(VecApplyUnary_Private(v, dctx, VecAsyncFnName(Conjugate), v->ops->conjugate, ScalarConjugate_Function)); 1350 PetscFunctionReturn(PETSC_SUCCESS); 1351 } 1352 1353 /*@ 1354 VecConjugate - Conjugates a vector. That is, replace every entry in a vector with its complex conjugate 1355 1356 Logically Collective 1357 1358 Input Parameter: 1359 . x - the vector 1360 1361 Level: intermediate 1362 1363 .seealso: [](ch_vectors), `Vec`, `VecSet()` 1364 @*/ 1365 PetscErrorCode VecConjugate(Vec x) 1366 { 1367 PetscFunctionBegin; 1368 PetscCall(VecConjugateAsync_Private(x, NULL)); 1369 PetscFunctionReturn(PETSC_SUCCESS); 1370 } 1371 1372 static PetscScalar ScalarSqrtAbs_Function(PetscScalar x) 1373 { 1374 return PetscSqrtScalar(ScalarAbs_Function(x)); 1375 } 1376 1377 PetscErrorCode VecSqrtAbsAsync_Private(Vec v, PetscDeviceContext dctx) 1378 { 1379 PetscFunctionBegin; 1380 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1381 PetscCall(VecApplyUnary_Private(v, dctx, VecAsyncFnName(SqrtAbs), v->ops->sqrt, ScalarSqrtAbs_Function)); 1382 PetscFunctionReturn(PETSC_SUCCESS); 1383 } 1384 1385 /*@ 1386 VecSqrtAbs - Replaces each component of a vector by the square root of its magnitude. 1387 1388 Not Collective 1389 1390 Input Parameter: 1391 . v - The vector 1392 1393 Level: beginner 1394 1395 Note: 1396 The actual function is sqrt(|x_i|) 1397 1398 .seealso: `Vec`, `VecLog()`, `VecExp()`, `VecReciprocal()`, `VecAbs()` 1399 1400 @*/ 1401 PetscErrorCode VecSqrtAbs(Vec v) 1402 { 1403 PetscFunctionBegin; 1404 PetscCall(VecSqrtAbsAsync_Private(v, NULL)); 1405 PetscFunctionReturn(PETSC_SUCCESS); 1406 } 1407 1408 static PetscScalar ScalarImaginaryPart_Function(PetscScalar x) 1409 { 1410 const PetscReal imag = PetscImaginaryPart(x); 1411 1412 #if PetscDefined(USE_COMPLEX) 1413 return PetscCMPLX(imag, 0.0); 1414 #else 1415 return imag; 1416 #endif 1417 } 1418 1419 /*@ 1420 VecImaginaryPart - Replaces a complex vector with its imginary part 1421 1422 Collective 1423 1424 Input Parameter: 1425 . v - the vector 1426 1427 Level: beginner 1428 1429 .seealso: `Vec`, `VecNorm()`, `VecRealPart()` 1430 @*/ 1431 PetscErrorCode VecImaginaryPart(Vec v) 1432 { 1433 PetscFunctionBegin; 1434 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1435 PetscCall(VecApplyUnary_Private(v, NULL, NULL, NULL, ScalarImaginaryPart_Function)); 1436 PetscFunctionReturn(PETSC_SUCCESS); 1437 } 1438 1439 static PetscScalar ScalarRealPart_Function(PetscScalar x) 1440 { 1441 const PetscReal real = PetscRealPart(x); 1442 1443 #if PetscDefined(USE_COMPLEX) 1444 return PetscCMPLX(real, 0.0); 1445 #else 1446 return real; 1447 #endif 1448 } 1449 1450 /*@ 1451 VecRealPart - Replaces a complex vector with its real part 1452 1453 Collective 1454 1455 Input Parameter: 1456 . v - the vector 1457 1458 Level: beginner 1459 1460 .seealso: `Vec`, `VecNorm()`, `VecImaginaryPart()` 1461 @*/ 1462 PetscErrorCode VecRealPart(Vec v) 1463 { 1464 PetscFunctionBegin; 1465 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1466 PetscCall(VecApplyUnary_Private(v, NULL, NULL, NULL, ScalarRealPart_Function)); 1467 PetscFunctionReturn(PETSC_SUCCESS); 1468 } 1469 1470 /*@ 1471 VecDotNorm2 - computes the inner product of two vectors and the 2-norm squared of the second vector 1472 1473 Collective 1474 1475 Input Parameters: 1476 + s - first vector 1477 - t - second vector 1478 1479 Output Parameters: 1480 + dp - s'conj(t) 1481 - nm - t'conj(t) 1482 1483 Level: advanced 1484 1485 Note: 1486 conj(x) is the complex conjugate of x when x is complex 1487 1488 .seealso: `Vec`, `VecDot()`, `VecNorm()`, `VecDotBegin()`, `VecNormBegin()`, `VecDotEnd()`, `VecNormEnd()` 1489 1490 @*/ 1491 PetscErrorCode VecDotNorm2(Vec s, Vec t, PetscScalar *dp, PetscReal *nm) 1492 { 1493 PetscScalar work[] = {0.0, 0.0}; 1494 1495 PetscFunctionBegin; 1496 PetscValidHeaderSpecific(s, VEC_CLASSID, 1); 1497 PetscValidHeaderSpecific(t, VEC_CLASSID, 2); 1498 PetscAssertPointer(dp, 3); 1499 PetscAssertPointer(nm, 4); 1500 PetscValidType(s, 1); 1501 PetscValidType(t, 2); 1502 PetscCheckSameTypeAndComm(s, 1, t, 2); 1503 PetscCheck(s->map->N == t->map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Incompatible vector global lengths"); 1504 PetscCheck(s->map->n == t->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Incompatible vector local lengths"); 1505 1506 PetscCall(PetscLogEventBegin(VEC_DotNorm2, s, t, 0, 0)); 1507 if (s->ops->dotnorm2) { 1508 PetscUseTypeMethod(s, dotnorm2, t, work, work + 1); 1509 } else { 1510 const PetscScalar *sx, *tx; 1511 PetscInt n; 1512 1513 PetscCall(VecGetLocalSize(s, &n)); 1514 PetscCall(VecGetArrayRead(s, &sx)); 1515 PetscCall(VecGetArrayRead(t, &tx)); 1516 for (PetscInt i = 0; i < n; ++i) { 1517 const PetscScalar txconj = PetscConj(tx[i]); 1518 1519 work[0] += sx[i] * txconj; 1520 work[1] += tx[i] * txconj; 1521 } 1522 PetscCall(VecRestoreArrayRead(t, &tx)); 1523 PetscCall(VecRestoreArrayRead(s, &sx)); 1524 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, work, 2, MPIU_SCALAR, MPIU_SUM, PetscObjectComm((PetscObject)s))); 1525 PetscCall(PetscLogFlops(4.0 * n)); 1526 } 1527 PetscCall(PetscLogEventEnd(VEC_DotNorm2, s, t, 0, 0)); 1528 *dp = work[0]; 1529 *nm = PetscRealPart(work[1]); 1530 PetscFunctionReturn(PETSC_SUCCESS); 1531 } 1532 1533 /*@ 1534 VecSum - Computes the sum of all the components of a vector. 1535 1536 Collective 1537 1538 Input Parameter: 1539 . v - the vector 1540 1541 Output Parameter: 1542 . sum - the result 1543 1544 Level: beginner 1545 1546 .seealso: `Vec`, `VecMean()`, `VecNorm()` 1547 @*/ 1548 PetscErrorCode VecSum(Vec v, PetscScalar *sum) 1549 { 1550 PetscScalar tmp = 0.0; 1551 1552 PetscFunctionBegin; 1553 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1554 PetscAssertPointer(sum, 2); 1555 if (v->ops->sum) { 1556 PetscUseTypeMethod(v, sum, &tmp); 1557 } else { 1558 const PetscScalar *x; 1559 PetscInt n; 1560 1561 PetscCall(VecGetLocalSize(v, &n)); 1562 PetscCall(VecGetArrayRead(v, &x)); 1563 for (PetscInt i = 0; i < n; ++i) tmp += x[i]; 1564 PetscCall(VecRestoreArrayRead(v, &x)); 1565 } 1566 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &tmp, 1, MPIU_SCALAR, MPIU_SUM, PetscObjectComm((PetscObject)v))); 1567 *sum = tmp; 1568 PetscFunctionReturn(PETSC_SUCCESS); 1569 } 1570 1571 /*@ 1572 VecMean - Computes the arithmetic mean of all the components of a vector. 1573 1574 Collective 1575 1576 Input Parameter: 1577 . v - the vector 1578 1579 Output Parameter: 1580 . mean - the result 1581 1582 Level: beginner 1583 1584 .seealso: `Vec`, `VecSum()`, `VecNorm()` 1585 @*/ 1586 PetscErrorCode VecMean(Vec v, PetscScalar *mean) 1587 { 1588 PetscInt n; 1589 1590 PetscFunctionBegin; 1591 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1592 PetscAssertPointer(mean, 2); 1593 PetscCall(VecGetSize(v, &n)); 1594 PetscCall(VecSum(v, mean)); 1595 *mean /= n; 1596 PetscFunctionReturn(PETSC_SUCCESS); 1597 } 1598 1599 PetscErrorCode VecShiftAsync_Private(Vec v, PetscScalar shift, PetscDeviceContext dctx) 1600 { 1601 PetscErrorCode (*shift_async)(Vec, PetscScalar, PetscDeviceContext) = NULL; 1602 1603 PetscFunctionBegin; 1604 if (dctx) { 1605 PetscErrorCode (*shift_async)(Vec, PetscScalar, PetscDeviceContext); 1606 1607 PetscCall(PetscObjectQueryFunction((PetscObject)v, VecAsyncFnName(Shift), &shift_async)); 1608 } 1609 if (shift_async) { 1610 PetscCall((*shift_async)(v, shift, dctx)); 1611 } else if (v->ops->shift) { 1612 PetscUseTypeMethod(v, shift, shift); 1613 } else { 1614 PetscInt n; 1615 PetscScalar *x; 1616 1617 PetscCall(VecGetLocalSize(v, &n)); 1618 PetscCall(VecGetArray(v, &x)); 1619 for (PetscInt i = 0; i < n; ++i) x[i] += shift; 1620 PetscCall(VecRestoreArray(v, &x)); 1621 PetscCall(PetscLogFlops(n)); 1622 } 1623 PetscFunctionReturn(PETSC_SUCCESS); 1624 } 1625 1626 /*@ 1627 VecShift - Shifts all of the components of a vector by computing 1628 `x[i] = x[i] + shift`. 1629 1630 Logically Collective 1631 1632 Input Parameters: 1633 + v - the vector 1634 - shift - the shift 1635 1636 Level: intermediate 1637 1638 .seealso: `Vec`, `VecISShift()` 1639 @*/ 1640 PetscErrorCode VecShift(Vec v, PetscScalar shift) 1641 { 1642 PetscFunctionBegin; 1643 PetscValidHeaderSpecific(v, VEC_CLASSID, 1); 1644 PetscValidLogicalCollectiveScalar(v, shift, 2); 1645 PetscCall(VecSetErrorIfLocked(v, 1)); 1646 if (shift == (PetscScalar)0.0) PetscFunctionReturn(PETSC_SUCCESS); 1647 PetscCall(PetscLogEventBegin(VEC_Shift, v, 0, 0, 0)); 1648 PetscCall(VecShiftAsync_Private(v, shift, NULL)); 1649 PetscCall(PetscLogEventEnd(VEC_Shift, v, 0, 0, 0)); 1650 PetscFunctionReturn(PETSC_SUCCESS); 1651 } 1652 1653 /*@ 1654 VecPermute - Permutes a vector in place using the given ordering. 1655 1656 Input Parameters: 1657 + x - The vector 1658 . row - The ordering 1659 - inv - The flag for inverting the permutation 1660 1661 Level: beginner 1662 1663 Note: 1664 This function does not yet support parallel Index Sets with non-local permutations 1665 1666 .seealso: `Vec`, `MatPermute()` 1667 @*/ 1668 PetscErrorCode VecPermute(Vec x, IS row, PetscBool inv) 1669 { 1670 PetscScalar *array, *newArray; 1671 const PetscInt *idx; 1672 PetscInt i, rstart, rend; 1673 1674 PetscFunctionBegin; 1675 PetscValidHeaderSpecific(x, VEC_CLASSID, 1); 1676 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 1677 PetscCall(VecSetErrorIfLocked(x, 1)); 1678 PetscCall(VecGetOwnershipRange(x, &rstart, &rend)); 1679 PetscCall(ISGetIndices(row, &idx)); 1680 PetscCall(VecGetArray(x, &array)); 1681 PetscCall(PetscMalloc1(x->map->n, &newArray)); 1682 PetscCall(PetscArraycpy(newArray, array, x->map->n)); 1683 if (PetscDefined(USE_DEBUG)) { 1684 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]); 1685 } 1686 if (!inv) { 1687 for (i = 0; i < x->map->n; i++) array[i] = newArray[idx[i] - rstart]; 1688 } else { 1689 for (i = 0; i < x->map->n; i++) array[idx[i] - rstart] = newArray[i]; 1690 } 1691 PetscCall(VecRestoreArray(x, &array)); 1692 PetscCall(ISRestoreIndices(row, &idx)); 1693 PetscCall(PetscFree(newArray)); 1694 PetscFunctionReturn(PETSC_SUCCESS); 1695 } 1696 1697 /*@ 1698 VecEqual - Compares two vectors. Returns true if the two vectors are either pointing to the same memory buffer, 1699 or if the two vectors have the same local and global layout as well as bitwise equality of all entries. 1700 Does NOT take round-off errors into account. 1701 1702 Collective 1703 1704 Input Parameters: 1705 + vec1 - the first vector 1706 - vec2 - the second vector 1707 1708 Output Parameter: 1709 . flg - `PETSC_TRUE` if the vectors are equal; `PETSC_FALSE` otherwise. 1710 1711 Level: intermediate 1712 1713 .seealso: `Vec` 1714 @*/ 1715 PetscErrorCode VecEqual(Vec vec1, Vec vec2, PetscBool *flg) 1716 { 1717 const PetscScalar *v1, *v2; 1718 PetscInt n1, n2, N1, N2; 1719 PetscBool flg1; 1720 1721 PetscFunctionBegin; 1722 PetscValidHeaderSpecific(vec1, VEC_CLASSID, 1); 1723 PetscValidHeaderSpecific(vec2, VEC_CLASSID, 2); 1724 PetscAssertPointer(flg, 3); 1725 if (vec1 == vec2) *flg = PETSC_TRUE; 1726 else { 1727 PetscCall(VecGetSize(vec1, &N1)); 1728 PetscCall(VecGetSize(vec2, &N2)); 1729 if (N1 != N2) flg1 = PETSC_FALSE; 1730 else { 1731 PetscCall(VecGetLocalSize(vec1, &n1)); 1732 PetscCall(VecGetLocalSize(vec2, &n2)); 1733 if (n1 != n2) flg1 = PETSC_FALSE; 1734 else { 1735 PetscCall(VecGetArrayRead(vec1, &v1)); 1736 PetscCall(VecGetArrayRead(vec2, &v2)); 1737 PetscCall(PetscArraycmp(v1, v2, n1, &flg1)); 1738 PetscCall(VecRestoreArrayRead(vec1, &v1)); 1739 PetscCall(VecRestoreArrayRead(vec2, &v2)); 1740 } 1741 } 1742 /* combine results from all processors */ 1743 PetscCallMPI(MPIU_Allreduce(&flg1, flg, 1, MPIU_BOOL, MPI_MIN, PetscObjectComm((PetscObject)vec1))); 1744 } 1745 PetscFunctionReturn(PETSC_SUCCESS); 1746 } 1747 1748 /*@ 1749 VecUniqueEntries - Compute the number of unique entries, and those entries 1750 1751 Collective 1752 1753 Input Parameter: 1754 . vec - the vector 1755 1756 Output Parameters: 1757 + n - The number of unique entries 1758 - e - The entries 1759 1760 Level: intermediate 1761 1762 .seealso: `Vec` 1763 @*/ 1764 PetscErrorCode VecUniqueEntries(Vec vec, PetscInt *n, PetscScalar **e) 1765 { 1766 const PetscScalar *v; 1767 PetscScalar *tmp, *vals; 1768 PetscMPIInt *N, *displs, l; 1769 PetscInt ng, m, i, j, p; 1770 PetscMPIInt size; 1771 1772 PetscFunctionBegin; 1773 PetscValidHeaderSpecific(vec, VEC_CLASSID, 1); 1774 PetscAssertPointer(n, 2); 1775 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)vec), &size)); 1776 PetscCall(VecGetLocalSize(vec, &m)); 1777 PetscCall(VecGetArrayRead(vec, &v)); 1778 PetscCall(PetscMalloc2(m, &tmp, size, &N)); 1779 for (i = 0, l = 0; i < m; ++i) { 1780 /* Can speed this up with sorting */ 1781 for (j = 0; j < l; ++j) { 1782 if (v[i] == tmp[j]) break; 1783 } 1784 if (j == l) { 1785 tmp[j] = v[i]; 1786 ++l; 1787 } 1788 } 1789 PetscCall(VecRestoreArrayRead(vec, &v)); 1790 /* Gather serial results */ 1791 PetscCallMPI(MPI_Allgather(&l, 1, MPI_INT, N, 1, MPI_INT, PetscObjectComm((PetscObject)vec))); 1792 for (p = 0, ng = 0; p < size; ++p) ng += N[p]; 1793 PetscCall(PetscMalloc2(ng, &vals, size + 1, &displs)); 1794 for (p = 1, displs[0] = 0; p <= size; ++p) displs[p] = displs[p - 1] + N[p - 1]; 1795 PetscCallMPI(MPI_Allgatherv(tmp, l, MPIU_SCALAR, vals, N, displs, MPIU_SCALAR, PetscObjectComm((PetscObject)vec))); 1796 /* Find unique entries */ 1797 #ifdef PETSC_USE_COMPLEX 1798 SETERRQ(PetscObjectComm((PetscObject)vec), PETSC_ERR_SUP, "Does not work with complex numbers"); 1799 #else 1800 *n = displs[size]; 1801 PetscCall(PetscSortRemoveDupsReal(n, vals)); 1802 if (e) { 1803 PetscAssertPointer(e, 3); 1804 PetscCall(PetscMalloc1(*n, e)); 1805 for (i = 0; i < *n; ++i) (*e)[i] = vals[i]; 1806 } 1807 PetscCall(PetscFree2(vals, displs)); 1808 PetscCall(PetscFree2(tmp, N)); 1809 PetscFunctionReturn(PETSC_SUCCESS); 1810 #endif 1811 } 1812