Subversion Repositories slepc-dev

Rev

Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2339 jroman 1
/*
2
   Subroutines related to special Vecs that share a common contiguous storage.
3
 
4
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5
   SLEPc - Scalable Library for Eigenvalue Problem Computations
6
   Copyright (c) 2002-2010, Universidad Politecnica de Valencia, Spain
7
 
8
   This file is part of SLEPc.
9
 
10
   SLEPc is free software: you can redistribute it and/or modify it under  the
11
   terms of version 3 of the GNU Lesser General Public License as published by
12
   the Free Software Foundation.
13
 
14
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
15
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
16
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
17
   more details.
18
 
19
   You  should have received a copy of the GNU Lesser General  Public  License
20
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
21
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22
*/
23
 
2341 jroman 24
#include <private/vecimplslepc.h>            /*I "slepcvec.h" I*/
2340 jroman 25
#include <petscblaslapack.h>
2339 jroman 26
 
2340 jroman 27
PetscLogEvent SLEPC_UpdateVectors = 0,SLEPC_VecMAXPBY = 0;
28
 
2339 jroman 29
#undef __FUNCT__
30
#define __FUNCT__ "Vecs_ContiguousDestroy"
31
/*
32
  Frees the array of the contiguous vectors when all vectors have been destroyed.
33
*/
34
static PetscErrorCode Vecs_ContiguousDestroy(void *ctx)
35
{
36
  PetscErrorCode  ierr;
37
  Vecs_Contiguous *vc = (Vecs_Contiguous*)ctx;
38
 
39
  PetscFunctionBegin;
40
  ierr = PetscFree(vc->array);CHKERRQ(ierr);
41
  ierr = PetscFree(vc);CHKERRQ(ierr);
42
  PetscFunctionReturn(0);
43
}
44
 
2410 jroman 45
#undef __FUNCT__
46
#define __FUNCT__ "VecDuplicateVecs_Contiguous"
47
/*
48
  Version of VecDuplicateVecs that sets contiguous storage.
49
*/
50
static PetscErrorCode VecDuplicateVecs_Contiguous(Vec v,PetscInt m,Vec *V[])
2339 jroman 51
{
52
  PetscErrorCode  ierr;
53
  PetscInt        i,nloc;
54
  PetscScalar     *pV;
55
  PetscContainer  container;
56
  Vecs_Contiguous *vc;
57
 
58
  PetscFunctionBegin;
59
  /* Allocate array */
60
  ierr = VecGetLocalSize(v,&nloc);CHKERRQ(ierr);
61
  ierr = PetscMalloc(m*nloc*sizeof(PetscScalar),&pV);CHKERRQ(ierr);
62
  /* Create container */
63
  ierr = PetscNew(Vecs_Contiguous,&vc);CHKERRQ(ierr);
64
  vc->nvecs = m;
65
  vc->array = pV;
66
  ierr = PetscContainerCreate(((PetscObject)v)->comm,&container);CHKERRQ(ierr);
67
  ierr = PetscContainerSetPointer(container,vc);CHKERRQ(ierr);
68
  ierr = PetscContainerSetUserDestroy(container,Vecs_ContiguousDestroy);CHKERRQ(ierr);
69
  /* Create vectors */
70
  ierr = PetscMalloc(m*sizeof(Vec),V);CHKERRQ(ierr);
71
  for (i=0;i<m;i++) {
72
    ierr = VecCreateMPIWithArray(((PetscObject)v)->comm,nloc,PETSC_DECIDE,pV+i*nloc,*V+i);CHKERRQ(ierr);
73
    ierr = PetscObjectCompose((PetscObject)*(*V+i),"contiguous",(PetscObject)container);CHKERRQ(ierr);
74
  }
75
  ierr = PetscContainerDestroy(&container);CHKERRQ(ierr);
76
  PetscFunctionReturn(0);
77
}
78
 
