Actual source code: linear.c

  1: /*

  3:    Straightforward linearization for quadratic eigenproblems.

  5:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  6:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  7:    Copyright (c) 2002-2013, Universitat Politecnica de Valencia, Spain

  9:    This file is part of SLEPc.

 11:    SLEPc is free software: you can redistribute it and/or modify it under  the
 12:    terms of version 3 of the GNU Lesser General Public License as published by
 13:    the Free Software Foundation.

 15:    SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
 16:    WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
 17:    FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
 18:    more details.

 20:    You  should have received a copy of the GNU Lesser General  Public  License
 21:    along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
 22:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 23: */

 25: #include <slepc-private/qepimpl.h>         /*I "slepcqep.h" I*/
 26: #include <slepc-private/epsimpl.h>         /*I "slepceps.h" I*/
 27:  #include linearp.h

 31: PetscErrorCode QEPSetUp_Linear(QEP qep)
 32: {
 34:   QEP_LINEAR     *ctx = (QEP_LINEAR*)qep->data;
 35:   PetscInt       i=0;
 36:   EPSWhich       which;
 37:   PetscBool      trackall;
 38:   PetscScalar    sigma;
 39:   /* function tables */
 40:   PetscErrorCode (*fcreate[][2])(MPI_Comm,QEP_LINEAR*,Mat*) = {
 41:     { MatCreateExplicit_Linear_N1A, MatCreateExplicit_Linear_N1B },   /* N1 */
 42:     { MatCreateExplicit_Linear_N2A, MatCreateExplicit_Linear_N2B },   /* N2 */
 43:     { MatCreateExplicit_Linear_S1A, MatCreateExplicit_Linear_S1B },   /* S1 */
 44:     { MatCreateExplicit_Linear_S2A, MatCreateExplicit_Linear_S2B },   /* S2 */
 45:     { MatCreateExplicit_Linear_H1A, MatCreateExplicit_Linear_H1B },   /* H1 */
 46:     { MatCreateExplicit_Linear_H2A, MatCreateExplicit_Linear_H2B }    /* H2 */
 47:   };
 48:   PetscErrorCode (*fmult[][2])(Mat,Vec,Vec) = {
 49:     { MatMult_Linear_N1A, MatMult_Linear_N1B },
 50:     { MatMult_Linear_N2A, MatMult_Linear_N2B },
 51:     { MatMult_Linear_S1A, MatMult_Linear_S1B },
 52:     { MatMult_Linear_S2A, MatMult_Linear_S2B },
 53:     { MatMult_Linear_H1A, MatMult_Linear_H1B },
 54:     { MatMult_Linear_H2A, MatMult_Linear_H2B }
 55:   };
 56:   PetscErrorCode (*fgetdiagonal[][2])(Mat,Vec) = {
 57:     { MatGetDiagonal_Linear_N1A, MatGetDiagonal_Linear_N1B },
 58:     { MatGetDiagonal_Linear_N2A, MatGetDiagonal_Linear_N2B },
 59:     { MatGetDiagonal_Linear_S1A, MatGetDiagonal_Linear_S1B },
 60:     { MatGetDiagonal_Linear_S2A, MatGetDiagonal_Linear_S2B },
 61:     { MatGetDiagonal_Linear_H1A, MatGetDiagonal_Linear_H1B },
 62:     { MatGetDiagonal_Linear_H2A, MatGetDiagonal_Linear_H2B }
 63:   };

 66:   if (!ctx->cform) ctx->cform = 1;
 67:   if (!qep->which) qep->which = QEP_LARGEST_MAGNITUDE;
 68:   ctx->M = qep->M;
 69:   ctx->C = qep->C;
 70:   ctx->K = qep->K;
 71:   ctx->sfactor = qep->sfactor;

 73:   MatDestroy(&ctx->A);
 74:   MatDestroy(&ctx->B);
 75:   VecDestroy(&ctx->x1);
 76:   VecDestroy(&ctx->x2);
 77:   VecDestroy(&ctx->y1);
 78:   VecDestroy(&ctx->y2);

 80:   switch (qep->problem_type) {
 81:     case QEP_GENERAL:    i = 0; break;
 82:     case QEP_HERMITIAN:  i = 2; break;
 83:     case QEP_GYROSCOPIC: i = 4; break;
 84:     default: SETERRQ(PetscObjectComm((PetscObject)qep),1,"Wrong value of qep->problem_type");
 85:   }
 86:   i += ctx->cform-1;

 88:   if (ctx->explicitmatrix) {
 89:     ctx->x1 = ctx->x2 = ctx->y1 = ctx->y2 = NULL;
 90:     (*fcreate[i][0])(PetscObjectComm((PetscObject)qep),ctx,&ctx->A);
 91:     (*fcreate[i][1])(PetscObjectComm((PetscObject)qep),ctx,&ctx->B);
 92:   } else {
 93:     VecCreateMPIWithArray(PetscObjectComm((PetscObject)qep),1,qep->nloc,qep->n,NULL,&ctx->x1);
 94:     VecCreateMPIWithArray(PetscObjectComm((PetscObject)qep),1,qep->nloc,qep->n,NULL,&ctx->x2);
 95:     VecCreateMPIWithArray(PetscObjectComm((PetscObject)qep),1,qep->nloc,qep->n,NULL,&ctx->y1);
 96:     VecCreateMPIWithArray(PetscObjectComm((PetscObject)qep),1,qep->nloc,qep->n,NULL,&ctx->y2);
 97:     PetscLogObjectParent(qep,ctx->x1);
 98:     PetscLogObjectParent(qep,ctx->x2);
 99:     PetscLogObjectParent(qep,ctx->y1);
100:     PetscLogObjectParent(qep,ctx->y2);
101:     MatCreateShell(PetscObjectComm((PetscObject)qep),2*qep->nloc,2*qep->nloc,2*qep->n,2*qep->n,ctx,&ctx->A);
102:     MatShellSetOperation(ctx->A,MATOP_MULT,(void(*)(void))fmult[i][0]);
103:     MatShellSetOperation(ctx->A,MATOP_GET_DIAGONAL,(void(*)(void))fgetdiagonal[i][0]);
104:     MatCreateShell(PetscObjectComm((PetscObject)qep),2*qep->nloc,2*qep->nloc,2*qep->n,2*qep->n,ctx,&ctx->B);
105:     MatShellSetOperation(ctx->B,MATOP_MULT,(void(*)(void))fmult[i][1]);
106:     MatShellSetOperation(ctx->B,MATOP_GET_DIAGONAL,(void(*)(void))fgetdiagonal[i][1]);
107:   }
108:   PetscLogObjectParent(qep,ctx->A);
109:   PetscLogObjectParent(qep,ctx->B);

111:   if (!ctx->eps) { QEPLinearGetEPS(qep,&ctx->eps); }
112:   EPSSetOperators(ctx->eps,ctx->A,ctx->B);
113:   if (qep->problem_type==QEP_HERMITIAN) {
114:     EPSSetProblemType(ctx->eps,EPS_GHIEP);
115:   } else {
116:     EPSSetProblemType(ctx->eps,EPS_GNHEP);
117:   }
118:   switch (qep->which) {
119:       case QEP_LARGEST_MAGNITUDE:  which = EPS_LARGEST_MAGNITUDE; break;
120:       case QEP_SMALLEST_MAGNITUDE: which = EPS_SMALLEST_MAGNITUDE; break;
121:       case QEP_LARGEST_REAL:       which = EPS_LARGEST_REAL; break;
122:       case QEP_SMALLEST_REAL:      which = EPS_SMALLEST_REAL; break;
123:       case QEP_LARGEST_IMAGINARY:  which = EPS_LARGEST_IMAGINARY; break;
124:       case QEP_SMALLEST_IMAGINARY: which = EPS_SMALLEST_IMAGINARY; break;
125:       default: SETERRQ(PetscObjectComm((PetscObject)qep),1,"Wrong value of which");
126:   }
127:   EPSSetWhichEigenpairs(ctx->eps,which);
128:   EPSSetLeftVectorsWanted(ctx->eps,qep->leftvecs);
129:   EPSSetDimensions(ctx->eps,qep->nev,qep->ncv,qep->mpd);
130:   EPSSetTolerances(ctx->eps,qep->tol==PETSC_DEFAULT?SLEPC_DEFAULT_TOL/10.0:qep->tol/10.0,qep->max_it);
131:   /* Transfer the trackall option from qep to eps */
132:   QEPGetTrackAll(qep,&trackall);
133:   EPSSetTrackAll(ctx->eps,trackall);
134:   if (ctx->setfromoptionscalled) {
135:     EPSSetFromOptions(ctx->eps);
136:     ctx->setfromoptionscalled = PETSC_FALSE;
137:   }
138:   /* temporary change of target */
139:   if (qep->sfactor!=1.0) {
140:     EPSGetTarget(ctx->eps,&sigma);
141:     EPSSetTarget(ctx->eps,sigma/qep->sfactor);
142:   }
143:   EPSSetUp(ctx->eps);
144:   EPSGetDimensions(ctx->eps,NULL,&qep->ncv,&qep->mpd);
145:   EPSGetTolerances(ctx->eps,NULL,&qep->max_it);
146:   if (qep->nini>0 || qep->ninil>0) { PetscInfo(qep,"Ignoring initial vectors\n"); }
147:   QEPAllocateSolution(qep);
148:   return(0);
149: }

