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
1302 slepc 1
/*
2
     Dot product routines
1376 slepc 3
 
4
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 5
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2116 eromero 6
   Copyright (c) 2002-2010, Universidad Politecnica de Valencia, Spain
1376 slepc 7
 
1672 slepc 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/>.
1376 slepc 21
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1302 slepc 22
*/
1376 slepc 23
 
2283 jroman 24
#include <private/ipimpl.h>      /*I "slepcip.h" I*/
1302 slepc 25
 
26
#undef __FUNCT__  
27
#define __FUNCT__ "IPNorm"
28
/*@
1704 jroman 29
   IPNorm - Computes the norm of a vector as the square root of the inner
1302 slepc 30
   product (x,x) as defined by IPInnerProduct().
31
 
32
   Collective on IP and Vec
33
 
34
   Input Parameters:
1423 slepc 35
+  ip - the inner product context
1302 slepc 36
-  x  - input vector
37
 
38
   Output Parameter:
39
.  norm - the computed norm
40
 
41
   Notes:
42
   This function will usually compute the 2-norm of a vector, ||x||_2. But
43
   this behaviour may be different if using a non-standard inner product changed
44
   via IPSetBilinearForm(). For example, if using the B-inner product for
45
   positive definite B, (x,y)_B=y^H Bx, then the computed norm is ||x||_B =
46
   sqrt( x^H Bx ).
47
 
48
   Level: developer
49
 
50
.seealso: IPInnerProduct()
51
@*/
52
PetscErrorCode IPNorm(IP ip,Vec x,PetscReal *norm)
53
{
54
  PetscErrorCode ierr;
55
  PetscScalar    p;
56
 
57
  PetscFunctionBegin;
2213 jroman 58
  PetscValidHeaderSpecific(ip,IP_CLASSID,1);
59
  PetscValidHeaderSpecific(x,VEC_CLASSID,2);
1302 slepc 60
  PetscValidPointer(norm,3);
1940 jroman 61
  if (!ip->matrix && ip->bilinear_form == IP_INNER_HERMITIAN) {
1432 slepc 62
    ierr = VecNorm(x,NORM_2,norm);CHKERRQ(ierr);
63
  } else {
64
    ierr = IPInnerProduct(ip,x,x,&p);CHKERRQ(ierr);
65
    if (PetscAbsScalar(p)<PETSC_MACHINE_EPSILON)
66
      PetscInfo(ip,"Zero norm, either the vector is zero or a semi-inner product is being used\n");
1302 slepc 67
#if defined(PETSC_USE_COMPLEX)
1432 slepc 68
    if (PetscRealPart(p)<0.0 || PetscAbsReal(PetscImaginaryPart(p))>PETSC_MACHINE_EPSILON)
2214 jroman 69
       SETERRQ(((PetscObject)ip)->comm,1,"IPNorm: The inner product is not well defined");
1432 slepc 70
    *norm = PetscSqrtScalar(PetscRealPart(p));
1302 slepc 71
#else
2214 jroman 72
    if (p<0.0) SETERRQ(((PetscObject)ip)->comm,1,"IPNorm: The inner product is not well defined");
1432 slepc 73
    *norm = PetscSqrtScalar(p);
1302 slepc 74
#endif
1432 slepc 75
  }
1302 slepc 76
  PetscFunctionReturn(0);
77
}
78
 
79
#undef __FUNCT__  
80
#define __FUNCT__ "IPNormBegin"
81
/*@
82
   IPNormBegin - Starts a split phase norm computation.
83
 
84
   Input Parameters:
1423 slepc 85
+  ip   - the inner product context
1302 slepc 86
.  x    - input vector
87
-  norm - where the result will go
88
 
89
   Level: developer
90
 
91
   Notes:
92
   Each call to IPNormBegin() should be paired with a call to IPNormEnd().
93
 
94
.seealso: IPNormEnd(), IPNorm(), IPInnerProduct(), IPMInnerProduct(),
95
          IPInnerProductBegin(), IPInnerProductEnd()
96
 
97
@*/
98
PetscErrorCode IPNormBegin(IP ip,Vec x,PetscReal *norm)
99
{
100
  PetscErrorCode ierr;
101
  PetscScalar    p;
102
 
103
  PetscFunctionBegin;
2213 jroman 104
  PetscValidHeaderSpecific(ip,IP_CLASSID,1);
105
  PetscValidHeaderSpecific(x,VEC_CLASSID,2);
1302 slepc 106
  PetscValidPointer(norm,3);
1940 jroman 107
  if (!ip->matrix && ip->bilinear_form == IP_INNER_HERMITIAN) {
1432 slepc 108
    ierr = VecNormBegin(x,NORM_2,norm);CHKERRQ(ierr);
109
  } else {
110
    ierr = IPInnerProductBegin(ip,x,x,&p);CHKERRQ(ierr);
111
  }
1302 slepc 112
  PetscFunctionReturn(0);
113
}
114
 