79
#undef __FUNCT__  
2410 jroman 80
#define __FUNCT__ "SlepcVecSetTemplate"
2339 jroman 81
/*@
2410 jroman 82
   SlepcVecSetTemplate - Sets a vector as a template for contiguous storage.
2339 jroman 83
 
84
   Collective on Vec
85
 
86
   Input Parameters:
2410 jroman 87
.  v - the vector
2339 jroman 88
 
2410 jroman 89
   Note:
90
   Once this function is called, subsequent calls to VecDuplicateVecs()
91
   with this vector will use a special version that generates vectors with
92
   contiguous storage, that is, the array of values of V[1] immediately
93
   follows the array of V[0], and so on.
94
 
2339 jroman 95
   Level: developer
2410 jroman 96
@*/
97
PetscErrorCode SlepcVecSetTemplate(Vec v)
98
{
99
  PetscErrorCode ierr;
100
  PetscBool      flg;
2339 jroman 101
 
2410 jroman 102
  PetscFunctionBegin;
103
  PetscValidHeaderSpecific(v,VEC_CLASSID,1);
104
  ierr = PetscTypeCompareAny((PetscObject)v,&flg,VECSEQ,VECMPI,"");CHKERRQ(ierr);
105
  if (!flg) SETERRQ(((PetscObject)v)->comm,PETSC_ERR_SUP,"Only available for standard vectors (VECSEQ or VECMPI)");
106
  v->ops->duplicatevecs = VecDuplicateVecs_Contiguous;
107
  PetscFunctionReturn(0);
108
}
109
 
110
#undef __FUNCT__  
111
#define __FUNCT__ "SlepcMatGetVecsTemplate"
112
/*@
113
   SlepcMatGetVecsTemplate - Get vectors compatible with a matrix,
114
   i.e. with the same parallel layout, and mark them as templates
115
   for contiguous storage.
116
 
117
   Collective on Mat
118
 
119
   Input Parameter:
120
.  mat - the matrix
121
 
122
   Output Parameters:
123
+  right - (optional) vector that the matrix can be multiplied against
124
-  left  - (optional) vector that the matrix vector product can be stored in
125
 
126
   Options Database Keys:
127
.  -slepc_non_contiguous - Disable contiguous vector storage
128
 
129
   Notes:
130
   Use -slepc_non_contiguous to disable contiguous storage throughout SLEPc.
131
   Contiguous storage is currently also disabled in AIJCUSP matrices.
132
 
133
   Level: developer
134
 
135
.seealso: SlepcVecSetTemplate()
2339 jroman 136
@*/
2410 jroman 137
PetscErrorCode SlepcMatGetVecsTemplate(Mat mat,Vec *right,Vec *left)
2339 jroman 138
{
139
  PetscErrorCode ierr;
2410 jroman 140
  PetscBool      flg;
141
  Vec            v;
2339 jroman 142
 
143
  PetscFunctionBegin;
2410 jroman 144
  PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
145
  PetscValidType(mat,1);
146
  ierr = MatGetVecs(mat,right,left);CHKERRQ(ierr);
147
  v = right? *right: *left;
148
  ierr = PetscTypeCompareAny((PetscObject)v,&flg,VECSEQ,VECMPI,"");CHKERRQ(ierr);
149
  if (!flg) PetscFunctionReturn(0);
150
  ierr = PetscOptionsHasName(PETSC_NULL,"-slepc_non_contiguous",&flg);CHKERRQ(ierr);
151
  if (!flg) {
152
    if (right) { ierr = SlepcVecSetTemplate(*right);CHKERRQ(ierr); }
153
    if (left) { ierr = SlepcVecSetTemplate(*left);CHKERRQ(ierr); }
2339 jroman 154
  }
155
  PetscFunctionReturn(0);
156
}
157
 