153: /*
154:    QEPLinearSelect_Norm - Auxiliary routine that copies the solution of the
155:    linear eigenproblem to the QEP object. The eigenvector of the generalized
156:    problem is supposed to be
157:                                z = [  x  ]
158:                                    [ l*x ]
159:    The eigenvector is taken from z(1:n) or z(n+1:2*n) depending on the explicitly
160:    computed residual norm.
161:    Finally, x is normalized so that ||x||_2 = 1.
162: */
163: static PetscErrorCode QEPLinearSelect_Norm(QEP qep,EPS eps)
164: {
166:   PetscInt       i;
167:   PetscScalar    *px;
168:   PetscReal      rn1,rn2;
169:   Vec            xr,xi,wr,wi;
170:   Mat            A;
171: #if !defined(PETSC_USE_COMPLEX)
172:   PetscScalar    *py;
173: #endif

176:   EPSGetOperators(eps,&A,NULL);
177:   MatGetVecs(A,&xr,NULL);
178:   VecDuplicate(xr,&xi);
179:   VecCreateMPIWithArray(PetscObjectComm((PetscObject)qep),1,qep->nloc,qep->n,NULL,&wr);
180:   VecCreateMPIWithArray(PetscObjectComm((PetscObject)qep),1,qep->nloc,qep->n,NULL,&wi);
181:   for (i=0;i<qep->nconv;i++) {
182:     EPSGetEigenpair(eps,i,&qep->eigr[i],&qep->eigi[i],xr,xi);
183:     qep->eigr[i] *= qep->sfactor;
184:     qep->eigi[i] *= qep->sfactor;
185: #if !defined(PETSC_USE_COMPLEX)
186:     if (qep->eigi[i]>0.0) {   /* first eigenvalue of a complex conjugate pair */
187:       VecGetArray(xr,&px);
188:       VecGetArray(xi,&py);
189:       VecPlaceArray(wr,px);
190:       VecPlaceArray(wi,py);
191:       SlepcVecNormalize(wr,wi,PETSC_TRUE,NULL);
192:       QEPComputeResidualNorm_Private(qep,qep->eigr[i],qep->eigi[i],wr,wi,&rn1);
193:       VecCopy(wr,qep->V[i]);
194:       VecCopy(wi,qep->V[i+1]);
195:       VecResetArray(wr);
196:       VecResetArray(wi);
197:       VecPlaceArray(wr,px+qep->nloc);
198:       VecPlaceArray(wi,py+qep->nloc);
199:       SlepcVecNormalize(wr,wi,PETSC_TRUE,NULL);
200:       QEPComputeResidualNorm_Private(qep,qep->eigr[i],qep->eigi[i],wr,wi,&rn2);
201:       if (rn1>rn2) {
202:         VecCopy(wr,qep->V[i]);
203:         VecCopy(wi,qep->V[i+1]);
204:       }
205:       VecResetArray(wr);
206:       VecResetArray(wi);
207:       VecRestoreArray(xr,&px);
208:       VecRestoreArray(xi,&py);
209:     } else if (qep->eigi[i]==0.0)   /* real eigenvalue */
210: #endif
211:     {
212:       VecGetArray(xr,&px);
213:       VecPlaceArray(wr,px);
214:       SlepcVecNormalize(wr,NULL,PETSC_FALSE,NULL);
215:       QEPComputeResidualNorm_Private(qep,qep->eigr[i],qep->eigi[i],wr,NULL,&rn1);
216:       VecCopy(wr,qep->V[i]);
217:       VecResetArray(wr);
218:       VecPlaceArray(wr,px+qep->nloc);
219:       SlepcVecNormalize(wr,NULL,PETSC_FALSE,NULL);
220:       QEPComputeResidualNorm_Private(qep,qep->eigr[i],qep->eigi[i],wr,NULL,&rn2);
221:       if (rn1>rn2) {
222:         VecCopy(wr,qep->V[i]);
223:       }
224:       VecResetArray(wr);
225:       VecRestoreArray(xr,&px);
226:     }
227:   }
228:   VecDestroy(&wr);
229:   VecDestroy(&wi);
230:   VecDestroy(&xr);
231:   VecDestroy(&xi);
232:   return(0);
233: }