115
#undef __FUNCT__  
116
#define __FUNCT__ "IPNormEnd"
117
/*@
118
   IPNormEnd - Ends a split phase norm computation.
119
 
120
   Input Parameters:
1423 slepc 121
+  ip   - the inner product context
1302 slepc 122
-  x    - input vector
123
 
124
   Output Parameter:
125
.  norm - the computed norm
126
 
127
   Level: developer
128
 
129
   Notes:
130
   Each call to IPNormBegin() should be paired with a call to IPNormEnd().
131
 
132
.seealso: IPNormBegin(), IPNorm(), IPInnerProduct(), IPMInnerProduct(),
133
          IPInnerProductBegin(), IPInnerProductEnd()
134
 
135
@*/
136
PetscErrorCode IPNormEnd(IP ip,Vec x,PetscReal *norm)
137
{
138
  PetscErrorCode ierr;
139
  PetscScalar    p;
140
 
141
  PetscFunctionBegin;
2213 jroman 142
  PetscValidHeaderSpecific(ip,IP_CLASSID,1);
143
  PetscValidHeaderSpecific(x,VEC_CLASSID,2);
1302 slepc 144
  PetscValidPointer(norm,3);
1940 jroman 145
  if (!ip->matrix && ip->bilinear_form == IP_INNER_HERMITIAN) {
1432 slepc 146
    ierr = VecNormEnd(x,NORM_2,norm);CHKERRQ(ierr);
147
  } else {
148
    ierr = IPInnerProductEnd(ip,x,x,&p);CHKERRQ(ierr);
149
    if (PetscAbsScalar(p)<PETSC_MACHINE_EPSILON)
150
      PetscInfo(ip,"Zero norm, either the vector is zero or a semi-inner product is being used\n");
1302 slepc 151
 
152
#if defined(PETSC_USE_COMPLEX)
1432 slepc 153
    if (PetscRealPart(p)<0.0 || PetscAbsReal(PetscImaginaryPart(p))>PETSC_MACHINE_EPSILON)
2214 jroman 154
       SETERRQ(((PetscObject)ip)->comm,1,"IPNorm: The inner product is not well defined");
1432 slepc 155
    *norm = PetscSqrtScalar(PetscRealPart(p));
1302 slepc 156
#else
2214 jroman 157
    if (p<0.0) SETERRQ(((PetscObject)ip)->comm,1,"IPNorm: The inner product is not well defined");
1432 slepc 158
    *norm = PetscSqrtScalar(p);
1302 slepc 159
#endif
1432 slepc 160
  }
1302 slepc 161
  PetscFunctionReturn(0);
162
}
163
 
164
#undef __FUNCT__  
165
#define __FUNCT__ "IPInnerProduct"
166
/*@
167
   IPInnerProduct - Computes the inner product of two vectors.
168
 
169
   Collective on IP and Vec
170
 
171
   Input Parameters:
1423 slepc 172
+  ip - the inner product context
1302 slepc 173
.  x  - input vector
174
-  y  - input vector
175
 
176
   Output Parameter:
177
.  p - result of the inner product
178
 
179
   Notes:
180
   This function will usually compute the standard dot product of vectors
181
   x and y, (x,y)=y^H x. However this behaviour may be different if changed
182
   via IPSetBilinearForm(). This allows use of other inner products such as
183
   the indefinite product y^T x for complex symmetric problems or the
184
   B-inner product for positive definite B, (x,y)_B=y^H Bx.
185
 
186
   Level: developer
187
 
2242 jroman 188
.seealso: IPSetBilinearForm(), VecDot(), IPMInnerProduct()
1302 slepc 189
@*/
190
PetscErrorCode IPInnerProduct(IP ip,Vec x,Vec y,PetscScalar *p)
191
{
192
  PetscErrorCode ierr;
193
 
194
  PetscFunctionBegin;
2213 jroman 195
  PetscValidHeaderSpecific(ip,IP_CLASSID,1);
196
  PetscValidHeaderSpecific(x,VEC_CLASSID,2);
197
  PetscValidHeaderSpecific(y,VEC_CLASSID,3);
1302 slepc 198
  PetscValidScalarPointer(p,4);
199
  ierr = PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
200
  ip->innerproducts++;
1329 slepc 201
  if (ip->matrix) {
1358 slepc 202
    ierr = IPApplyMatrix_Private(ip,x);CHKERRQ(ierr);
1940 jroman 203
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1358 slepc 204
      ierr = VecDot(ip->Bx,y,p);CHKERRQ(ierr);
1307 slepc 205
    } else {
1358 slepc 206
      ierr = VecTDot(ip->Bx,y,p);CHKERRQ(ierr);
1307 slepc 207
    }
1329 slepc 208
  } else {
1940 jroman 209
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1329 slepc 210
      ierr = VecDot(x,y,p);CHKERRQ(ierr);
211
    } else {
212
      ierr = VecTDot(x,y,p);CHKERRQ(ierr);
213
    }