2340 jroman 158
#undef __FUNCT__  
2414 jroman 159
#define __FUNCT__ "SlepcUpdateVectors_Noncontiguous_Inplace"
2415 jroman 160
/*
2414 jroman 161
   SlepcUpdateVectors_Noncontiguous_Inplace - V = V*Q for regular vectors
162
   (non-contiguous).
2415 jroman 163
*/
2417 jroman 164
static PetscErrorCode SlepcUpdateVectors_Noncontiguous_Inplace(PetscInt m_,Vec *V,const PetscScalar *Q,PetscInt ldq_,PetscBool qtrans)
2413 jroman 165
{
2417 jroman 166
  PetscInt       l;
167
  PetscBLASInt   j,ls,bs=64,m,k,ldq;
168
  PetscScalar    *pv,*pq=(PetscScalar*)Q,*work,*out,one=1.0,zero=0.0;
2413 jroman 169
  PetscErrorCode ierr;
170
 
171
  PetscFunctionBegin;
172
  ierr = PetscLogEventBegin(SLEPC_UpdateVectors,0,0,0,0);CHKERRQ(ierr);
2417 jroman 173
  ierr = VecGetLocalSize(V[0],&l);CHKERRQ(ierr);
174
  ls = PetscBLASIntCast(l);  
175
  m = PetscBLASIntCast(m_);
176
  ldq = PetscBLASIntCast(ldq_);
177
  ierr = PetscMalloc(sizeof(PetscScalar)*2*bs*m,&work);CHKERRQ(ierr);
178
  out = work+m*bs;
179
  k = ls % bs;
180
  if (k) {
2414 jroman 181
    for (j=0;j<m;j++) {
2417 jroman 182
      ierr = VecGetArray(V[j],&pv);CHKERRQ(ierr);
183
      ierr = PetscMemcpy(work+j*bs,pv,k*sizeof(PetscScalar));CHKERRQ(ierr);
184
      ierr = VecRestoreArray(V[j],&pv);CHKERRQ(ierr);    
2413 jroman 185
    }
2417 jroman 186
    BLASgemm_("N",qtrans?"T":"N",&k,&m,&m,&one,work,&bs,pq,&ldq,&zero,out,&bs);
2414 jroman 187
    for (j=0;j<m;j++) {
2413 jroman 188
      ierr = VecGetArray(V[j],&pv);CHKERRQ(ierr);
2417 jroman 189
      ierr = PetscMemcpy(pv,out+j*bs,k*sizeof(PetscScalar));CHKERRQ(ierr);
2413 jroman 190
      ierr = VecRestoreArray(V[j],&pv);CHKERRQ(ierr);    
191
    }
192
  }
2417 jroman 193
  for (;k<ls;k+=bs) {
194
    for (j=0;j<m;j++) {
195
      ierr = VecGetArray(V[j],&pv);CHKERRQ(ierr);
196
      ierr = PetscMemcpy(work+j*bs,pv+k,bs*sizeof(PetscScalar));CHKERRQ(ierr);
197
      ierr = VecRestoreArray(V[j],&pv);CHKERRQ(ierr);    
198
    }
199
    BLASgemm_("N",qtrans?"C":"N",&bs,&m,&m,&one,work,&bs,pq,&ldq,&zero,out,&bs);
200
    for (j=0;j<m;j++) {
201
      ierr = VecGetArray(V[j],&pv);CHKERRQ(ierr);
202
      ierr = PetscMemcpy(pv+k,out+j*bs,bs*sizeof(PetscScalar));CHKERRQ(ierr);
203
      ierr = VecRestoreArray(V[j],&pv);CHKERRQ(ierr);    
204
    }
205
  }
2413 jroman 206
  ierr = PetscFree(work);CHKERRQ(ierr);
2414 jroman 207
  ierr = PetscLogFlops(m*m*2.0*ls);CHKERRQ(ierr);
2413 jroman 208
  ierr = PetscLogEventEnd(SLEPC_UpdateVectors,0,0,0,0);CHKERRQ(ierr);
209
  PetscFunctionReturn(0);
210
}
211
 
212
#undef __FUNCT__  
2414 jroman 213
#define __FUNCT__ "SlepcUpdateVectors_Noncontiguous"
2415 jroman 214
/*
2414 jroman 215
   SlepcUpdateVectors_Noncontiguous - V(:,s:e-1) = V*Q(:,s:e-1) for
216
   regular vectors (non-contiguous).
217
 
218
   Writing V = [ V1 V2 V3 ] and Q = [ Q1 Q2 Q3 ], where the V2 and Q2
219
   correspond to the columns s:e-1, the computation is done as
220
                  V2 := V2*Q2 + V1*Q1 + V3*Q3
221
   (the first term is computed with SlepcUpdateVectors_Noncontiguous_Inplace).
2415 jroman 222
*/
2414 jroman 223
static PetscErrorCode SlepcUpdateVectors_Noncontiguous(PetscInt n,Vec *V,PetscInt s,PetscInt e,const PetscScalar *Q,PetscInt ldq,PetscBool qtrans)
224
{
225
  PetscInt       i,j,m,ln;
226
  PetscScalar    *pq,qt[100];
227
  PetscBool      allocated = PETSC_FALSE;
228
  PetscErrorCode ierr;
229
 
230
  PetscFunctionBegin;
231
  m = e-s;
232
  if (qtrans) {
233
    ln = PetscMax(s,n-e);
234
    if (ln<=100) pq = qt;
235
    else {
236
      ierr = PetscMalloc(ln*sizeof(PetscScalar),&pq);CHKERRQ(ierr);
237
      allocated = PETSC_TRUE;
238
    }
239
  }
240
  /* V2 */
241
  pq = (PetscScalar*)Q+s*ldq+s;
242
  ierr = SlepcUpdateVectors_Noncontiguous_Inplace(m,V+s,pq,ldq,qtrans);CHKERRQ(ierr);
243
  /* V1 */
244
  if (s>0) {
245
    for (i=s;i<e;i++) {
246
      if (qtrans) {
247
        for (j=0;j<s;j++) pq[j] = Q[i+j*ldq];
248
      } else pq = (PetscScalar*)Q+i*ldq;
249
      ierr = VecMAXPY(V[i],s,pq,V);CHKERRQ(ierr);
250
    }
251
  }
252
  /* V3 */
253
  if (n>e) {
254
    for (i=s;i<e;i++) {
255
      if (qtrans) {
256
        for (j=0;j<n-e;j++) pq[j] = Q[i+(j+e)*ldq];
257
      } else pq = (PetscScalar*)Q+i*ldq+e;
258
      ierr = VecMAXPY(V[i],n-e,pq,V+e);CHKERRQ(ierr);
259
    }
260
  }
261
  if (allocated) { ierr = PetscFree(pq);CHKERRQ(ierr); }
262
  PetscFunctionReturn(0);
263
}
264
 
