1 #define PETSCVEC_DLL 2 3 /* 4 Some useful vector utility functions. 5 */ 6 #include "private/vecimpl.h" /*I "petscvec.h" I*/ 7 8 extern MPI_Op VecMax_Local_Op; 9 extern MPI_Op VecMin_Local_Op; 10 11 #undef __FUNCT__ 12 #define __FUNCT__ "VecStrideScale" 13 /*@ 14 VecStrideScale - Scales a subvector of a vector defined 15 by a starting point and a stride. 16 17 Collective on Vec 18 19 Input Parameter: 20 + v - the vector 21 . start - starting point of the subvector (defined by a stride) 22 - scale - value to multiply each subvector entry by 23 24 Notes: 25 One must call VecSetBlockSize() before this routine to set the stride 26 information, or use a vector created from a multicomponent DA. 27 28 This will only work if the desire subvector is a stride subvector 29 30 Level: advanced 31 32 Concepts: scale^on stride of vector 33 Concepts: stride^scale 34 35 .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideScale() 36 @*/ 37 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScale(Vec v,PetscInt start,PetscScalar *scale) 38 { 39 PetscErrorCode ierr; 40 PetscInt i,n,bs; 41 PetscScalar *x,xscale = *scale; 42 43 PetscFunctionBegin; 44 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 45 PetscValidScalarPointer(scale,3); 46 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 47 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 48 49 bs = v->bs; 50 if (start >= bs) { 51 SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\ 52 Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs); 53 } 54 x += start; 55 56 for (i=0; i<n; i+=bs) { 57 x[i] *= xscale; 58 } 59 x -= start; 60 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 61 PetscFunctionReturn(0); 62 } 63 64 #undef __FUNCT__ 65 #define __FUNCT__ "VecStrideNorm" 66 /*@ 67 VecStrideNorm - Computes the norm of subvector of a vector defined 68 by a starting point and a stride. 69 70 Collective on Vec 71 72 Input Parameter: 73 + v - the vector 74 . start - starting point of the subvector (defined by a stride) 75 - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY 76 77 Output Parameter: 78 . norm - the norm 79 80 Notes: 81 One must call VecSetBlockSize() before this routine to set the stride 82 information, or use a vector created from a multicomponent DA. 83 84 If x is the array representing the vector x then this computes the norm 85 of the array (x[start],x[start+stride],x[start+2*stride], ....) 86 87 This is useful for computing, say the norm of the pressure variable when 88 the pressure is stored (interlaced) with other variables, say density etc. 89 90 This will only work if the desire subvector is a stride subvector 91 92 Level: advanced 93 94 Concepts: norm^on stride of vector 95 Concepts: stride^norm 96 97 .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax() 98 @*/ 99 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideNorm(Vec v,PetscInt start,NormType ntype,PetscReal *nrm) 100 { 101 PetscErrorCode ierr; 102 PetscInt i,n,bs; 103 PetscScalar *x; 104 PetscReal tnorm; 105 MPI_Comm comm; 106 107 PetscFunctionBegin; 108 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 109 PetscValidDoublePointer(nrm,3); 110 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 111 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 112 ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr); 113 114 bs = v->bs; 115 if (start >= bs) { 116 SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\ 117 Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs); 118 } 119 x += start; 120 121 if (ntype == NORM_2) { 122 PetscScalar sum = 0.0; 123 for (i=0; i<n; i+=bs) { 124 sum += x[i]*(PetscConj(x[i])); 125 } 126 tnorm = PetscRealPart(sum); 127 ierr = MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);CHKERRQ(ierr); 128 *nrm = sqrt(*nrm); 129 } else if (ntype == NORM_1) { 130 tnorm = 0.0; 131 for (i=0; i<n; i+=bs) { 132 tnorm += PetscAbsScalar(x[i]); 133 } 134 ierr = MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);CHKERRQ(ierr); 135 } else if (ntype == NORM_INFINITY) { 136 PetscReal tmp; 137 tnorm = 0.0; 138 139 for (i=0; i<n; i+=bs) { 140 if ((tmp = PetscAbsScalar(x[i])) > tnorm) tnorm = tmp; 141 /* check special case of tmp == NaN */ 142 if (tmp != tmp) {tnorm = tmp; break;} 143 } 144 ierr = MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_MAX,comm);CHKERRQ(ierr); 145 } else { 146 SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type"); 147 } 148 149 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 150 PetscFunctionReturn(0); 151 } 152 153 #undef __FUNCT__ 154 #define __FUNCT__ "VecStrideMax" 155 /*@ 156 VecStrideMax - Computes the maximum of subvector of a vector defined 157 by a starting point and a stride and optionally its location. 158 159 Collective on Vec 160 161 Input Parameter: 162 + v - the vector 163 - start - starting point of the subvector (defined by a stride) 164 165 Output Parameter: 166 + index - the location where the maximum occurred (pass PETSC_NULL if not required) 167 - nrm - the max 168 169 Notes: 170 One must call VecSetBlockSize() before this routine to set the stride 171 information, or use a vector created from a multicomponent DA. 172 173 If xa is the array representing the vector x, then this computes the max 174 of the array (xa[start],xa[start+stride],xa[start+2*stride], ....) 175 176 This is useful for computing, say the maximum of the pressure variable when 177 the pressure is stored (interlaced) with other variables, e.g., density, etc. 178 This will only work if the desire subvector is a stride subvector. 179 180 Level: advanced 181 182 Concepts: maximum^on stride of vector 183 Concepts: stride^maximum 184 185 .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin() 186 @*/ 187 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMax(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm) 188 { 189 PetscErrorCode ierr; 190 PetscInt i,n,bs,id; 191 PetscScalar *x; 192 PetscReal max,tmp; 193 MPI_Comm comm; 194 195 PetscFunctionBegin; 196 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 197 PetscValidDoublePointer(nrm,3); 198 199 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 200 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 201 ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr); 202 203 bs = v->bs; 204 if (start >= bs) { 205 SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\ 206 Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs); 207 } 208 x += start; 209 210 id = -1; 211 if (!n) { 212 max = PETSC_MIN; 213 } else { 214 id = 0; 215 #if defined(PETSC_USE_COMPLEX) 216 max = PetscRealPart(x[0]); 217 #else 218 max = x[0]; 219 #endif 220 for (i=bs; i<n; i+=bs) { 221 #if defined(PETSC_USE_COMPLEX) 222 if ((tmp = PetscRealPart(x[i])) > max) { max = tmp; id = i;} 223 #else 224 if ((tmp = x[i]) > max) { max = tmp; id = i;} 225 #endif 226 } 227 } 228 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 229 230 if (!idex) { 231 ierr = MPI_Allreduce(&max,nrm,1,MPIU_REAL,MPI_MAX,comm);CHKERRQ(ierr); 232 } else { 233 PetscReal in[2],out[2]; 234 PetscInt rstart; 235 236 ierr = VecGetOwnershipRange(v,&rstart,PETSC_NULL);CHKERRQ(ierr); 237 in[0] = max; 238 in[1] = rstart+id; 239 ierr = MPI_Allreduce(in,out,2,MPIU_REAL,VecMax_Local_Op,v->comm);CHKERRQ(ierr); 240 *nrm = out[0]; 241 *idex = (PetscInt)out[1]; 242 } 243 244 PetscFunctionReturn(0); 245 } 246 247 #undef __FUNCT__ 248 #define __FUNCT__ "VecStrideMin" 249 /*@ 250 VecStrideMin - Computes the minimum of subvector of a vector defined 251 by a starting point and a stride and optionally its location. 252 253 Collective on Vec 254 255 Input Parameter: 256 + v - the vector 257 - start - starting point of the subvector (defined by a stride) 258 259 Output Parameter: 260 + idex - the location where the minimum occurred. (pass PETSC_NULL if not required) 261 - nrm - the min 262 263 Level: advanced 264 265 Notes: 266 One must call VecSetBlockSize() before this routine to set the stride 267 information, or use a vector created from a multicomponent DA. 268 269 If xa is the array representing the vector x, then this computes the min 270 of the array (xa[start],xa[start+stride],xa[start+2*stride], ....) 271 272 This is useful for computing, say the minimum of the pressure variable when 273 the pressure is stored (interlaced) with other variables, e.g., density, etc. 274 This will only work if the desire subvector is a stride subvector. 275 276 Concepts: minimum^on stride of vector 277 Concepts: stride^minimum 278 279 .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax() 280 @*/ 281 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMin(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm) 282 { 283 PetscErrorCode ierr; 284 PetscInt i,n,bs,id; 285 PetscScalar *x; 286 PetscReal min,tmp; 287 MPI_Comm comm; 288 289 PetscFunctionBegin; 290 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 291 PetscValidDoublePointer(nrm,4); 292 293 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 294 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 295 ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr); 296 297 bs = v->bs; 298 if (start >= bs) { 299 SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\ 300 Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs); 301 } 302 x += start; 303 304 id = -1; 305 if (!n) { 306 min = PETSC_MAX; 307 } else { 308 id = 0; 309 #if defined(PETSC_USE_COMPLEX) 310 min = PetscRealPart(x[0]); 311 #else 312 min = x[0]; 313 #endif 314 for (i=bs; i<n; i+=bs) { 315 #if defined(PETSC_USE_COMPLEX) 316 if ((tmp = PetscRealPart(x[i])) < min) { min = tmp; id = i;} 317 #else 318 if ((tmp = x[i]) < min) { min = tmp; id = i;} 319 #endif 320 } 321 } 322 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 323 324 if (!idex) { 325 ierr = MPI_Allreduce(&min,nrm,1,MPIU_REAL,MPI_MIN,comm);CHKERRQ(ierr); 326 } else { 327 PetscReal in[2],out[2]; 328 PetscInt rstart; 329 330 ierr = VecGetOwnershipRange(v,&rstart,PETSC_NULL);CHKERRQ(ierr); 331 in[0] = min; 332 in[1] = rstart+id; 333 ierr = MPI_Allreduce(in,out,2,MPIU_REAL,VecMin_Local_Op,v->comm);CHKERRQ(ierr); 334 *nrm = out[0]; 335 *idex = (PetscInt)out[1]; 336 } 337 338 PetscFunctionReturn(0); 339 } 340 341 #undef __FUNCT__ 342 #define __FUNCT__ "VecStrideScaleAll" 343 /*@ 344 VecStrideScaleAll - Scales the subvectors of a vector defined 345 by a starting point and a stride. 346 347 Collective on Vec 348 349 Input Parameter: 350 + v - the vector 351 - scales - values to multiply each subvector entry by 352 353 Notes: 354 One must call VecSetBlockSize() before this routine to set the stride 355 information, or use a vector created from a multicomponent DA. 356 357 358 Level: advanced 359 360 Concepts: scale^on stride of vector 361 Concepts: stride^scale 362 363 .seealso: VecNorm(), VecStrideScale(), VecScale(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax() 364 @*/ 365 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScaleAll(Vec v,PetscScalar *scales) 366 { 367 PetscErrorCode ierr; 368 PetscInt i,j,n,bs; 369 PetscScalar *x; 370 371 PetscFunctionBegin; 372 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 373 PetscValidScalarPointer(scales,2); 374 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 375 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 376 377 bs = v->bs; 378 379 /* need to provide optimized code for each bs */ 380 for (i=0; i<n; i+=bs) { 381 for (j=0; j<bs; j++) { 382 x[i+j] *= scales[j]; 383 } 384 } 385 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 386 PetscFunctionReturn(0); 387 } 388 389 #undef __FUNCT__ 390 #define __FUNCT__ "VecStrideNormAll" 391 /*@ 392 VecStrideNormAll - Computes the norms subvectors of a vector defined 393 by a starting point and a stride. 394 395 Collective on Vec 396 397 Input Parameter: 398 + v - the vector 399 - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY 400 401 Output Parameter: 402 . nrm - the norms 403 404 Notes: 405 One must call VecSetBlockSize() before this routine to set the stride 406 information, or use a vector created from a multicomponent DA. 407 408 If x is the array representing the vector x then this computes the norm 409 of the array (x[start],x[start+stride],x[start+2*stride], ....) 410 411 This is useful for computing, say the norm of the pressure variable when 412 the pressure is stored (interlaced) with other variables, say density etc. 413 414 This will only work if the desire subvector is a stride subvector 415 416 Level: advanced 417 418 Concepts: norm^on stride of vector 419 Concepts: stride^norm 420 421 .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax() 422 @*/ 423 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideNormAll(Vec v,NormType ntype,PetscReal *nrm) 424 { 425 PetscErrorCode ierr; 426 PetscInt i,j,n,bs; 427 PetscScalar *x; 428 PetscReal tnorm[128]; 429 MPI_Comm comm; 430 431 PetscFunctionBegin; 432 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 433 PetscValidDoublePointer(nrm,3); 434 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 435 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 436 ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr); 437 438 bs = v->bs; 439 if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128"); 440 441 if (ntype == NORM_2) { 442 PetscScalar sum[128]; 443 for (j=0; j<bs; j++) sum[j] = 0.0; 444 for (i=0; i<n; i+=bs) { 445 for (j=0; j<bs; j++) { 446 sum[j] += x[i+j]*(PetscConj(x[i+j])); 447 } 448 } 449 for (j=0; j<bs; j++) { 450 tnorm[j] = PetscRealPart(sum[j]); 451 } 452 ierr = MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);CHKERRQ(ierr); 453 for (j=0; j<bs; j++) { 454 nrm[j] = sqrt(nrm[j]); 455 } 456 } else if (ntype == NORM_1) { 457 for (j=0; j<bs; j++) { 458 tnorm[j] = 0.0; 459 } 460 for (i=0; i<n; i+=bs) { 461 for (j=0; j<bs; j++) { 462 tnorm[j] += PetscAbsScalar(x[i+j]); 463 } 464 } 465 ierr = MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);CHKERRQ(ierr); 466 } else if (ntype == NORM_INFINITY) { 467 PetscReal tmp; 468 for (j=0; j<bs; j++) { 469 tnorm[j] = 0.0; 470 } 471 472 for (i=0; i<n; i+=bs) { 473 for (j=0; j<bs; j++) { 474 if ((tmp = PetscAbsScalar(x[i+j])) > tnorm[j]) tnorm[j] = tmp; 475 /* check special case of tmp == NaN */ 476 if (tmp != tmp) {tnorm[j] = tmp; break;} 477 } 478 } 479 ierr = MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_MAX,comm);CHKERRQ(ierr); 480 } else { 481 SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type"); 482 } 483 484 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 485 PetscFunctionReturn(0); 486 } 487 488 #undef __FUNCT__ 489 #define __FUNCT__ "VecStrideMaxAll" 490 /*@ 491 VecStrideMaxAll - Computes the maximums of subvectors of a vector defined 492 by a starting point and a stride and optionally its location. 493 494 Collective on Vec 495 496 Input Parameter: 497 . v - the vector 498 499 Output Parameter: 500 + index - the location where the maximum occurred (not supported, pass PETSC_NULL, 501 if you need this, send mail to petsc-maint@mcs.anl.gov to request it) 502 - nrm - the maximums 503 504 Notes: 505 One must call VecSetBlockSize() before this routine to set the stride 506 information, or use a vector created from a multicomponent DA. 507 508 This is useful for computing, say the maximum of the pressure variable when 509 the pressure is stored (interlaced) with other variables, e.g., density, etc. 510 This will only work if the desire subvector is a stride subvector. 511 512 Level: advanced 513 514 Concepts: maximum^on stride of vector 515 Concepts: stride^maximum 516 517 .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin() 518 @*/ 519 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMaxAll(Vec v,PetscInt *idex,PetscReal *nrm) 520 { 521 PetscErrorCode ierr; 522 PetscInt i,j,n,bs; 523 PetscScalar *x; 524 PetscReal max[128],tmp; 525 MPI_Comm comm; 526 527 PetscFunctionBegin; 528 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 529 PetscValidDoublePointer(nrm,3); 530 if (idex) { 531 SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it"); 532 } 533 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 534 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 535 ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr); 536 537 bs = v->bs; 538 if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128"); 539 540 if (!n) { 541 for (j=0; j<bs; j++) { 542 max[j] = PETSC_MIN; 543 } 544 } else { 545 for (j=0; j<bs; j++) { 546 #if defined(PETSC_USE_COMPLEX) 547 max[j] = PetscRealPart(x[j]); 548 #else 549 max[j] = x[j]; 550 #endif 551 } 552 for (i=bs; i<n; i+=bs) { 553 for (j=0; j<bs; j++) { 554 #if defined(PETSC_USE_COMPLEX) 555 if ((tmp = PetscRealPart(x[i+j])) > max[j]) { max[j] = tmp;} 556 #else 557 if ((tmp = x[i+j]) > max[j]) { max[j] = tmp; } 558 #endif 559 } 560 } 561 } 562 ierr = MPI_Allreduce(max,nrm,bs,MPIU_REAL,MPI_MAX,comm);CHKERRQ(ierr); 563 564 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 565 PetscFunctionReturn(0); 566 } 567 568 #undef __FUNCT__ 569 #define __FUNCT__ "VecStrideMinAll" 570 /*@ 571 VecStrideMinAll - Computes the minimum of subvector of a vector defined 572 by a starting point and a stride and optionally its location. 573 574 Collective on Vec 575 576 Input Parameter: 577 . v - the vector 578 579 Output Parameter: 580 + idex - the location where the minimum occurred (not supported, pass PETSC_NULL, 581 if you need this, send mail to petsc-maint@mcs.anl.gov to request it) 582 - nrm - the minimums 583 584 Level: advanced 585 586 Notes: 587 One must call VecSetBlockSize() before this routine to set the stride 588 information, or use a vector created from a multicomponent DA. 589 590 This is useful for computing, say the minimum of the pressure variable when 591 the pressure is stored (interlaced) with other variables, e.g., density, etc. 592 This will only work if the desire subvector is a stride subvector. 593 594 Concepts: minimum^on stride of vector 595 Concepts: stride^minimum 596 597 .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax() 598 @*/ 599 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMinAll(Vec v,PetscInt *idex,PetscReal *nrm) 600 { 601 PetscErrorCode ierr; 602 PetscInt i,n,bs,j; 603 PetscScalar *x; 604 PetscReal min[128],tmp; 605 MPI_Comm comm; 606 607 PetscFunctionBegin; 608 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 609 PetscValidDoublePointer(nrm,3); 610 if (idex) { 611 SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it"); 612 } 613 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 614 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 615 ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr); 616 617 bs = v->bs; 618 if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128"); 619 620 if (!n) { 621 for (j=0; j<bs; j++) { 622 min[j] = PETSC_MAX; 623 } 624 } else { 625 for (j=0; j<bs; j++) { 626 #if defined(PETSC_USE_COMPLEX) 627 min[j] = PetscRealPart(x[j]); 628 #else 629 min[j] = x[j]; 630 #endif 631 } 632 for (i=bs; i<n; i+=bs) { 633 for (j=0; j<bs; j++) { 634 #if defined(PETSC_USE_COMPLEX) 635 if ((tmp = PetscRealPart(x[i+j])) < min[j]) { min[j] = tmp;} 636 #else 637 if ((tmp = x[i+j]) < min[j]) { min[j] = tmp; } 638 #endif 639 } 640 } 641 } 642 ierr = MPI_Allreduce(min,nrm,bs,MPIU_REAL,MPI_MIN,comm);CHKERRQ(ierr); 643 644 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 645 PetscFunctionReturn(0); 646 } 647 648 /*----------------------------------------------------------------------------------------------*/ 649 #undef __FUNCT__ 650 #define __FUNCT__ "VecStrideGatherAll" 651 /*@ 652 VecStrideGatherAll - Gathers all the single components from a multi-component vector into 653 separate vectors. 654 655 Collective on Vec 656 657 Input Parameter: 658 + v - the vector 659 - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES 660 661 Output Parameter: 662 . s - the location where the subvectors are stored 663 664 Notes: 665 One must call VecSetBlockSize() before this routine to set the stride 666 information, or use a vector created from a multicomponent DA. 667 668 If x is the array representing the vector x then this gathers 669 the arrays (x[start],x[start+stride],x[start+2*stride], ....) 670 for start=0,1,2,...bs-1 671 672 The parallel layout of the vector and the subvector must be the same; 673 i.e., nlocal of v = stride*(nlocal of s) 674 675 Not optimized; could be easily 676 677 Level: advanced 678 679 Concepts: gather^into strided vector 680 681 .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(), 682 VecStrideScatterAll() 683 @*/ 684 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideGatherAll(Vec v,Vec *s,InsertMode addv) 685 { 686 PetscErrorCode ierr; 687 PetscInt i,n,bs,j,k,*bss,nv,jj,nvc; 688 PetscScalar *x,**y; 689 690 PetscFunctionBegin; 691 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 692 PetscValidPointer(s,2); 693 PetscValidHeaderSpecific(*s,VEC_COOKIE,2); 694 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 695 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 696 bs = v->bs; 697 if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set"); 698 699 ierr = PetscMalloc2(bs,PetscReal*,&y,bs,PetscInt,&bss);CHKERRQ(ierr); 700 nv = 0; 701 nvc = 0; 702 for (i=0; i<bs; i++) { 703 ierr = VecGetBlockSize(s[i],&bss[i]);CHKERRQ(ierr); 704 if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */ 705 ierr = VecGetArray(s[i],&y[i]);CHKERRQ(ierr); 706 nvc += bss[i]; 707 nv++; 708 if (nvc > bs) SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector"); 709 if (nvc == bs) break; 710 } 711 712 n = n/bs; 713 714 jj = 0; 715 if (addv == INSERT_VALUES) { 716 for (j=0; j<nv; j++) { 717 for (k=0; k<bss[j]; k++) { 718 for (i=0; i<n; i++) { 719 y[j][i*bss[j] + k] = x[bs*i+jj+k]; 720 } 721 } 722 jj += bss[j]; 723 } 724 } else if (addv == ADD_VALUES) { 725 for (j=0; j<nv; j++) { 726 for (k=0; k<bss[j]; k++) { 727 for (i=0; i<n; i++) { 728 y[j][i*bss[j] + k] += x[bs*i+jj+k]; 729 } 730 } 731 jj += bss[j]; 732 } 733 #if !defined(PETSC_USE_COMPLEX) 734 } else if (addv == MAX_VALUES) { 735 for (j=0; j<nv; j++) { 736 for (k=0; k<bss[j]; k++) { 737 for (i=0; i<n; i++) { 738 y[j][i*bss[j] + k] = PetscMax(y[j][i*bss[j] + k],x[bs*i+jj+k]); 739 } 740 } 741 jj += bss[j]; 742 } 743 #endif 744 } else { 745 SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type"); 746 } 747 748 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 749 for (i=0; i<nv; i++) { 750 ierr = VecRestoreArray(s[i],&y[i]);CHKERRQ(ierr); 751 } 752 ierr = PetscFree2(y,bss);CHKERRQ(ierr); 753 PetscFunctionReturn(0); 754 } 755 756 #undef __FUNCT__ 757 #define __FUNCT__ "VecStrideScatterAll" 758 /*@ 759 VecStrideScatterAll - Scatters all the single components from separate vectors into 760 a multi-component vector. 761 762 Collective on Vec 763 764 Input Parameter: 765 + s - the location where the subvectors are stored 766 - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES 767 768 Output Parameter: 769 . v - the multicomponent vector 770 771 Notes: 772 One must call VecSetBlockSize() before this routine to set the stride 773 information, or use a vector created from a multicomponent DA. 774 775 The parallel layout of the vector and the subvector must be the same; 776 i.e., nlocal of v = stride*(nlocal of s) 777 778 Not optimized; could be easily 779 780 Level: advanced 781 782 Concepts: scatter^into strided vector 783 784 .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(), 785 VecStrideScatterAll() 786 @*/ 787 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScatterAll(Vec *s,Vec v,InsertMode addv) 788 { 789 PetscErrorCode ierr; 790 PetscInt i,n,bs,j,jj,k,*bss,nv,nvc; 791 PetscScalar *x,**y; 792 793 PetscFunctionBegin; 794 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 795 PetscValidPointer(s,2); 796 PetscValidHeaderSpecific(*s,VEC_COOKIE,2); 797 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 798 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 799 bs = v->bs; 800 if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set"); 801 802 ierr = PetscMalloc2(bs,PetscScalar**,&y,bs,PetscInt,&bss);CHKERRQ(ierr); 803 nv = 0; 804 nvc = 0; 805 for (i=0; i<bs; i++) { 806 ierr = VecGetBlockSize(s[i],&bss[i]);CHKERRQ(ierr); 807 if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */ 808 ierr = VecGetArray(s[i],&y[i]);CHKERRQ(ierr); 809 nvc += bss[i]; 810 nv++; 811 if (nvc > bs) SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector"); 812 if (nvc == bs) break; 813 } 814 815 n = n/bs; 816 817 jj = 0; 818 if (addv == INSERT_VALUES) { 819 for (j=0; j<nv; j++) { 820 for (k=0; k<bss[j]; k++) { 821 for (i=0; i<n; i++) { 822 x[bs*i+jj+k] = y[j][i*bss[j] + k]; 823 } 824 } 825 jj += bss[j]; 826 } 827 } else if (addv == ADD_VALUES) { 828 for (j=0; j<nv; j++) { 829 for (k=0; k<bss[j]; k++) { 830 for (i=0; i<n; i++) { 831 x[bs*i+jj+k] += y[j][i*bss[j] + k]; 832 } 833 } 834 jj += bss[j]; 835 } 836 #if !defined(PETSC_USE_COMPLEX) 837 } else if (addv == MAX_VALUES) { 838 for (j=0; j<nv; j++) { 839 for (k=0; k<bss[j]; k++) { 840 for (i=0; i<n; i++) { 841 x[bs*i+jj+k] = PetscMax(x[bs*i+jj+k],y[j][i*bss[j] + k]); 842 } 843 } 844 jj += bss[j]; 845 } 846 #endif 847 } else { 848 SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type"); 849 } 850 851 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 852 for (i=0; i<nv; i++) { 853 ierr = VecRestoreArray(s[i],&y[i]);CHKERRQ(ierr); 854 } 855 ierr = PetscFree2(y,bss);CHKERRQ(ierr); 856 PetscFunctionReturn(0); 857 } 858 859 #undef __FUNCT__ 860 #define __FUNCT__ "VecStrideGather" 861 /*@ 862 VecStrideGather - Gathers a single component from a multi-component vector into 863 another vector. 864 865 Collective on Vec 866 867 Input Parameter: 868 + v - the vector 869 . start - starting point of the subvector (defined by a stride) 870 - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES 871 872 Output Parameter: 873 . s - the location where the subvector is stored 874 875 Notes: 876 One must call VecSetBlockSize() before this routine to set the stride 877 information, or use a vector created from a multicomponent DA. 878 879 If x is the array representing the vector x then this gathers 880 the array (x[start],x[start+stride],x[start+2*stride], ....) 881 882 The parallel layout of the vector and the subvector must be the same; 883 i.e., nlocal of v = stride*(nlocal of s) 884 885 Not optimized; could be easily 886 887 Level: advanced 888 889 Concepts: gather^into strided vector 890 891 .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(), 892 VecStrideScatterAll() 893 @*/ 894 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideGather(Vec v,PetscInt start,Vec s,InsertMode addv) 895 { 896 PetscErrorCode ierr; 897 PetscInt i,n,bs,ns; 898 PetscScalar *x,*y; 899 900 PetscFunctionBegin; 901 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 902 PetscValidHeaderSpecific(s,VEC_COOKIE,3); 903 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 904 ierr = VecGetLocalSize(s,&ns);CHKERRQ(ierr); 905 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 906 ierr = VecGetArray(s,&y);CHKERRQ(ierr); 907 908 bs = v->bs; 909 if (start >= bs) { 910 SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\ 911 Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs); 912 } 913 if (n != ns*bs) { 914 SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for gather from original vector %D",ns*bs,n); 915 } 916 x += start; 917 n = n/bs; 918 919 if (addv == INSERT_VALUES) { 920 for (i=0; i<n; i++) { 921 y[i] = x[bs*i]; 922 } 923 } else if (addv == ADD_VALUES) { 924 for (i=0; i<n; i++) { 925 y[i] += x[bs*i]; 926 } 927 #if !defined(PETSC_USE_COMPLEX) 928 } else if (addv == MAX_VALUES) { 929 for (i=0; i<n; i++) { 930 y[i] = PetscMax(y[i],x[bs*i]); 931 } 932 #endif 933 } else { 934 SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type"); 935 } 936 937 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 938 ierr = VecRestoreArray(s,&y);CHKERRQ(ierr); 939 PetscFunctionReturn(0); 940 } 941 942 #undef __FUNCT__ 943 #define __FUNCT__ "VecStrideScatter" 944 /*@ 945 VecStrideScatter - Scatters a single component from a vector into a multi-component vector. 946 947 Collective on Vec 948 949 Input Parameter: 950 + s - the single-component vector 951 . start - starting point of the subvector (defined by a stride) 952 - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES 953 954 Output Parameter: 955 . v - the location where the subvector is scattered (the multi-component vector) 956 957 Notes: 958 One must call VecSetBlockSize() on the multi-component vector before this 959 routine to set the stride information, or use a vector created from a multicomponent DA. 960 961 The parallel layout of the vector and the subvector must be the same; 962 i.e., nlocal of v = stride*(nlocal of s) 963 964 Not optimized; could be easily 965 966 Level: advanced 967 968 Concepts: scatter^into strided vector 969 970 .seealso: VecStrideNorm(), VecStrideGather(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(), 971 VecStrideScatterAll() 972 @*/ 973 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScatter(Vec s,PetscInt start,Vec v,InsertMode addv) 974 { 975 PetscErrorCode ierr; 976 PetscInt i,n,bs,ns; 977 PetscScalar *x,*y; 978 979 PetscFunctionBegin; 980 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 981 PetscValidHeaderSpecific(s,VEC_COOKIE,3); 982 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 983 ierr = VecGetLocalSize(s,&ns);CHKERRQ(ierr); 984 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 985 ierr = VecGetArray(s,&y);CHKERRQ(ierr); 986 987 bs = v->bs; 988 if (start >= bs) { 989 SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\ 990 Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs); 991 } 992 if (n != ns*bs) { 993 SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for scatter to multicomponent vector %D",ns*bs,n); 994 } 995 x += start; 996 n = n/bs; 997 998 999 if (addv == INSERT_VALUES) { 1000 for (i=0; i<n; i++) { 1001 x[bs*i] = y[i]; 1002 } 1003 } else if (addv == ADD_VALUES) { 1004 for (i=0; i<n; i++) { 1005 x[bs*i] += y[i]; 1006 } 1007 #if !defined(PETSC_USE_COMPLEX) 1008 } else if (addv == MAX_VALUES) { 1009 for (i=0; i<n; i++) { 1010 x[bs*i] = PetscMax(y[i],x[bs*i]); 1011 } 1012 #endif 1013 } else { 1014 SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type"); 1015 } 1016 1017 1018 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1019 ierr = VecRestoreArray(s,&y);CHKERRQ(ierr); 1020 PetscFunctionReturn(0); 1021 } 1022 1023 #undef __FUNCT__ 1024 #define __FUNCT__ "VecReciprocal_Default" 1025 PetscErrorCode VecReciprocal_Default(Vec v) 1026 { 1027 PetscErrorCode ierr; 1028 PetscInt i,n; 1029 PetscScalar *x; 1030 1031 PetscFunctionBegin; 1032 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 1033 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 1034 for (i=0; i<n; i++) { 1035 if (x[i] != 0.0) x[i] = 1.0/x[i]; 1036 } 1037 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1038 PetscFunctionReturn(0); 1039 } 1040 1041 #undef __FUNCT__ 1042 #define __FUNCT__ "VecSqrt" 1043 /*@ 1044 VecSqrt - Replaces each component of a vector by the square root of its magnitude. 1045 1046 Not collective 1047 1048 Input Parameter: 1049 . v - The vector 1050 1051 Output Parameter: 1052 . v - The vector square root 1053 1054 Level: beginner 1055 1056 Note: The actual function is sqrt(|x_i|) 1057 1058 .keywords: vector, sqrt, square root 1059 @*/ 1060 PetscErrorCode PETSCVEC_DLLEXPORT VecSqrt(Vec v) 1061 { 1062 PetscScalar *x; 1063 PetscInt i, n; 1064 PetscErrorCode ierr; 1065 1066 PetscFunctionBegin; 1067 PetscValidHeaderSpecific(v, VEC_COOKIE,1); 1068 ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr); 1069 ierr = VecGetArray(v, &x);CHKERRQ(ierr); 1070 for(i = 0; i < n; i++) { 1071 x[i] = sqrt(PetscAbsScalar(x[i])); 1072 } 1073 ierr = VecRestoreArray(v, &x);CHKERRQ(ierr); 1074 PetscFunctionReturn(0); 1075 } 1076 1077 #undef __FUNCT__ 1078 #define __FUNCT__ "VecSum" 1079 /*@ 1080 VecSum - Computes the sum of all the components of a vector. 1081 1082 Collective on Vec 1083 1084 Input Parameter: 1085 . v - the vector 1086 1087 Output Parameter: 1088 . sum - the result 1089 1090 Level: beginner 1091 1092 Concepts: sum^of vector entries 1093 1094 .seealso: VecNorm() 1095 @*/ 1096 PetscErrorCode PETSCVEC_DLLEXPORT VecSum(Vec v,PetscScalar *sum) 1097 { 1098 PetscErrorCode ierr; 1099 PetscInt i,n; 1100 PetscScalar *x,lsum = 0.0; 1101 1102 PetscFunctionBegin; 1103 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 1104 PetscValidScalarPointer(sum,2); 1105 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 1106 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 1107 for (i=0; i<n; i++) { 1108 lsum += x[i]; 1109 } 1110 ierr = MPI_Allreduce(&lsum,sum,1,MPIU_SCALAR,PetscSum_Op,v->comm);CHKERRQ(ierr); 1111 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1112 PetscFunctionReturn(0); 1113 } 1114 1115 #undef __FUNCT__ 1116 #define __FUNCT__ "VecShift" 1117 /*@ 1118 VecShift - Shifts all of the components of a vector by computing 1119 x[i] = x[i] + shift. 1120 1121 Collective on Vec 1122 1123 Input Parameters: 1124 + v - the vector 1125 - shift - the shift 1126 1127 Output Parameter: 1128 . v - the shifted vector 1129 1130 Level: intermediate 1131 1132 Concepts: vector^adding constant 1133 1134 @*/ 1135 PetscErrorCode PETSCVEC_DLLEXPORT VecShift(Vec v,PetscScalar shift) 1136 { 1137 PetscErrorCode ierr; 1138 PetscInt i,n; 1139 PetscScalar *x; 1140 1141 PetscFunctionBegin; 1142 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 1143 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 1144 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 1145 for (i=0; i<n; i++) { 1146 x[i] += shift; 1147 } 1148 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1149 PetscFunctionReturn(0); 1150 } 1151 1152 #undef __FUNCT__ 1153 #define __FUNCT__ "VecAbs" 1154 /*@ 1155 VecAbs - Replaces every element in a vector with its absolute value. 1156 1157 Collective on Vec 1158 1159 Input Parameters: 1160 . v - the vector 1161 1162 Level: intermediate 1163 1164 Concepts: vector^absolute value 1165 1166 @*/ 1167 PetscErrorCode PETSCVEC_DLLEXPORT VecAbs(Vec v) 1168 { 1169 PetscErrorCode ierr; 1170 PetscInt i,n; 1171 PetscScalar *x; 1172 1173 PetscFunctionBegin; 1174 PetscValidHeaderSpecific(v,VEC_COOKIE,1); 1175 ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr); 1176 ierr = VecGetArray(v,&x);CHKERRQ(ierr); 1177 for (i=0; i<n; i++) { 1178 x[i] = PetscAbsScalar(x[i]); 1179 } 1180 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1181 PetscFunctionReturn(0); 1182 } 1183 1184 #undef __FUNCT__ 1185 #define __FUNCT__ "VecPermute" 1186 /*@ 1187 VecPermute - Permutes a vector in place using the given ordering. 1188 1189 Input Parameters: 1190 + vec - The vector 1191 . order - The ordering 1192 - inv - The flag for inverting the permutation 1193 1194 Level: beginner 1195 1196 Note: This function does not yet support parallel Index Sets 1197 1198 .seealso: MatPermute() 1199 .keywords: vec, permute 1200 @*/ 1201 PetscErrorCode PETSCVEC_DLLEXPORT VecPermute(Vec x, IS row, PetscTruth inv) 1202 { 1203 PetscScalar *array, *newArray; 1204 PetscInt *idx; 1205 PetscInt i; 1206 PetscErrorCode ierr; 1207 1208 PetscFunctionBegin; 1209 ierr = ISGetIndices(row, &idx);CHKERRQ(ierr); 1210 ierr = VecGetArray(x, &array);CHKERRQ(ierr); 1211 ierr = PetscMalloc(x->n*sizeof(PetscScalar), &newArray);CHKERRQ(ierr); 1212 #ifdef PETSC_USE_DEBUG 1213 for(i = 0; i < x->n; i++) { 1214 if ((idx[i] < 0) || (idx[i] >= x->n)) { 1215 SETERRQ2(PETSC_ERR_ARG_CORRUPT, "Permutation index %D is out of bounds: %D", i, idx[i]); 1216 } 1217 } 1218 #endif 1219 if (!inv) { 1220 for(i = 0; i < x->n; i++) newArray[i] = array[idx[i]]; 1221 } else { 1222 for(i = 0; i < x->n; i++) newArray[idx[i]] = array[i]; 1223 } 1224 ierr = VecRestoreArray(x, &array);CHKERRQ(ierr); 1225 ierr = ISRestoreIndices(row, &idx);CHKERRQ(ierr); 1226 ierr = VecReplaceArray(x, newArray);CHKERRQ(ierr); 1227 PetscFunctionReturn(0); 1228 } 1229 1230 #undef __FUNCT__ 1231 #define __FUNCT__ "VecEqual" 1232 /*@ 1233 VecEqual - Compares two vectors. 1234 1235 Collective on Vec 1236 1237 Input Parameters: 1238 + vec1 - the first matrix 1239 - vec2 - the second matrix 1240 1241 Output Parameter: 1242 . flg - PETSC_TRUE if the vectors are equal; PETSC_FALSE otherwise. 1243 1244 Level: intermediate 1245 1246 Concepts: equal^two vectors 1247 Concepts: vector^equality 1248 1249 @*/ 1250 PetscErrorCode PETSCVEC_DLLEXPORT VecEqual(Vec vec1,Vec vec2,PetscTruth *flg) 1251 { 1252 PetscScalar *v1,*v2; 1253 PetscErrorCode ierr; 1254 PetscInt n1,n2,N1,N2; 1255 PetscInt state1,state2; 1256 PetscTruth flg1; 1257 1258 PetscFunctionBegin; 1259 PetscValidHeaderSpecific(vec1,VEC_COOKIE,1); 1260 PetscValidHeaderSpecific(vec2,VEC_COOKIE,2); 1261 PetscValidPointer(flg,3); 1262 if (vec1 == vec2) { 1263 *flg = PETSC_TRUE; 1264 } else { 1265 ierr = VecGetSize(vec1,&N1);CHKERRQ(ierr); 1266 ierr = VecGetSize(vec2,&N2);CHKERRQ(ierr); 1267 if (N1 != N2) { 1268 flg1 = PETSC_FALSE; 1269 } else { 1270 ierr = VecGetLocalSize(vec1,&n1);CHKERRQ(ierr); 1271 ierr = VecGetLocalSize(vec2,&n2);CHKERRQ(ierr); 1272 if (n1 != n2) { 1273 flg1 = PETSC_FALSE; 1274 } else { 1275 ierr = PetscObjectStateQuery((PetscObject) vec1,&state1);CHKERRQ(ierr); 1276 ierr = PetscObjectStateQuery((PetscObject) vec2,&state2);CHKERRQ(ierr); 1277 ierr = VecGetArray(vec1,&v1);CHKERRQ(ierr); 1278 ierr = VecGetArray(vec2,&v2);CHKERRQ(ierr); 1279 ierr = PetscMemcmp(v1,v2,n1*sizeof(PetscScalar),&flg1);CHKERRQ(ierr); 1280 ierr = VecRestoreArray(vec1,&v1);CHKERRQ(ierr); 1281 ierr = VecRestoreArray(vec2,&v2);CHKERRQ(ierr); 1282 ierr = PetscObjectSetState((PetscObject) vec1,state1);CHKERRQ(ierr); 1283 ierr = PetscObjectSetState((PetscObject) vec2,state2);CHKERRQ(ierr); 1284 } 1285 } 1286 /* combine results from all processors */ 1287 ierr = MPI_Allreduce(&flg1,flg,1,MPI_INT,MPI_MIN,vec1->comm);CHKERRQ(ierr); 1288 } 1289 PetscFunctionReturn(0); 1290 } 1291 1292 1293 1294