1302 slepc 214
  }
215
  ierr = PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
216
  PetscFunctionReturn(0);
217
}
218
 
219
#undef __FUNCT__  
220
#define __FUNCT__ "IPInnerProductBegin"
221
/*@
222
   IPInnerProductBegin - Starts a split phase inner product computation.
223
 
224
   Input Parameters:
1423 slepc 225
+  ip - the inner product context
1302 slepc 226
.  x  - the first vector
227
.  y  - the second vector
228
-  p  - where the result will go
229
 
230
   Level: developer
231
 
232
   Notes:
233
   Each call to IPInnerProductBegin() should be paired with a call to IPInnerProductEnd().
234
 
235
.seealso: IPInnerProductEnd(), IPInnerProduct(), IPNorm(), IPNormBegin(),
236
          IPNormEnd(), IPMInnerProduct()
237
 
238
@*/
239
PetscErrorCode IPInnerProductBegin(IP ip,Vec x,Vec y,PetscScalar *p)
240
{
241
  PetscErrorCode ierr;
242
 
243
  PetscFunctionBegin;
2213 jroman 244
  PetscValidHeaderSpecific(ip,IP_CLASSID,1);
245
  PetscValidHeaderSpecific(x,VEC_CLASSID,2);
246
  PetscValidHeaderSpecific(y,VEC_CLASSID,3);
1302 slepc 247
  PetscValidScalarPointer(p,4);
248
  ierr = PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
249
  ip->innerproducts++;
1329 slepc 250
  if (ip->matrix) {
1358 slepc 251
    ierr = IPApplyMatrix_Private(ip,x);CHKERRQ(ierr);
1940 jroman 252
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1358 slepc 253
      ierr = VecDotBegin(ip->Bx,y,p);CHKERRQ(ierr);
1307 slepc 254
    } else {
1358 slepc 255
      ierr = VecTDotBegin(ip->Bx,y,p);CHKERRQ(ierr);
1307 slepc 256
    }
1329 slepc 257
  } else {
1940 jroman 258
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1329 slepc 259
      ierr = VecDotBegin(x,y,p);CHKERRQ(ierr);
260
    } else {
261
      ierr = VecTDotBegin(x,y,p);CHKERRQ(ierr);
262
    }
1302 slepc 263
  }
264
  ierr = PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
265
  PetscFunctionReturn(0);
266
}
267
 