265
#undef __FUNCT__  
2340 jroman 266
#define __FUNCT__ "SlepcUpdateVectors"
267
/*@
268
   SlepcUpdateVectors - Update a set of vectors V as V(:,s:e-1) = V*Q(:,s:e-1).
269
 
270
   Not Collective
271
 
272
   Input parameters:
273
+  n      - number of vectors in V
274
.  s      - first column of V to be overwritten
275
.  e      - first column of V not to be overwritten
276
.  Q      - matrix containing the coefficients of the update
277
.  ldq    - leading dimension of Q
278
-  qtrans - flag indicating if Q is to be transposed
279
 
280
   Input/Output parameter:
281
.  V      - set of vectors
282
 
283
   Notes:
284
   This function computes V(:,s:e-1) = V*Q(:,s:e-1), that is, given a set of
285
   vectors V, columns from s to e-1 are overwritten with columns from s to
286
   e-1 of the matrix-matrix product V*Q.
287
 
288
   Matrix V is represented as an array of Vec, whereas Q is represented as
289
   a column-major dense array of leading dimension ldq. Only columns s to e-1
290
   of Q are referenced.
291
 
292
   If qtrans=PETSC_TRUE, the operation is V*Q'.
293
 
294
   This routine is implemented with a call to BLAS, therefore V is an array
295
   of Vec which have the data stored contiguously in memory as a Fortran matrix.
296
   PETSc does not create such arrays by default.
297
 
298
   Level: developer
299
 
300
@*/
2413 jroman 301
PetscErrorCode SlepcUpdateVectors(PetscInt n,Vec *V,PetscInt s,PetscInt e,const PetscScalar *Q,PetscInt ldq,PetscBool qtrans)
2340 jroman 302
{
2413 jroman 303
  PetscContainer container;
2340 jroman 304
  PetscErrorCode ierr;
305
 
306
  PetscFunctionBegin;
2413 jroman 307
  if (n<0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",n);
308
  if (n==0 || s>=e) PetscFunctionReturn(0);
309
  PetscValidPointer(V,2);
310
  PetscValidHeaderSpecific(*V,VEC_CLASSID,2);
311
  PetscValidType(*V,2);
312
  PetscValidScalarPointer(Q,5);
313
  ierr = PetscObjectQuery((PetscObject)(V[0]),"contiguous",(PetscObject*)&container);CHKERRQ(ierr);
314
  if (container) {
315
    /* contiguous Vecs, use BLAS calls */
316
    ierr = SlepcUpdateStrideVectors(n,V,s,1,e,Q,ldq,qtrans);CHKERRQ(ierr);
317
  } else {
318
    /* use regular Vec operations */
319
    ierr = SlepcUpdateVectors_Noncontiguous(n,V,s,e,Q,ldq,qtrans);CHKERRQ(ierr);
320
  }
2340 jroman 321
  PetscFunctionReturn(0);
322
}
323
 
324
#undef __FUNCT__  
325
#define __FUNCT__ "SlepcUpdateStrideVectors"
326
/*@
327
   SlepcUpdateStrideVectors - Update a set of vectors V as
328
   V(:,s:d:e-1) = V*Q(:,s:e-1).
329
 
330
   Not Collective
331
 
332
   Input parameters:
333
+  n      - number of vectors in V
334
.  s      - first column of V to be overwritten
335
.  d      - stride
336
.  e      - first column of V not to be overwritten
337
.  Q      - matrix containing the coefficients of the update
338
.  ldq    - leading dimension of Q
339
-  qtrans - flag indicating if Q is to be transposed
340
 
341
   Input/Output parameter:
342
.  V      - set of vectors
343
 
344
   Notes:
345
   This function computes V(:,s:d:e-1) = V*Q(:,s:e-1), that is, given a set
346
   of vectors V, columns from s to e-1 are overwritten with columns from s to
347
   e-1 of the matrix-matrix product V*Q.
348
 
349
   Matrix V is represented as an array of Vec, whereas Q is represented as
350
   a column-major dense array of leading dimension ldq. Only columns s to e-1
351
   of Q are referenced.
352
 
353
   If qtrans=PETSC_TRUE, the operation is V*Q'.
354
 
355
   This routine is implemented with a call to BLAS, therefore V is an array
356
   of Vec which have the data stored contiguously in memory as a Fortran matrix.
357
   PETSc does not create such arrays by default.
358
 
359
   Level: developer
360
 
361
@*/
362
PetscErrorCode SlepcUpdateStrideVectors(PetscInt n_,Vec *V,PetscInt s,PetscInt d,PetscInt e,const PetscScalar *Q,PetscInt ldq_,PetscBool qtrans)
363
{
364
  PetscErrorCode ierr;
365
  PetscInt       l;
366
  PetscBLASInt   i,j,k,bs=64,m,n,ldq,ls,ld;
367
  PetscScalar    *pv,*pw,*pq,*work,*pwork,one=1.0,zero=0.0;
368
  const char     *qt;
369
 
370
  PetscFunctionBegin;
371
  n = PetscBLASIntCast(n_/d);
372
  ldq = PetscBLASIntCast(ldq_);
373
  m = (e-s)/d;
374
  if (m==0) PetscFunctionReturn(0);
375
  PetscValidIntPointer(Q,5);
376
  if (m<0 || n<0 || s<0 || m>n) SETERRQ(((PetscObject)*V)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Index argument out of range");
377
  ierr = PetscLogEventBegin(SLEPC_UpdateVectors,0,0,0,0);CHKERRQ(ierr);
378
  ierr = VecGetLocalSize(V[0],&l);CHKERRQ(ierr);
379
  ls = PetscBLASIntCast(l);
380
  ld = ls*PetscBLASIntCast(d);
381
  ierr = VecGetArray(V[0],&pv);CHKERRQ(ierr);
382
  if (qtrans) {
383
    pq = (PetscScalar*)Q+s;
2417 jroman 384
    qt = "C";
2340 jroman 385
  } else {
386
    pq = (PetscScalar*)Q+s*ldq;
387
    qt = "N";
388
  }
389
  ierr = PetscMalloc(sizeof(PetscScalar)*bs*m,&work);CHKERRQ(ierr);
390
  k = ls % bs;
391
  if (k) {
392
    BLASgemm_("N",qt,&k,&m,&n,&one,pv,&ld,pq,&ldq,&zero,work,&k);
393
    for (j=0;j<m;j++) {
394
      pw = pv+(s+j)*ld;
395
      pwork = work+j*k;
396
      for (i=0;i<k;i++) {
397
        *pw++ = *pwork++;
398
      }
399
    }        
400
  }
401
  for (;k<ls;k+=bs) {
402
    BLASgemm_("N",qt,&bs,&m,&n,&one,pv+k,&ld,pq,&ldq,&zero,work,&bs);
403
    for (j=0;j<m;j++) {
404
      pw = pv+(s+j)*ld+k;
405
      pwork = work+j*bs;
406
      for (i=0;i<bs;i++) {
407
        *pw++ = *pwork++;
408
      }
409
    }
410
  }
411
  ierr = VecRestoreArray(V[0],&pv);CHKERRQ(ierr);
412
  ierr = PetscFree(work);CHKERRQ(ierr);
413
  ierr = PetscLogFlops(m*n*2.0*ls);CHKERRQ(ierr);
414
  ierr = PetscLogEventEnd(SLEPC_UpdateVectors,0,0,0,0);CHKERRQ(ierr);
415
  PetscFunctionReturn(0);
416
}
417
 
418
#undef __FUNCT__  
419
#define __FUNCT__ "SlepcVecMAXPBY"
420
/*@
421
   SlepcVecMAXPBY - Computes y = beta*y + sum alpha*a[j]*x[j]
422
 
423
   Logically Collective on Vec
424
 
425
   Input parameters:
426
+  beta   - scalar beta
427
.  alpha  - scalar alpha
428
.  nv     - number of vectors in x and scalars in a
429
.  a      - array of scalars
430
-  x      - set of vectors
431
 
432
   Input/Output parameter:
433
.  y      - the vector to update
434
 
435
   Notes:
2410 jroman 436
   If x are Vec's with contiguous storage, then the operation is done
437
   through a call to BLAS. Otherwise, VecMAXPY() is called.
2340 jroman 438
 
439
   Level: developer
440
 
2410 jroman 441
.seealso: SlepcVecSetTemplate()
2340 jroman 442
@*/
2416 jroman 443
PetscErrorCode SlepcVecMAXPBY(Vec y,PetscScalar beta,PetscScalar alpha,PetscInt nv,PetscScalar a[],Vec x[])
2340 jroman 444
{
445
  PetscErrorCode    ierr;
2416 jroman 446
  PetscBLASInt      i,n,m,one=1;
2340 jroman 447
  PetscScalar       *py;
448
  const PetscScalar *px;
2386 jroman 449
  PetscContainer    container;
450
  Vec               z;
2340 jroman 451
 
452
  PetscFunctionBegin;
453
  PetscValidHeaderSpecific(y,VEC_CLASSID,1);
454
  if (!nv || !(y)->map->n) PetscFunctionReturn(0);
455
  if (nv < 0) SETERRQ1(((PetscObject)y)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",nv);
456
  PetscValidLogicalCollectiveScalar(y,alpha,2);
457
  PetscValidLogicalCollectiveScalar(y,beta,3);
458
  PetscValidLogicalCollectiveInt(y,nv,4);
459
  PetscValidScalarPointer(a,5);
460
  PetscValidPointer(x,6);
461
  PetscValidHeaderSpecific(*x,VEC_CLASSID,6);
462
  PetscValidType(y,1);
463
  PetscValidType(*x,6);
464
  PetscCheckSameTypeAndComm(y,1,*x,6);
465
  if ((*x)->map->N != (y)->map->N) SETERRQ(((PetscObject)y)->comm,PETSC_ERR_ARG_INCOMP,"Incompatible vector global lengths");
466
  if ((*x)->map->n != (y)->map->n) SETERRQ(((PetscObject)y)->comm,PETSC_ERR_ARG_INCOMP,"Incompatible vector local lengths");
467
 
2386 jroman 468
  ierr = PetscObjectQuery((PetscObject)(x[0]),"contiguous",(PetscObject*)&container);CHKERRQ(ierr);
469
  if (container) {
470
    /* assume x Vecs are contiguous, use BLAS calls */
471
    ierr = PetscLogEventBegin(SLEPC_VecMAXPBY,*x,y,0,0);CHKERRQ(ierr);
472
    ierr = VecGetArray(y,&py);CHKERRQ(ierr);
473
    ierr = VecGetArrayRead(*x,&px);CHKERRQ(ierr);
474
    n = PetscBLASIntCast(nv);
475
    m = PetscBLASIntCast((y)->map->n);
476
    BLASgemv_("N",&m,&n,&alpha,px,&m,a,&one,&beta,py,&one);
477
    ierr = VecRestoreArray(y,&py);CHKERRQ(ierr);
478
    ierr = VecRestoreArrayRead(*x,&px);CHKERRQ(ierr);
479
    ierr = PetscLogFlops(nv*2*(y)->map->n);CHKERRQ(ierr);
480
    ierr = PetscLogEventEnd(SLEPC_VecMAXPBY,*x,y,0,0);CHKERRQ(ierr);
481
  } else {
482
    /* use regular Vec operations */
2416 jroman 483
    if (alpha==-beta) {
484
      for (i=0;i<nv;i++) a[i] = -a[i];
485
      ierr = VecMAXPY(y,nv,a,x);CHKERRQ(ierr);
486
      for (i=0;i<nv;i++) a[i] = -a[i];
487
      ierr = VecScale(y,beta);CHKERRQ(ierr);
488
    } else {
489
      ierr = VecDuplicate(y,&z);CHKERRQ(ierr);
490
      ierr = VecCopy(y,z);CHKERRQ(ierr);
491
      ierr = VecMAXPY(y,nv,a,x);CHKERRQ(ierr);
492
      ierr = VecAXPBY(y,beta-alpha,alpha,z);CHKERRQ(ierr);
493
      ierr = VecDestroy(&z);CHKERRQ(ierr);
494
    }
2386 jroman 495
  }
2340 jroman 496
  PetscFunctionReturn(0);
497
}
498