Actual source code: dvdinitv.c
slepc-3.22.2 2024-12-02
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
6: This file is part of SLEPc.
7: SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9: */
10: /*
11: SLEPc eigensolver: "davidson"
13: Step: initialize subspace V
14: */
16: #include "davidson.h"
18: typedef struct {
19: PetscInt k; /* desired initial subspace size */
20: PetscInt user; /* number of user initial vectors */
21: void *old_initV_data; /* old initV data */
22: } dvdInitV;
24: static PetscErrorCode dvd_initV_classic_0(dvdDashboard *d)
25: {
26: dvdInitV *data = (dvdInitV*)d->initV_data;
27: PetscInt i,user = PetscMin(data->user,d->eps->mpd), l,k;
29: PetscFunctionBegin;
30: PetscCall(BVGetActiveColumns(d->eps->V,&l,&k));
31: /* User vectors are added at the beginning, so no active column should be in V */
32: PetscAssert(data->user==0 || l==0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Consistency broken");
33: /* Generate a set of random initial vectors and orthonormalize them */
34: for (i=l+user;i<l+data->k && i<d->eps->ncv && i-l<d->eps->mpd;i++) PetscCall(BVSetRandomColumn(d->eps->V,i));
35: d->V_tra_s = 0; d->V_tra_e = 0;
36: d->V_new_s = 0; d->V_new_e = i-l;
38: /* After that the user vectors will be destroyed */
39: data->user = 0;
40: PetscFunctionReturn(PETSC_SUCCESS);
41: }
43: static PetscErrorCode dvd_initV_krylov_0(dvdDashboard *d)
44: {
45: dvdInitV *data = (dvdInitV*)d->initV_data;
46: PetscInt i,user = PetscMin(data->user,d->eps->mpd),l,k;
47: Vec av,v1,v2;
49: PetscFunctionBegin;
50: PetscCall(BVGetActiveColumns(d->eps->V,&l,&k));
51: /* User vectors are added at the beginning, so no active column should be in V */
52: PetscAssert(data->user==0 || l==0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Consistency broken");
54: /* If needed, generate a random vector for starting the arnoldi method */
55: if (user == 0) {
56: PetscCall(BVSetRandomColumn(d->eps->V,l));
57: user = 1;
58: }
60: /* Perform k steps of Arnoldi with the operator K^{-1}*(t[1]*A-t[2]*B) */
61: PetscCall(dvd_orthV(d->eps->V,l,l+user));
62: for (i=l+user;i<l+data->k && i<d->eps->ncv && i-l<d->eps->mpd;i++) {
63: /* aux <- theta[1]A*in - theta[0]*B*in */
64: PetscCall(BVGetColumn(d->eps->V,i,&v1));
65: PetscCall(BVGetColumn(d->eps->V,i-user,&v2));
66: PetscCall(BVGetColumn(d->auxBV,0,&av));
67: if (d->B) {
68: PetscCall(MatMult(d->A,v2,v1));
69: PetscCall(MatMult(d->B,v2,av));
70: PetscCall(VecAXPBY(av,d->target[1],-d->target[0],v1));
71: } else {
72: PetscCall(MatMult(d->A,v2,av));
73: PetscCall(VecAXPBY(av,-d->target[0],d->target[1],v2));
74: }
75: PetscCall(d->improvex_precond(d,0,av,v1));
76: PetscCall(BVRestoreColumn(d->eps->V,i,&v1));
77: PetscCall(BVRestoreColumn(d->eps->V,i-user,&v2));
78: PetscCall(BVRestoreColumn(d->auxBV,0,&av));
79: PetscCall(dvd_orthV(d->eps->V,i,i+1));
80: }
82: d->V_tra_s = 0; d->V_tra_e = 0;
83: d->V_new_s = 0; d->V_new_e = i-l;
85: /* After that the user vectors will be destroyed */
86: data->user = 0;
87: PetscFunctionReturn(PETSC_SUCCESS);
88: }
90: static PetscErrorCode dvd_initV_d(dvdDashboard *d)
91: {
92: dvdInitV *data = (dvdInitV*)d->initV_data;
94: PetscFunctionBegin;
95: /* Restore changes in dvdDashboard */
96: d->initV_data = data->old_initV_data;
98: /* Free local data */
99: PetscCall(PetscFree(data));
100: PetscFunctionReturn(PETSC_SUCCESS);
101: }
103: PetscErrorCode dvd_initV(dvdDashboard *d, dvdBlackboard *b, PetscInt k,PetscInt user, PetscBool krylov)
104: {
105: dvdInitV *data;
107: PetscFunctionBegin;
108: /* Setting configuration constrains */
109: b->max_size_V = PetscMax(b->max_size_V, k);
111: /* Setup the step */
112: if (b->state >= DVD_STATE_CONF) {
113: PetscCall(PetscNew(&data));
114: data->k = k;
115: data->user = user;
116: data->old_initV_data = d->initV_data;
117: d->initV_data = data;
118: if (krylov) d->initV = dvd_initV_krylov_0;
119: else d->initV = dvd_initV_classic_0;
120: PetscCall(EPSDavidsonFLAdd(&d->destroyList,dvd_initV_d));
121: }
122: PetscFunctionReturn(PETSC_SUCCESS);
123: }
125: PetscErrorCode dvd_orthV(BV V,PetscInt V_new_s,PetscInt V_new_e)
126: {
127: PetscInt i;
129: PetscFunctionBegin;
130: for (i=V_new_s;i<V_new_e;i++) PetscCall(BVOrthonormalizeColumn(V,i,PETSC_TRUE,NULL,NULL));
131: PetscFunctionReturn(PETSC_SUCCESS);
132: }