268
#undef __FUNCT__  
269
#define __FUNCT__ "IPInnerProductEnd"
270
/*@
271
   IPInnerProductEnd - Ends a split phase inner product computation.
272
 
273
   Input Parameters:
1423 slepc 274
+  ip - the inner product context
1302 slepc 275
.  x  - the first vector
276
-  y  - the second vector
277
 
278
   Output Parameter:
279
.  p  - result of the inner product
280
 
281
   Level: developer
282
 
283
   Notes:
284
   Each call to IPInnerProductBegin() should be paired with a call to IPInnerProductEnd().
285
 
286
.seealso: IPInnerProductBegin(), IPInnerProduct(), IPNorm(), IPNormBegin(),
287
          IPNormEnd(), IPMInnerProduct()
288
 
289
@*/
290
PetscErrorCode IPInnerProductEnd(IP ip,Vec x,Vec y,PetscScalar *p)
291
{
292
  PetscErrorCode ierr;
293
 
294
  PetscFunctionBegin;
2213 jroman 295
  PetscValidHeaderSpecific(ip,IP_CLASSID,1);
296
  PetscValidHeaderSpecific(x,VEC_CLASSID,2);
297
  PetscValidHeaderSpecific(y,VEC_CLASSID,3);
1302 slepc 298
  PetscValidScalarPointer(p,4);
299
  ierr = PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
1329 slepc 300
  if (ip->matrix) {
1940 jroman 301
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1358 slepc 302
      ierr = VecDotEnd(ip->Bx,y,p);CHKERRQ(ierr);
1329 slepc 303
    } else {
1358 slepc 304
      ierr = VecTDotEnd(ip->Bx,y,p);CHKERRQ(ierr);
1329 slepc 305
    }
306
  } else {
1940 jroman 307
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1329 slepc 308
      ierr = VecDotEnd(x,y,p);CHKERRQ(ierr);
309
    } else {
310
      ierr = VecTDotEnd(x,y,p);CHKERRQ(ierr);
311
    }
1302 slepc 312
  }
313
  ierr = PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
314
  PetscFunctionReturn(0);
315
}
316
 
317
#undef __FUNCT__  
318
#define __FUNCT__ "IPMInnerProduct"
319
/*@
320
   IPMInnerProduct - Computes the inner products a vector x with a set of
321
   vectors (columns of Y).
322
 
323
   Collective on IP and Vec
324
 
325
   Input Parameters:
1423 slepc 326
+  ip - the inner product context
1381 slepc 327
.  x  - the first input vector
1302 slepc 328
.  n  - number of vectors in y
329
-  y  - array of vectors
330
 
331
   Output Parameter:
332
.  p - result of the inner products
333
 
334
   Notes:
335
   This function will usually compute the standard dot product of x and y_i,
336
   (x,y_i)=y_i^H x, for each column of Y. However this behaviour may be different
337
   if changed via IPSetBilinearForm(). This allows use of other inner products
338
   such as the indefinite product y_i^T x for complex symmetric problems or the
339
   B-inner product for positive definite B, (x,y_i)_B=y_i^H Bx.
340
 
341
   Level: developer
342
 
2242 jroman 343
.seealso: IPSetBilinearForm(), VecMDot(), IPInnerProduct()
1302 slepc 344
@*/
1381 slepc 345
PetscErrorCode IPMInnerProduct(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
1302 slepc 346
{
347
  PetscErrorCode ierr;
348
 
349
  PetscFunctionBegin;
2213 jroman 350
  PetscValidHeaderSpecific(ip,IP_CLASSID,1);
351
  PetscValidHeaderSpecific(x,VEC_CLASSID,3);
1302 slepc 352
  PetscValidPointer(y,4);
2213 jroman 353
  PetscValidHeaderSpecific(*y,VEC_CLASSID,4);
1302 slepc 354
  PetscValidScalarPointer(p,5);
355
  ierr = PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
356
  ip->innerproducts += n;
1329 slepc 357
  if (ip->matrix) {
1358 slepc 358
    ierr = IPApplyMatrix_Private(ip,x);CHKERRQ(ierr);
1940 jroman 359
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1358 slepc 360
      ierr = VecMDot(ip->Bx,n,y,p);CHKERRQ(ierr);
1307 slepc 361
    } else {
1358 slepc 362
      ierr = VecMTDot(ip->Bx,n,y,p);CHKERRQ(ierr);
1307 slepc 363
    }
1329 slepc 364
  } else {
1940 jroman 365
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1329 slepc 366
      ierr = VecMDot(x,n,y,p);CHKERRQ(ierr);
367
    } else {
368
      ierr = VecMTDot(x,n,y,p);CHKERRQ(ierr);
369
    }
1302 slepc 370
  }
371
  ierr = PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
372
  PetscFunctionReturn(0);
373
}
374
 