237: /*
238:    QEPLinearSelect_Simple - Auxiliary routine that copies the solution of the
239:    linear eigenproblem to the QEP object. The eigenvector of the generalized
240:    problem is supposed to be
241:                                z = [  x  ]
242:                                    [ l*x ]
243:    If |l|<1.0, the eigenvector is taken from z(1:n), otherwise from z(n+1:2*n).
244:    Finally, x is normalized so that ||x||_2 = 1.
245: */
246: static PetscErrorCode QEPLinearSelect_Simple(QEP qep,EPS eps)
247: {
249:   PetscInt       i,offset;
250:   PetscScalar    *px;
251:   Vec            xr,xi,w;
252:   Mat            A;

255:   EPSGetOperators(eps,&A,NULL);
256:   MatGetVecs(A,&xr,NULL);
257:   VecDuplicate(xr,&xi);
258:   VecCreateMPIWithArray(PetscObjectComm((PetscObject)qep),1,qep->nloc,qep->n,NULL,&w);
259:   for (i=0;i<qep->nconv;i++) {
260:     EPSGetEigenpair(eps,i,&qep->eigr[i],&qep->eigi[i],xr,xi);
261:     qep->eigr[i] *= qep->sfactor;
262:     qep->eigi[i] *= qep->sfactor;
263:     if (SlepcAbsEigenvalue(qep->eigr[i],qep->eigi[i])>1.0) offset = qep->nloc;
264:     else offset = 0;
265: #if !defined(PETSC_USE_COMPLEX)
266:     if (qep->eigi[i]>0.0) {   /* first eigenvalue of a complex conjugate pair */
267:       VecGetArray(xr,&px);
268:       VecPlaceArray(w,px+offset);
269:       VecCopy(w,qep->V[i]);
270:       VecResetArray(w);
271:       VecRestoreArray(xr,&px);
272:       VecGetArray(xi,&px);
273:       VecPlaceArray(w,px+offset);
274:       VecCopy(w,qep->V[i+1]);
275:       VecResetArray(w);
276:       VecRestoreArray(xi,&px);
277:       SlepcVecNormalize(qep->V[i],qep->V[i+1],PETSC_TRUE,NULL);
278:     } else if (qep->eigi[i]==0.0)   /* real eigenvalue */
279: #endif
280:     {
281:       VecGetArray(xr,&px);
282:       VecPlaceArray(w,px+offset);
283:       VecCopy(w,qep->V[i]);
284:       VecResetArray(w);
285:       VecRestoreArray(xr,&px);
286:       SlepcVecNormalize(qep->V[i],NULL,PETSC_FALSE,NULL);
287:     }
288:   }
289:   VecDestroy(&w);
290:   VecDestroy(&xr);
291:   VecDestroy(&xi);
292:   return(0);
293: }

