| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
| 3 | SLEPc - Scalable Library for Eigenvalue Problem Computations | ||
| 4 | Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain | ||
| 5 | |||
| 6 | This file is part of SLEPc. | ||
| 7 | SLEPc is distributed under a 2-clause BSD license (see LICENSE). | ||
| 8 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||
| 9 | */ | ||
| 10 | |||
| 11 | static char help[] = "1-D discrete Kohn-Sham model solved as a Nonlinear Eigenvalue Problem with eigenvector dependence (NEPv).\n\n" | ||
| 12 | "Implemented by embedding an EPS inside a nonlinear SNES loop.\n\n" | ||
| 13 | "The Kohn-Sham (KS) equations simplify a complex, interacting many-electron system by mapping it\n" | ||
| 14 | "onto an equivalent system of noninteracting particles. The goal is to find the single-particle\n" | ||
| 15 | "wavefunctions (eigenvectors) and orbital energies (eigenvalues) that self-consistently describe the ground state.\n\n" | ||
| 16 | "The nonlinear Hamiltonian matrix is defined as H(X) = L + alpha * Diag(L^-1 * rho(X)), where:\n" | ||
| 17 | " L = 1-D discrete Laplacian operator matrix.\n" | ||
| 18 | " rho = electronic density vector computed from the current block of eigenvectors X as rho = diag(X * X').\n\n" | ||
| 19 | "The command line options are:\n" | ||
| 20 | " -n <n>, where <n> = number of grid points.\n" | ||
| 21 | " -k <k>, where <k> = number of eigenvectors to compute.\n" | ||
| 22 | " -alpha <alpha>, where <alpha> = real scaling parameter controlling the nonlinearity.\n" | ||
| 23 | " -verbose, to print the converged Hamiltonian diagonal and its sum.\n\n"; | ||
| 24 | |||
| 25 | #include <slepceps.h> | ||
| 26 | |||
| 27 | /* | ||
| 28 | Context structure to store the necessary data regarding the discrete Kohn-Sham (DKS) problem | ||
| 29 | as well as the objects needed for the nonlinear iteration. | ||
| 30 | */ | ||
| 31 | typedef struct { | ||
| 32 | // DKS context | ||
| 33 | |||
| 34 | // Inputs | ||
| 35 | PetscInt n; // Spatial mesh size | ||
| 36 | PetscInt k; // Number of eigenvectors to compute | ||
| 37 | PetscReal alpha; // Parameter controlling the nonlinearity | ||
| 38 | |||
| 39 | // Constants | ||
| 40 | Mat L; // 1D discrete Laplacian matrix | ||
| 41 | |||
| 42 | // Working vectors and base solvers | ||
| 43 | KSP ksp; // Linear solver (to apply L^-1) | ||
| 44 | Vec rho; // Vector to store the electronic density | ||
| 45 | Vec z; // Intermediate vector to store the result z = L^-1 * rho | ||
| 46 | Vec xr; // Temporary vector to extract eigenvectors during each iteration | ||
| 47 | |||
| 48 | // Nonlinear iteration context | ||
| 49 | EPS eps; // Solver for each H | ||
| 50 | Mat H; // Hamiltonian matrix | ||
| 51 | BV X; // Block of eigenvectors | ||
| 52 | Vec *initial_space; // Array of vectors to store the EPS initial space | ||
| 53 | } DKSContext; | ||
| 54 | |||
| 55 | /* | ||
| 56 | Initialize the context for the 1D discrete Kohn-Sham problem. | ||
| 57 | |||
| 58 | This function allocates the necessary memory, builds the 1D Laplacian operator, | ||
| 59 | and configures the linear solver (KSP) to apply L^-1. | ||
| 60 | |||
| 61 | Arguments: | ||
| 62 | comm - MPI communicator | ||
| 63 | n - Spatial mesh size | ||
| 64 | k - Number of eigenvectors to compute | ||
| 65 | alpha - Parameter controlling the nonlinearity | ||
| 66 | ctx_out - Output pointer where the created context will be stored | ||
| 67 | */ | ||
| 68 | 40 | PetscErrorCode DKSCreateContext(MPI_Comm comm,PetscInt n,PetscInt k,PetscReal alpha,DKSContext **ctx_out) | |
| 69 | { | ||
| 70 | 40 | DKSContext *ctx; | |
| 71 | 40 | PetscInt Istart,Iend,i; | |
| 72 | 40 | PC pc; | |
| 73 | |||
| 74 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
40 | PetscFunctionBeginUser; |
| 75 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(PetscNew(&ctx)); |
| 76 | 40 | ctx->n=n; | |
| 77 | 40 | ctx->k=k; | |
| 78 | 40 | ctx->alpha=alpha; | |
| 79 | |||
| 80 | // 1. Create and fill the Laplacian L | ||
| 81 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(MatCreate(comm,&ctx->L)); |
| 82 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(MatSetSizes(ctx->L,PETSC_DECIDE,PETSC_DECIDE,n,n)); |
| 83 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(MatSetFromOptions(ctx->L)); |
| 84 | |||
| 85 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(MatGetOwnershipRange(ctx->L,&Istart,&Iend)); |
| 86 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
240 | for (i=Istart;i<Iend;i++) { |
| 87 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
200 | PetscCall(MatSetValue(ctx->L,i,i,2.0,INSERT_VALUES)); |
| 88 |
6/8✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
200 | if (i>0) PetscCall(MatSetValue(ctx->L,i,i-1,-1.0,INSERT_VALUES)); |
| 89 |
6/8✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
200 | if (i<n-1) PetscCall(MatSetValue(ctx->L,i,i+1,-1.0,INSERT_VALUES)); |
| 90 | } | ||
| 91 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(MatAssemblyBegin(ctx->L,MAT_FINAL_ASSEMBLY)); |
| 92 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(MatAssemblyEnd(ctx->L,MAT_FINAL_ASSEMBLY)); |
| 93 | |||
| 94 | // 2. Configure the KSP | ||
| 95 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(KSPCreate(comm,&ctx->ksp)); |
| 96 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(KSPSetOperators(ctx->ksp,ctx->L,ctx->L)); |
| 97 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(KSPSetType(ctx->ksp,KSPPREONLY)); |
| 98 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(KSPGetPC(ctx->ksp,&pc)); |
| 99 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(PCSetType(pc,PCCHOLESKY)); |
| 100 | |||
| 101 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
40 | if (PetscDefined(HAVE_MUMPS)) PetscCall(PCFactorSetMatSolverType(pc,MATSOLVERMUMPS)); |
| 102 | |||
| 103 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(KSPSetFromOptions(ctx->ksp)); |
| 104 | |||
| 105 | // 3. Create internal work vectors | ||
| 106 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(MatCreateVecs(ctx->L,&ctx->rho,&ctx->z)); |
| 107 | |||
| 108 | 40 | *ctx_out=ctx; | |
| 109 |
5/12✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
40 | PetscFunctionReturn(PETSC_SUCCESS); |
| 110 | } | ||
| 111 | |||
| 112 | /* | ||
| 113 | Configure the SLEPc objects necessary for the nonlinear iteration. | ||
| 114 | |||
| 115 | This function prepares the Hamiltonian matrix by cloning the structure of the Laplacian, | ||
| 116 | initializes the basis vectors (BV) block for the eigenvectors, and configures the eigenvalue | ||
| 117 | solver (EPS) by defining the problem type and adjusting its tolerance. | ||
| 118 | |||
| 119 | Arguments: | ||
| 120 | ctx - Pointer to the previously initialized DKS context | ||
| 121 | tol - Desired tolerance for the internal eigenvalue solver | ||
| 122 | */ | ||
| 123 | 40 | PetscErrorCode DKSSetUpIterationWorkspace(DKSContext *ctx,PetscReal tol) | |
| 124 | { | ||
| 125 | 40 | MPI_Comm comm; | |
| 126 | |||
| 127 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
40 | PetscFunctionBeginUser; |
| 128 | 40 | comm = PetscObjectComm((PetscObject)ctx->L); | |
| 129 | /* Prepare the H matrix */ | ||
| 130 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(MatDuplicate(ctx->L,MAT_DO_NOT_COPY_VALUES,&ctx->H)); |
| 131 | |||
| 132 | /* Configure the eigenvector block X */ | ||
| 133 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(BVCreate(comm,&ctx->X)); |
| 134 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(BVSetSizesFromVec(ctx->X,ctx->rho,ctx->k)); |
| 135 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(BVSetFromOptions(ctx->X)); |
| 136 | |||
| 137 | /* Configure SLEPc EPS */ | ||
| 138 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(EPSCreate(comm,&ctx->eps)); |
| 139 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(EPSSetProblemType(ctx->eps,EPS_HEP)); |
| 140 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(EPSSetWhichEigenpairs(ctx->eps,EPS_SMALLEST_REAL)); |
| 141 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(EPSSetDimensions(ctx->eps,ctx->k,PETSC_DECIDE,PETSC_DECIDE)); |
| 142 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(EPSSetTolerances(ctx->eps,tol,PETSC_DECIDE)); |
| 143 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(EPSSetFromOptions(ctx->eps)); |
| 144 | |||
| 145 | /* Pre-allocate temporary vectors for the nonlinear iteration loop */ | ||
| 146 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(VecDuplicateVecs(ctx->rho,ctx->k,&ctx->initial_space)); |
| 147 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(MatCreateVecs(ctx->H,&ctx->xr,NULL)); |
| 148 |
5/12✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
8 | PetscFunctionReturn(PETSC_SUCCESS); |
| 149 | } | ||
| 150 | |||
| 151 | /* | ||
| 152 | Generate the initial guess X0 using the exact eigenvectors of the 1D Laplacian. | ||
| 153 | |||
| 154 | This function fills the vector block X with the initial guess, which greatly | ||
| 155 | improves the convergence of the nonlinear iteration loop. | ||
| 156 | |||
| 157 | Formula used: vv = [1:n]'/(n+1)*pi; X0 = sin(vv * [1:k])*sqrt(2/(n+1)); | ||
| 158 | |||
| 159 | Arguments: | ||
| 160 | ctx - Pointer to the previously initialized DKS context | ||
| 161 | */ | ||
| 162 | 40 | PetscErrorCode DKSGenerateInitialGuess(DKSContext *ctx) | |
| 163 | { | ||
| 164 | 40 | PetscInt Istart,Iend,i,j; | |
| 165 | 40 | PetscReal h_val,norm_factor,val; | |
| 166 | 40 | Vec col; | |
| 167 | 40 | PetscScalar *x_local; | |
| 168 | |||
| 169 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
40 | PetscFunctionBeginUser; |
| 170 | // Mathematical constants of the formula | ||
| 171 | // X0 = sin( [1:n]' * [1:k] * pi/(n+1) ) * sqrt(2/(n+1)); | ||
| 172 | 40 | h_val=PETSC_PI/(ctx->n+1.0); | |
| 173 | 40 | norm_factor=PetscSqrtReal(2.0/(ctx->n+1.0)); | |
| 174 | |||
| 175 | // Iterate over each column (eigenvector) | ||
| 176 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
160 | for (j=0;j<ctx->k;j++) { |
| 177 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
120 | PetscCall(BVGetColumn(ctx->X,j,&col)); |
| 178 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
120 | PetscCall(VecGetOwnershipRange(col,&Istart,&Iend)); |
| 179 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
120 | PetscCall(VecGetArray(col,&x_local)); |
| 180 | |||
| 181 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
720 | for (i=Istart;i<Iend;i++) { |
| 182 | // i and j start at 0 in C, so we add 1 for the mathematical formula | ||
| 183 | 600 | val=PetscSinReal((i+1.0)*(j+1.0)*h_val)*norm_factor; | |
| 184 | 600 | x_local[i-Istart]=val; | |
| 185 | } | ||
| 186 | |||
| 187 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
120 | PetscCall(VecRestoreArray(col,&x_local)); |
| 188 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
120 | PetscCall(BVRestoreColumn(ctx->X,j,&col)); |
| 189 | } | ||
| 190 |
5/12✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
8 | PetscFunctionReturn(PETSC_SUCCESS); |
| 191 | } | ||
| 192 | |||
| 193 | /* | ||
| 194 | Compute the eigenvector-dependent term from the eigenvectors. | ||
| 195 | |||
| 196 | In the context of the Kohn-Sham model, this function computes the electronic | ||
| 197 | density rho(X) as the sum of the squares of the components of each eigenvector. | ||
| 198 | The formula used is: rho(X) = diag(X * X'). | ||
| 199 | |||
| 200 | Arguments: | ||
| 201 | ctx - Pointer to the initialized DKS context | ||
| 202 | rho_out - Pre-created vector where the computed term will be stored | ||
| 203 | */ | ||
| 204 | 542 | PetscErrorCode DKSComputeEigvecDependentTerm(DKSContext *ctx,Vec rho_out) | |
| 205 | { | ||
| 206 | 542 | PetscInt i,j,n_loc; | |
| 207 | 542 | Vec col; | |
| 208 | 542 | const PetscScalar *x_local; | |
| 209 | 542 | PetscScalar *rho_local; | |
| 210 | |||
| 211 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
542 | PetscFunctionBeginUser; |
| 212 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
542 | PetscCall(VecSet(rho_out,0.0)); |
| 213 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
542 | PetscCall(VecGetLocalSize(rho_out,&n_loc)); |
| 214 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
542 | PetscCall(VecGetArray(rho_out,&rho_local)); |
| 215 | |||
| 216 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
2168 | for (j=0;j<ctx->k;j++) { |
| 217 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
1626 | PetscCall(BVGetColumn(ctx->X,j,&col)); |
| 218 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
1626 | PetscCall(VecGetArrayRead(col,&x_local)); |
| 219 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
9756 | for (i=0;i<n_loc;i++) { |
| 220 | 8130 | rho_local[i]+=x_local[i]*PetscConj(x_local[i]); | |
| 221 | } | ||
| 222 | |||
| 223 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
1626 | PetscCall(VecRestoreArrayRead(col,&x_local)); |
| 224 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
1626 | PetscCall(BVRestoreColumn(ctx->X,j,&col)); |
| 225 | } | ||
| 226 | |||
| 227 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
542 | PetscCall(VecRestoreArray(rho_out,&rho_local)); |
| 228 |
5/12✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
106 | PetscFunctionReturn(PETSC_SUCCESS); |
| 229 | } | ||
| 230 | |||
| 231 | /* | ||
| 232 | Build the Hamiltonian from an input eigenvector-dependent term. | ||
| 233 | |||
| 234 | This function solves the linear system L * z = rho_in using the configured | ||
| 235 | KSP solver. Then, it assembles the updated Hamiltonian matrix stored in the context | ||
| 236 | using the formula: H = L + alpha * Diag(z), where z = L^-1 * rho_in. | ||
| 237 | |||
| 238 | Arguments: | ||
| 239 | ctx - Pointer to the initialized DKS context (ctx->H and ctx->z are updated) | ||
| 240 | rho_in - Vector with the proposed input eigenvector-dependent term | ||
| 241 | */ | ||
| 242 | 502 | PetscErrorCode DKSBuildHamiltonian(DKSContext *ctx,Vec rho_in) | |
| 243 | { | ||
| 244 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
502 | PetscFunctionBeginUser; |
| 245 | // 1. Solve L * z = rho_in | ||
| 246 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
502 | PetscCall(KSPSolve(ctx->ksp,rho_in,ctx->z)); |
| 247 | |||
| 248 | // 2. Build H = L + alpha * Diag(z) | ||
| 249 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
502 | PetscCall(MatCopy(ctx->L,ctx->H,SAME_NONZERO_PATTERN)); |
| 250 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
502 | PetscCall(VecScale(ctx->z,ctx->alpha)); |
| 251 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
502 | PetscCall(MatDiagonalSet(ctx->H,ctx->z,ADD_VALUES)); |
| 252 |
5/12✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
98 | PetscFunctionReturn(PETSC_SUCCESS); |
| 253 | } | ||
| 254 | |||
| 255 | /* | ||
| 256 | Evaluation function (Callback) for the SNES nonlinear solver. | ||
| 257 | |||
| 258 | In each SNES iteration, this function receives a proposed eigenvector-dependent | ||
| 259 | term (rho_in), builds the Hamiltonian, solves the eigenvalue equation, computes the | ||
| 260 | resulting term, and returns the residual F = rho_out - rho_in. | ||
| 261 | |||
| 262 | Arguments: | ||
| 263 | snes - The nonlinear solver context | ||
| 264 | rho_in - Input state (eigenvector-dependent term) proposed by SNES | ||
| 265 | F - Vector where the computed residual will be stored | ||
| 266 | ctx_void - Pointer to the user's DKS context (DKSContext) | ||
| 267 | */ | ||
| 268 | 502 | PetscErrorCode DKSNonlinearIteration(SNES snes,Vec rho_in,Vec F,void *ctx_void) | |
| 269 | { | ||
| 270 | 502 | DKSContext *ctx=(DKSContext*)ctx_void; | |
| 271 | 502 | PetscInt j,nconv; | |
| 272 | 502 | Vec col; | |
| 273 | 502 | MPI_Comm comm; | |
| 274 | |||
| 275 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
502 | PetscFunctionBeginUser; |
| 276 | 502 | comm = PetscObjectComm((PetscObject)ctx->L); | |
| 277 | /* 1. Build the physics (Hamiltonian) with the guess proposed by SNES */ | ||
| 278 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
502 | PetscCall(DKSBuildHamiltonian(ctx,rho_in)); |
| 279 | |||
| 280 | /* 2. Solve with the current H */ | ||
| 281 | // Pass our newly built H matrix to SLEPc | ||
| 282 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
502 | PetscCall(EPSSetOperators(ctx->eps,ctx->H,NULL)); |
| 283 | |||
| 284 | // Extract the eigenvectors from the previous iteration to use as the initial space | ||
| 285 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
2008 | for (j=0; j<ctx->k; j++) { |
| 286 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
1506 | PetscCall(BVGetColumn(ctx->X,j,&col)); |
| 287 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
1506 | PetscCall(VecCopy(col,ctx->initial_space[j])); |
| 288 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
1506 | PetscCall(BVRestoreColumn(ctx->X,j,&col)); |
| 289 | } | ||
| 290 | |||
| 291 | // Inject the initial space into the EPS | ||
| 292 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
502 | PetscCall(EPSSetInitialSpace(ctx->eps,ctx->k,ctx->initial_space)); |
| 293 | |||
| 294 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
502 | PetscCall(EPSSolve(ctx->eps)); |
| 295 | |||
| 296 | // (Safety check: verify that SLEPc has not failed internally) | ||
| 297 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
502 | PetscCall(EPSGetConverged(ctx->eps,&nconv)); |
| 298 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
502 | PetscCheck(nconv>=ctx->k,comm,PETSC_ERR_NOT_CONVERGED,"SLEPc only converged %" PetscInt_FMT " out of %" PetscInt_FMT " eigenvalues in this SNES iteration",nconv,ctx->k); |
| 299 | |||
| 300 | /* 3. Extract the new eigenvectors and store them in ctx->X */ | ||
| 301 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
2008 | for (j=0;j<ctx->k;j++) { |
| 302 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
1506 | PetscCall(EPSGetEigenvector(ctx->eps,j,ctx->xr,NULL)); // Extracts the j-th vector |
| 303 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
1506 | PetscCall(BVGetColumn(ctx->X,j,&col)); // Gets column j of X |
| 304 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
1506 | PetscCall(VecCopy(ctx->xr,col)); // Copies the data |
| 305 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
1506 | PetscCall(BVRestoreColumn(ctx->X,j,&col)); // Restores the column |
| 306 | } | ||
| 307 | |||
| 308 | /* 4. Compute the new eigenvector-dependent term */ | ||
| 309 | // We use ctx->rho as a temporary work vector to store rho_out | ||
| 310 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
502 | PetscCall(DKSComputeEigvecDependentTerm(ctx,ctx->rho)); |
| 311 | |||
| 312 | /* 5. Calculate the nonlinear residual: F = rho_in - rho_out */ | ||
| 313 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
502 | PetscCall(VecWAXPY(F,-1.0,ctx->rho,rho_in)); |
| 314 |
5/12✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
98 | PetscFunctionReturn(PETSC_SUCCESS); |
| 315 | } | ||
| 316 | |||
| 317 | /* | ||
| 318 | Free the memory associated with the DKS context. | ||
| 319 | |||
| 320 | This function destroys all internal PETSc objects created during | ||
| 321 | initialization and frees the memory of the main structure. | ||
| 322 | |||
| 323 | Arguments: | ||
| 324 | ctx - Pointer to the DKS context (set to NULL upon completion) | ||
| 325 | */ | ||
| 326 | 40 | PetscErrorCode DKSDestroyContext(DKSContext **ctx) | |
| 327 | { | ||
| 328 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
40 | PetscFunctionBeginUser; |
| 329 |
2/14✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
40 | if (!*ctx) PetscFunctionReturn(PETSC_SUCCESS); |
| 330 | |||
| 331 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(MatDestroy(&(*ctx)->L)); |
| 332 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(KSPDestroy(&(*ctx)->ksp)); |
| 333 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(VecDestroy(&(*ctx)->rho)); |
| 334 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(VecDestroy(&(*ctx)->z)); |
| 335 | |||
| 336 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(MatDestroy(&(*ctx)->H)); |
| 337 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(BVDestroy(&(*ctx)->X)); |
| 338 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(EPSDestroy(&(*ctx)->eps)); |
| 339 | |||
| 340 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(VecDestroy(&(*ctx)->xr)); |
| 341 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(VecDestroyVecs((*ctx)->k, &(*ctx)->initial_space)); |
| 342 | |||
| 343 |
5/8✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
40 | PetscCall(PetscFree(*ctx)); |
| 344 |
5/12✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
8 | PetscFunctionReturn(PETSC_SUCCESS); |
| 345 | } | ||
| 346 | |||
| 347 | 40 | int main(int argc,char **argv) | |
| 348 | { | ||
| 349 | 40 | DKSContext *ctx; | |
| 350 | 40 | Vec H_diag,rho_guess; | |
| 351 | 40 | PetscScalar diagonal_sum,kr; | |
| 352 | 40 | PetscInt n=5,k=3,maxit=100,its,i; | |
| 353 | 40 | PetscInt nconv; | |
| 354 | 40 | PetscReal alpha=0.5,rtol=SLEPC_DEFAULT_TOL,stol=1e-12; | |
| 355 | 40 | SNES snes; | |
| 356 | 40 | Vec F; // Vector to store the residual (F = rho_out - rho_in) | |
| 357 | 40 | PetscBool verbose=PETSC_FALSE; | |
| 358 | 40 | SNESConvergedReason reason; | |
| 359 | 40 | SNESLineSearch linesearch; | |
| 360 | |||
| 361 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
40 | PetscFunctionBeginUser; |
| 362 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SlepcInitialize(&argc,&argv,NULL,help)); |
| 363 | |||
| 364 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(PetscPrintf(PETSC_COMM_WORLD,"--- DKS SNES NEPv ---\n")); |
| 365 | |||
| 366 | /* 1. Read options from the command line (if provided by the user) */ | ||
| 367 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL)); |
| 368 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(PetscOptionsGetInt(NULL,NULL,"-k",&k,NULL)); |
| 369 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(PetscOptionsGetReal(NULL,NULL,"-alpha",&alpha,NULL)); |
| 370 | |||
| 371 | /* 2. Initialization of the DKS context */ | ||
| 372 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(DKSCreateContext(PETSC_COMM_WORLD,n,k,alpha,&ctx)); |
| 373 | |||
| 374 | /* 3. Configure general objects for the nonlinear iteration (Matrices, EPS, eigenvectors) */ | ||
| 375 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(DKSSetUpIterationWorkspace(ctx,rtol*0.1)); |
| 376 | |||
| 377 | /* 4. Generate the initial guess for the eigenvectors and their density */ | ||
| 378 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(DKSGenerateInitialGuess(ctx)); |
| 379 | |||
| 380 | /* 5. Calculate the initial density (rho_guess) from X0 */ | ||
| 381 | // Since SNES works with densities, the density is extracted from our X0 | ||
| 382 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(VecDuplicate(ctx->rho,&rho_guess)); |
| 383 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(DKSComputeEigvecDependentTerm(ctx,rho_guess)); |
| 384 | |||
| 385 | /* 6. Prepare the residual vector F by cloning the structure of rho */ | ||
| 386 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(VecDuplicate(ctx->rho,&F)); |
| 387 | |||
| 388 | /* 7. Create and set up the nonlinear solver engine (SNES) */ | ||
| 389 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESCreate(PETSC_COMM_WORLD,&snes)); |
| 390 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESSetFunction(snes,F,DKSNonlinearIteration,ctx)); |
| 391 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESSetTolerances(snes,PETSC_DETERMINE,rtol,stol,maxit,PETSC_DETERMINE)); |
| 392 | |||
| 393 | // Default -> NRICHARDSON with step lambda = 1.0 to simulate basic SCF | ||
| 394 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESSetType(snes,SNESNRICHARDSON)); |
| 395 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESGetLineSearch(snes,&linesearch)); |
| 396 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESLineSearchSetType(linesearch,SNESLINESEARCHNONE)); |
| 397 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESLineSearchSetDamping(linesearch,1.0)); |
| 398 | |||
| 399 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESSetFromOptions(snes)); |
| 400 | |||
| 401 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESGetTolerances(snes,NULL,&rtol,NULL,&maxit,NULL)); |
| 402 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Current parameters: n=%" PetscInt_FMT ", k=%" PetscInt_FMT ", alpha=%g, rtol=%g, maxit=%" PetscInt_FMT "\n",n,k,(double)alpha,(double)rtol,maxit)); |
| 403 | |||
| 404 | /* 8. Nonlinear iteration loop */ | ||
| 405 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nStarting nonlinear iterations...\n")); |
| 406 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESSolve(snes,NULL,rho_guess)); |
| 407 | |||
| 408 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESGetConvergedReason(snes,&reason)); |
| 409 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESGetIterationNumber(snes,&its)); |
| 410 | |||
| 411 | /* 9. Result analysis */ | ||
| 412 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
40 | if (reason>0) { |
| 413 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(PetscPrintf(PETSC_COMM_WORLD,"--> CONVERGENCE REACHED in %" PetscInt_FMT " iterations (Reason: %s).\n",its,SNESConvergedReasons[reason])); |
| 414 | |||
| 415 | /* Show the final result */ | ||
| 416 | |||
| 417 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(EPSGetConverged(ctx->eps,&nconv)); |
| 418 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\n--- Eigenvalues (%" PetscInt_FMT " found) ---\n",nconv)); |
| 419 | |||
| 420 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
240 | for (i=0;i<nconv;i++) { |
| 421 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
200 | PetscCall(EPSGetEigenvalue(ctx->eps,i,&kr,NULL)); |
| 422 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
200 | PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Eigenvalue[%" PetscInt_FMT "] = %10.6f\n",i,(double)PetscRealPart(kr))); |
| 423 | } | ||
| 424 | |||
| 425 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(PetscOptionsHasName(NULL,NULL,"-verbose",&verbose)); |
| 426 | |||
| 427 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
40 | if (verbose) { |
| 428 | ✗ | PetscCall(MatCreateVecs(ctx->H,NULL,&H_diag)); | |
| 429 | ✗ | PetscCall(MatGetDiagonal(ctx->H,H_diag)); | |
| 430 | |||
| 431 | ✗ | PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Diagonal of the converged Hamiltonian:\n")); | |
| 432 | ✗ | PetscCall(VecView(H_diag,PETSC_VIEWER_STDOUT_WORLD)); | |
| 433 | |||
| 434 | ✗ | PetscCall(VecSum(H_diag,&diagonal_sum)); | |
| 435 | ✗ | PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Sum of the diagonal: %g\n",(double)PetscRealPart(diagonal_sum))); | |
| 436 | ✗ | PetscCall(VecDestroy(&H_diag)); | |
| 437 | } | ||
| 438 | |||
| 439 | } else { | ||
| 440 | ✗ | PetscCall(PetscPrintf(PETSC_COMM_WORLD,"--> ERROR: SNES did not converge (Reason: %s)\n",SNESConvergedReasons[reason])); | |
| 441 | } | ||
| 442 | |||
| 443 | /* 10. Clean up memory */ | ||
| 444 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(VecDestroy(&F)); |
| 445 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(VecDestroy(&rho_guess)); |
| 446 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(SNESDestroy(&snes)); |
| 447 |
4/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
40 | PetscCall(DKSDestroyContext(&ctx)); |
| 448 | |||
| 449 |
2/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
40 | PetscCall(SlepcFinalize()); |
| 450 | return 0; | ||
| 451 | } | ||
| 452 | |||
| 453 | /*TEST | ||
| 454 | |||
| 455 | testset: | ||
| 456 | filter: sed -e "s/1.364212/1.364211/" -e "s/4.864809/4.864808/" -e "s/1.92185[24]/1.921853/" -e "s/2.931104/2.931103/" -e "s/3.95751[46]/3.957515/" -e "s/rtol=1e-05/rtol=1e-08/" -e "s/rtol=1e-16/rtol=1e-08/" -e "s/[0-9]\{1,\} iterations/8 iterations/" -e "s/CONVERGED_SNORM_RELATIVE/CONVERGED_FNORM_RELATIVE/" | ||
| 457 | output_file: output/ex59_1.out | ||
| 458 | test: | ||
| 459 | suffix: 1 | ||
| 460 | test: | ||
| 461 | suffix: 2 | ||
| 462 | args: -snes_type anderson -snes_anderson_m 7 | ||
| 463 | test: | ||
| 464 | suffix: 3 | ||
| 465 | args: -snes_type ngmres -npc_snes_type nrichardson -snes_npc_side right | ||
| 466 | test: | ||
| 467 | suffix: 4 | ||
| 468 | args: -snes_type composite -snes_composite_type additiveoptimal -snes_composite_sneses anderson,nrichardson -sub_0_snes_anderson_m 7 -sub_0_snes_anderson_beta 0.4 | ||
| 469 | |||
| 470 | TEST*/ | ||
| 471 |