375
#undef __FUNCT__  
376
#define __FUNCT__ "IPMInnerProductBegin"
377
/*@
378
   IPMInnerProductBegin - Starts a split phase multiple inner product computation.
379
 
380
   Input Parameters:
1423 slepc 381
+  ip - the inner product context
1381 slepc 382
.  x  - the first input vector
1302 slepc 383
.  n  - number of vectors in y
384
.  y  - array of vectors
385
-  p  - where the result will go
386
 
387
   Level: developer
388
 
389
   Notes:
390
   Each call to IPMInnerProductBegin() should be paired with a call to IPMInnerProductEnd().
391
 
392
.seealso: IPMInnerProductEnd(), IPMInnerProduct(), IPNorm(), IPNormBegin(),
393
          IPNormEnd(), IPInnerProduct()
394
 
395
@*/
1381 slepc 396
PetscErrorCode IPMInnerProductBegin(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
1302 slepc 397
{
398
  PetscErrorCode ierr;
399
 
400
  PetscFunctionBegin;
2213 jroman 401
  PetscValidHeaderSpecific(ip,IP_CLASSID,1);
402
  PetscValidHeaderSpecific(x,VEC_CLASSID,3);
1877 antodo 403
  if (n == 0) PetscFunctionReturn(0);
1302 slepc 404
  PetscValidPointer(y,4);
2213 jroman 405
  PetscValidHeaderSpecific(*y,VEC_CLASSID,4);
1302 slepc 406
  PetscValidScalarPointer(p,5);
407
  ierr = PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
408
  ip->innerproducts += n;
1329 slepc 409
  if (ip->matrix) {
1358 slepc 410
    ierr = IPApplyMatrix_Private(ip,x);CHKERRQ(ierr);
1940 jroman 411
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1358 slepc 412
      ierr = VecMDotBegin(ip->Bx,n,y,p);CHKERRQ(ierr);
1307 slepc 413
    } else {
1358 slepc 414
      ierr = VecMTDotBegin(ip->Bx,n,y,p);CHKERRQ(ierr);
1307 slepc 415
    }
1329 slepc 416
  } else {
1940 jroman 417
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1329 slepc 418
      ierr = VecMDotBegin(x,n,y,p);CHKERRQ(ierr);
419
    } else {
420
      ierr = VecMTDotBegin(x,n,y,p);CHKERRQ(ierr);
421
    }
1302 slepc 422
  }
423
  ierr = PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
424
  PetscFunctionReturn(0);
425
}
426
 
427
#undef __FUNCT__  
428
#define __FUNCT__ "IPMInnerProductEnd"
429
/*@
430
   IPMInnerProductEnd - Ends a split phase multiple inner product computation.
431
 
432
   Input Parameters:
1423 slepc 433
+  ip - the inner product context
1381 slepc 434
.  x  - the first input vector
1302 slepc 435
.  n  - number of vectors in y
436
-  y  - array of vectors
437
 
438
   Output Parameter:
439
.  p - result of the inner products
440
 
441
   Level: developer
442
 
443
   Notes:
444
   Each call to IPMInnerProductBegin() should be paired with a call to IPMInnerProductEnd().
445
 
446
.seealso: IPMInnerProductBegin(), IPMInnerProduct(), IPNorm(), IPNormBegin(),
447
          IPNormEnd(), IPInnerProduct()
448
 
449
@*/
1381 slepc 450
PetscErrorCode IPMInnerProductEnd(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
1302 slepc 451
{
452
  PetscErrorCode ierr;
453
 
454
  PetscFunctionBegin;
2213 jroman 455
  PetscValidHeaderSpecific(ip,IP_CLASSID,1);
456
  PetscValidHeaderSpecific(x,VEC_CLASSID,3);
1877 antodo 457
  if (n == 0) PetscFunctionReturn(0);
1302 slepc 458
  PetscValidPointer(y,4);
2213 jroman 459
  PetscValidHeaderSpecific(*y,VEC_CLASSID,4);
1302 slepc 460
  PetscValidScalarPointer(p,5);
461
  ierr = PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
1329 slepc 462
  if (ip->matrix) {
1940 jroman 463
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1358 slepc 464
      ierr = VecMDotEnd(ip->Bx,n,y,p);CHKERRQ(ierr);
1329 slepc 465
    } else {
1358 slepc 466
      ierr = VecMTDotEnd(ip->Bx,n,y,p);CHKERRQ(ierr);
1329 slepc 467
    }
468
  } else {
1940 jroman 469
    if (ip->bilinear_form == IP_INNER_HERMITIAN) {
1329 slepc 470
      ierr = VecMDotEnd(x,n,y,p);CHKERRQ(ierr);
471
    } else {
472
      ierr = VecMTDotEnd(x,n,y,p);CHKERRQ(ierr);
473
    }
1302 slepc 474
  }
475
  ierr = PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);CHKERRQ(ierr);
476
  PetscFunctionReturn(0);
477
}