297: PetscErrorCode QEPSolve_Linear(QEP qep)
298: {
300:   QEP_LINEAR     *ctx = (QEP_LINEAR*)qep->data;
301:   PetscBool      flg=PETSC_FALSE;
302:   PetscScalar    sigma;

305:   EPSSolve(ctx->eps);
306:   EPSGetConverged(ctx->eps,&qep->nconv);
307:   EPSGetIterationNumber(ctx->eps,&qep->its);
308:   EPSGetConvergedReason(ctx->eps,(EPSConvergedReason*)&qep->reason);
309:   EPSGetOperationCounters(ctx->eps,&qep->matvecs,NULL,&qep->linits);
310:   /* restore target */
311:   EPSGetTarget(ctx->eps,&sigma);
312:   EPSSetTarget(ctx->eps,sigma*qep->sfactor);

314:   qep->matvecs *= 2;  /* convention: count one matvec for each non-trivial block in A */
315:   PetscOptionsGetBool(((PetscObject)qep)->prefix,"-qep_linear_select_simple",&flg,NULL);
316:   if (flg) {
317:     QEPLinearSelect_Simple(qep,ctx->eps);
318:   } else {
319:     QEPLinearSelect_Norm(qep,ctx->eps);
320:   }
321:   return(0);
322: }

326: static PetscErrorCode EPSMonitor_Linear(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *ctx)
327: {
328:   PetscInt       i;
329:   QEP            qep = (QEP)ctx;

333:   nconv = 0;
334:   for (i=0;i<PetscMin(nest,qep->ncv);i++) {
335:     qep->eigr[i] = eigr[i];
336:     qep->eigi[i] = eigi[i];
337:     qep->errest[i] = errest[i];
338:     if (0.0 < errest[i] && errest[i] < qep->tol) nconv++;
339:   }
340:   STBackTransform(eps->st,nest,qep->eigr,qep->eigi);
341:   QEPMonitor(qep,its,nconv,qep->eigr,qep->eigi,qep->errest,nest);
342:   return(0);
343: }

347: PetscErrorCode QEPSetFromOptions_Linear(QEP qep)
348: {
350:   PetscBool      set,val;
351:   PetscInt       i;
352:   QEP_LINEAR     *ctx = (QEP_LINEAR*)qep->data;
353:   ST             st;

356:   ctx->setfromoptionscalled = PETSC_TRUE;
357:   PetscOptionsHead("QEP Linear Options");
358:   PetscOptionsInt("-qep_linear_cform","Number of the companion form","QEPLinearSetCompanionForm",ctx->cform,&i,&set);
359:   if (set) {
360:     QEPLinearSetCompanionForm(qep,i);
361:   }
362:   PetscOptionsBool("-qep_linear_explicitmatrix","Use explicit matrix in linearization","QEPLinearSetExplicitMatrix",ctx->explicitmatrix,&val,&set);
363:   if (set) {
364:     QEPLinearSetExplicitMatrix(qep,val);
365:   }
366:   if (!ctx->explicitmatrix) {
367:     /* use as default an ST with shell matrix and Jacobi */
368:     if (!ctx->eps) { QEPLinearGetEPS(qep,&ctx->eps); }
369:     EPSGetST(ctx->eps,&st);
370:     STSetMatMode(st,ST_MATMODE_SHELL);
371:   }
372:   PetscOptionsTail();
373:   return(0);
374: }

378: static PetscErrorCode QEPLinearSetCompanionForm_Linear(QEP qep,PetscInt cform)
379: {
380:   QEP_LINEAR *ctx = (QEP_LINEAR*)qep->data;

383:   if (!cform) return(0);
384:   if (cform==PETSC_DECIDE || cform==PETSC_DEFAULT) ctx->cform = 1;
385:   else {
386:     if (cform!=1 && cform!=2) SETERRQ(PetscObjectComm((PetscObject)qep),PETSC_ERR_ARG_OUTOFRANGE,"Invalid value of argument 'cform'");
387:     ctx->cform = cform;
388:   }
389:   return(0);
390: }

394: /*@
395:    QEPLinearSetCompanionForm - Choose between the two companion forms available
396:    for the linearization of the quadratic problem.

398:    Logically Collective on QEP

400:    Input Parameters:
401: +  qep   - quadratic eigenvalue solver
402: -  cform - 1 or 2 (first or second companion form)

404:    Options Database Key:
405: .  -qep_linear_cform <int> - Choose the companion form

407:    Level: advanced

409: .seealso: QEPLinearGetCompanionForm()
410: @*/
411: PetscErrorCode QEPLinearSetCompanionForm(QEP qep,PetscInt cform)
412: {

418:   PetscTryMethod(qep,"QEPLinearSetCompanionForm_C",(QEP,PetscInt),(qep,cform));
419:   return(0);
420: }

424: static PetscErrorCode QEPLinearGetCompanionForm_Linear(QEP qep,PetscInt *cform)
425: {
426:   QEP_LINEAR *ctx = (QEP_LINEAR*)qep->data;

429:   *cform = ctx->cform;
430:   return(0);
431: }

435: /*@
436:    QEPLinearGetCompanionForm - Returns the number of the companion form that
437:    will be used for the linearization of the quadratic problem.

439:    Not Collective

441:    Input Parameter:
442: .  qep  - quadratic eigenvalue solver

444:    Output Parameter:
445: .  cform - the companion form number (1 or 2)

447:    Level: advanced

449: .seealso: QEPLinearSetCompanionForm()
450: @*/
451: PetscErrorCode QEPLinearGetCompanionForm(QEP qep,PetscInt *cform)
452: {

458:   PetscTryMethod(qep,"QEPLinearGetCompanionForm_C",(QEP,PetscInt*),(qep,cform));
459:   return(0);
460: }

464: static PetscErrorCode QEPLinearSetExplicitMatrix_Linear(QEP qep,PetscBool explicitmatrix)
465: {
466:   QEP_LINEAR *ctx = (QEP_LINEAR*)qep->data;

469:   ctx->explicitmatrix = explicitmatrix;
470:   return(0);
471: }

475: /*@
476:    QEPLinearSetExplicitMatrix - Indicate if the matrices A and B for the linearization
477:    of the quadratic problem must be built explicitly.

479:    Logically Collective on QEP

481:    Input Parameters:
482: +  qep      - quadratic eigenvalue solver
483: -  explicit - boolean flag indicating if the matrices are built explicitly

485:    Options Database Key:
486: .  -qep_linear_explicitmatrix <boolean> - Indicates the boolean flag

488:    Level: advanced

490: .seealso: QEPLinearGetExplicitMatrix()
491: @*/
492: PetscErrorCode QEPLinearSetExplicitMatrix(QEP qep,PetscBool explicitmatrix)
493: {

499:   PetscTryMethod(qep,"QEPLinearSetExplicitMatrix_C",(QEP,PetscBool),(qep,explicitmatrix));
500:   return(0);
501: }

505: static PetscErrorCode QEPLinearGetExplicitMatrix_Linear(QEP qep,PetscBool *explicitmatrix)
506: {
507:   QEP_LINEAR *ctx = (QEP_LINEAR*)qep->data;

510:   *explicitmatrix = ctx->explicitmatrix;
511:   return(0);
512: }

516: /*@
517:    QEPLinearGetExplicitMatrix - Returns the flag indicating if the matrices A and B
518:    for the linearization of the quadratic problem are built explicitly.

520:    Not Collective

522:    Input Parameter:
523: .  qep  - quadratic eigenvalue solver

525:    Output Parameter:
526: .  explicitmatrix - the mode flag

528:    Level: advanced

530: .seealso: QEPLinearSetExplicitMatrix()
531: @*/
532: PetscErrorCode QEPLinearGetExplicitMatrix(QEP qep,PetscBool *explicitmatrix)
533: {

539:   PetscTryMethod(qep,"QEPLinearGetExplicitMatrix_C",(QEP,PetscBool*),(qep,explicitmatrix));
540:   return(0);
541: }

545: static PetscErrorCode QEPLinearSetEPS_Linear(QEP qep,EPS eps)
546: {
548:   QEP_LINEAR     *ctx = (QEP_LINEAR*)qep->data;

551:   PetscObjectReference((PetscObject)eps);
552:   EPSDestroy(&ctx->eps);
553:   ctx->eps = eps;
554:   PetscLogObjectParent(qep,ctx->eps);
555:   qep->setupcalled = 0;
556:   return(0);
557: }

561: /*@
562:    QEPLinearSetEPS - Associate an eigensolver object (EPS) to the
563:    quadratic eigenvalue solver.

565:    Collective on QEP

567:    Input Parameters:
568: +  qep - quadratic eigenvalue solver
569: -  eps - the eigensolver object

571:    Level: advanced

573: .seealso: QEPLinearGetEPS()
574: @*/
575: PetscErrorCode QEPLinearSetEPS(QEP qep,EPS eps)
576: {

583:   PetscTryMethod(qep,"QEPLinearSetEPS_C",(QEP,EPS),(qep,eps));
584:   return(0);
585: }

589: static PetscErrorCode QEPLinearGetEPS_Linear(QEP qep,EPS *eps)
590: {
592:   QEP_LINEAR     *ctx = (QEP_LINEAR*)qep->data;

595:   if (!ctx->eps) {
596:     EPSCreate(PetscObjectComm((PetscObject)qep),&ctx->eps);
597:     EPSSetOptionsPrefix(ctx->eps,((PetscObject)qep)->prefix);
598:     EPSAppendOptionsPrefix(ctx->eps,"qep_");
599:     STSetOptionsPrefix(ctx->eps->st,((PetscObject)ctx->eps)->prefix);
600:     PetscObjectIncrementTabLevel((PetscObject)ctx->eps,(PetscObject)qep,1);
601:     PetscLogObjectParent(qep,ctx->eps);
602:     if (!qep->ip) { QEPGetIP(qep,&qep->ip); }
603:     EPSSetIP(ctx->eps,qep->ip);
604:     EPSMonitorSet(ctx->eps,EPSMonitor_Linear,qep,NULL);
605:   }
606:   *eps = ctx->eps;
607:   return(0);
608: }

612: /*@
613:    QEPLinearGetEPS - Retrieve the eigensolver object (EPS) associated
614:    to the quadratic eigenvalue solver.

616:    Not Collective

618:    Input Parameter:
619: .  qep - quadratic eigenvalue solver

621:    Output Parameter:
622: .  eps - the eigensolver object

624:    Level: advanced

626: .seealso: QEPLinearSetEPS()
627: @*/
628: PetscErrorCode QEPLinearGetEPS(QEP qep,EPS *eps)
629: {

635:   PetscTryMethod(qep,"QEPLinearGetEPS_C",(QEP,EPS*),(qep,eps));
636:   return(0);
637: }

641: PetscErrorCode QEPView_Linear(QEP qep,PetscViewer viewer)
642: {
644:   QEP_LINEAR     *ctx = (QEP_LINEAR*)qep->data;

647:   if (!ctx->eps) { QEPLinearGetEPS(qep,&ctx->eps); }
648:   PetscViewerASCIIPrintf(viewer,"  Linear: %s matrices\n",ctx->explicitmatrix? "explicit": "implicit");
649:   PetscViewerASCIIPrintf(viewer,"  Linear: %s companion form\n",ctx->cform==1? "1st": "2nd");
650:   PetscViewerASCIIPushTab(viewer);
651:   EPSView(ctx->eps,viewer);
652:   PetscViewerASCIIPopTab(viewer);
653:   return(0);
654: }

658: PetscErrorCode QEPReset_Linear(QEP qep)
659: {
661:   QEP_LINEAR     *ctx = (QEP_LINEAR*)qep->data;

664:   if (!ctx->eps) { EPSReset(ctx->eps); }
665:   MatDestroy(&ctx->A);
666:   MatDestroy(&ctx->B);
667:   VecDestroy(&ctx->x1);
668:   VecDestroy(&ctx->x2);
669:   VecDestroy(&ctx->y1);
670:   VecDestroy(&ctx->y2);
671:   QEPReset_Default(qep);
672:   return(0);
673: }

677: PetscErrorCode QEPDestroy_Linear(QEP qep)
678: {
680:   QEP_LINEAR     *ctx = (QEP_LINEAR*)qep->data;

683:   EPSDestroy(&ctx->eps);
684:   PetscFree(qep->data);
685:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearSetCompanionForm_C",NULL);
686:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearGetCompanionForm_C",NULL);
687:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearSetEPS_C",NULL);
688:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearGetEPS_C",NULL);
689:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearSetExplicitMatrix_C",NULL);
690:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearGetExplicitMatrix_C",NULL);
691:   return(0);
692: }

696: PETSC_EXTERN PetscErrorCode QEPCreate_Linear(QEP qep)
697: {
699:   QEP_LINEAR     *ctx;

702:   PetscNewLog(qep,QEP_LINEAR,&ctx);
703:   qep->data                      = (void*)ctx;
704:   qep->ops->solve                = QEPSolve_Linear;
705:   qep->ops->setup                = QEPSetUp_Linear;
706:   qep->ops->setfromoptions       = QEPSetFromOptions_Linear;
707:   qep->ops->destroy              = QEPDestroy_Linear;
708:   qep->ops->reset                = QEPReset_Linear;
709:   qep->ops->view                 = QEPView_Linear;
710:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearSetCompanionForm_C",QEPLinearSetCompanionForm_Linear);
711:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearGetCompanionForm_C",QEPLinearGetCompanionForm_Linear);
712:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearSetEPS_C",QEPLinearSetEPS_Linear);
713:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearGetEPS_C",QEPLinearGetEPS_Linear);
714:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearSetExplicitMatrix_C",QEPLinearSetExplicitMatrix_Linear);
715:   PetscObjectComposeFunction((PetscObject)qep,"QEPLinearGetExplicitMatrix_C",QEPLinearGetExplicitMatrix_Linear);
716:   return(0);
717: }