|
**VERSION>=2021.09.18**
|
|
[[_TOC_]]
|
|
|
|
|
|
# Tracking the states
|
|
# Tracking the states using build in mechanism
|
|
|
|
**VERSION>=2021.09.18**
|
|
|
|
## Defining the subset
|
|
W-SLDA Toolkit allows the tracking of observables arising from selected states in time. Presently, the following quantities can be tracked:
|
|
W-SLDA Toolkit allows the tracking of observables arising from selected states in time. Presently, the following quantities can be tracked:
|
|
* `subset_rho_a`:
|
|
* `subset_rho_a`:
|
|
$`n_{\uparrow}^{\textrm{(subset)}}(r)= \sum_{E_{\textrm{min}}^{\textrm{(subset)}}<E_n<E_{\textrm{max}}^{\textrm{(subset)}}}|u_{n,\uparrow}(r)|^2 f_{\beta}(E_n)`$
|
|
$`n_{\uparrow}^{\textrm{(subset)}}(r)= \sum_{E_{\textrm{min}}^{\textrm{(subset)}}<E_n<E_{\textrm{max}}^{\textrm{(subset)}}}|u_{n,\uparrow}(r)|^2 f_{\beta}(E_n)`$
|
... | @@ -21,10 +23,10 @@ In the case of spin-imbalanced systems, it is also convenient to introduce a shi |
... | @@ -21,10 +23,10 @@ In the case of spin-imbalanced systems, it is also convenient to introduce a shi |
|
```bash
|
|
```bash
|
|
subsetShiftDmu 1 # if 1 then apply extra shift of quasiparticle energies by (mu_a-mu_b)/2, default=0
|
|
subsetShiftDmu 1 # if 1 then apply extra shift of quasiparticle energies by (mu_a-mu_b)/2, default=0
|
|
```
|
|
```
|
|
# Limitations
|
|
## Limitations
|
|
The states to be tracked and contracted into `subset_rho` and `subset_j` are tagged at the beginning of the simulations. It means that we select states based on their energies at `t=0`. However, as the dynamics proceed energies of the states can change as well, so some of them can acquire energy that is out of the given range, and some that were not included initially can acquire energy within the considered energy range. These effects are not taken into account by the presented prescription.
|
|
The states to be tracked and contracted into `subset_rho` and `subset_j` are tagged at the beginning of the simulations. We select states based on their energies at `t=0`. However, as the dynamics proceed, the energies of the states can change as well, so some of them can acquire energy that is out of the given range, and some that were not included initially can acquire energy within the considered energy range. These effects are not taken into account by the presented prescription.
|
|
|
|
|
|
# Example
|
|
## Example
|
|
Below we present a snapshot from a simulation with SLDA functional for the spin-symmetric system. `td-wslda-2d` has been used. The unitary Fermi gas is confined in a tube, and the vortex dipole is imprinted in the initial state. Following options for subset tracking were used
|
|
Below we present a snapshot from a simulation with SLDA functional for the spin-symmetric system. `td-wslda-2d` has been used. The unitary Fermi gas is confined in a tube, and the vortex dipole is imprinted in the initial state. Following options for subset tracking were used
|
|
|
|
|
|
```bash
|
|
```bash
|
... | @@ -36,5 +38,155 @@ subsetMinEn -0.35 # in eF units, deafault=0.0 |
... | @@ -36,5 +38,155 @@ subsetMinEn -0.35 # in eF units, deafault=0.0 |
|
subsetMaxEn 0.35 # in eF units, deafault=0.0
|
|
subsetMaxEn 0.35 # in eF units, deafault=0.0
|
|
subsetShiftDmu 1 # if 1 then apply extra shift of quasiparticle energies by (mu_a-mu_b)/2, default=0
|
|
subsetShiftDmu 1 # if 1 then apply extra shift of quasiparticle energies by (mu_a-mu_b)/2, default=0
|
|
```
|
|
```
|
|
For the unitary Fermi gas $`\Delta/\varepsilon_{F}=0.5`$, thus as the subset we select only in-gap states, which in this case corresponds to Andreev vortex states. They are localized in the vortex core. It is visualized below: the left half shows $`\Delta(r)/\varepsilon_{F}`$, while the right half shows `subset_rho_a`.
|
|
For the unitary Fermi gas $`\Delta/\varepsilon_{F}=0.5`$, thus, as the subset, we select only in-gap states, which in this case corresponds to Andreev vortex states. They are localized in the vortex core. It is visualized below: the left half shows $`\Delta(r)/\varepsilon_{F}`$, while the right half shows `subset_rho_a`.
|
|
![subset](uploads/448524d11f75bbd5e63179d7ba7722b9/subset.png) |
|
![subset](uploads/448524d11f75bbd5e63179d7ba7722b9/subset.png)
|
|
\ No newline at end of file |
|
|
|
|
|
# Writing to files selected states
|
|
|
|
**VERSION>=2024.01.31**
|
|
|
|
# Tracking the state using write_wave_functions(...)
|
|
|
|
The use can track the selected state via `write_wave_functions(...)` function located in `logger.h`. The example below shows an example code that writes periodically to files states with quasiparticle energies smaller than the given threshold value. The example is for 2D code.
|
|
|
|
```c
|
|
|
|
static int wffileid; // line id
|
|
|
|
static int wfcall; // call id of the function
|
|
|
|
int *idx_wf_for_storage;
|
|
|
|
static int cnt_wf_for_storage;
|
|
|
|
int write_wave_functions(int it, int nxyz, int nwfip, int nwf, double beta, MPI_Comm comm,
|
|
|
|
double complex *h_wf, double *h_qpe, double *h_kky, double *h_kkz, int *h_cnt, // Host pointers
|
|
|
|
double complex *d_wf, // Device pointers
|
|
|
|
double *params, size_t extra_data_size, void *extra_data
|
|
|
|
)
|
|
|
|
{
|
|
|
|
// settings mapping
|
|
|
|
int sweep = params[11];
|
|
|
|
double delta = params[12];
|
|
|
|
|
|
|
|
// do periodically
|
|
|
|
wfcall++;
|
|
|
|
if((wfcall-1) % sweep != 0) return 0; // break
|
|
|
|
|
|
|
|
// example code demonstrating writing wave functions to data format (readable by VisIt).
|
|
|
|
int ip, np;
|
|
|
|
MPI_Comm_size(comm, &np); // np = total number of processes
|
|
|
|
MPI_Comm_rank(comm, &ip); // id of process st 0 <= ip < np
|
|
|
|
|
|
|
|
// printf("S--> %d %d %d %d\n", ip, np, nwfip, nwf);
|
|
|
|
|
|
|
|
// Copy wave functions from device to host
|
|
|
|
memcopy_gpu2host(d_wf, h_wf, (size_t)2*nxyz*nwfip*sizeof(double complex));
|
|
|
|
// set pointers to u and v components
|
|
|
|
double complex *wf_u=h_wf+(size_t)0*nxyz*nwfip; // pointer to nwfip wave functions
|
|
|
|
double complex *wf_v=h_wf+(size_t)1*nxyz*nwfip; // pointer to nwfip wave functions
|
|
|
|
|
|
|
|
int i, ixy, cnt ;
|
|
|
|
|
|
|
|
// identify only states that have e_n<Delta, where Delta is stored in delta
|
|
|
|
// and save their indices to the global array
|
|
|
|
// do it only for the firts call of the function
|
|
|
|
if(wffileid==0)
|
|
|
|
{
|
|
|
|
cnt=0;
|
|
|
|
for(i=0; i<nwfip; i++) if(fabs(h_qpe[i])<delta) {cnt++;}
|
|
|
|
cnt_wf_for_storage = cnt;
|
|
|
|
|
|
|
|
if(cnt_wf_for_storage>0) idx_wf_for_storage = (int *)malloc(cnt_wf_for_storage*sizeof(int));
|
|
|
|
else idx_wf_for_storage=NULL;
|
|
|
|
|
|
|
|
cnt=0;
|
|
|
|
for(i=0; i<nwfip; i++) if(fabs(h_qpe[i])<delta) {idx_wf_for_storage[cnt]=i; cnt++;}
|
|
|
|
}
|
|
|
|
|
|
|
|
double *my_qpe=NULL, *my_kkz=NULL;
|
|
|
|
if(cnt_wf_for_storage>0)
|
|
|
|
{
|
|
|
|
my_qpe = (double *)malloc(sizeof(double)*cnt_wf_for_storage);
|
|
|
|
my_kkz = (double *)malloc(sizeof(double)*cnt_wf_for_storage);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; i<cnt_wf_for_storage; i++) my_qpe[i]=h_qpe[idx_wf_for_storage[i]]; // make local copy
|
|
|
|
for(i=0; i<cnt_wf_for_storage; i++) my_kkz[i]=h_kkz[idx_wf_for_storage[i]]; // make local copy
|
|
|
|
for(i=0; i<cnt_wf_for_storage; i++) for(ixy=0; ixy<NXY; ixy++) wf_u[i*nxyz+ixy] = wf_u[idx_wf_for_storage[i]*nxyz+ixy]; // reorganize
|
|
|
|
for(i=0; i<cnt_wf_for_storage; i++) for(ixy=0; ixy<NXY; ixy++) wf_v[i*nxyz+ixy] = wf_v[idx_wf_for_storage[i]*nxyz+ixy]; // reorganize
|
|
|
|
nwfip=cnt_wf_for_storage;
|
|
|
|
MPI_Allreduce(&nwfip, &nwf, 1, MPI_INT, MPI_SUM, comm);
|
|
|
|
if(ip==0) printf("# [write_wave_functions] IDENTIFIED %d STATES WITH |E_n|<%f\n", nwf, delta);
|
|
|
|
|
|
|
|
// get info about the number of wave functions kept by each MPI process
|
|
|
|
int * wf_tbl = (int *)malloc(np*sizeof(int));
|
|
|
|
MPI_Gather( &nwfip , 1 , MPI_INT , wf_tbl , 1 , MPI_INT , 0 , MPI_COMM_WORLD ) ;
|
|
|
|
MPI_Bcast( wf_tbl , np , MPI_INT , 0 , MPI_COMM_WORLD ) ;
|
|
|
|
|
|
|
|
// use MPI I/O to write a file
|
|
|
|
char file_name[128];
|
|
|
|
MPI_File fh;
|
|
|
|
MPI_Offset my_offset=0;
|
|
|
|
MPI_Status status;
|
|
|
|
|
|
|
|
for(i=0; i<ip; i++) my_offset+=sizeof(double complex)*nxyz*wf_tbl[i];
|
|
|
|
|
|
|
|
// u component
|
|
|
|
sprintf(file_name, "%s_%06d_wf_u.wdat", md.outprefix, wffileid);
|
|
|
|
if(ip==0) printf("# [write_wave_functions] WRITING U COMPONENTS TO FILE `%s`\n", file_name);
|
|
|
|
MPI_File_open(comm, file_name, MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
|
|
|
|
MPI_File_seek(fh, my_offset, MPI_SEEK_SET);
|
|
|
|
MPI_File_write_all(fh, wf_u , nxyz*nwfip, MPI_DOUBLE_COMPLEX, &status);
|
|
|
|
MPI_Get_count(&status, MPI_DOUBLE_COMPLEX, &cnt);
|
|
|
|
if(cnt!=nxyz*nwfip) { printf("# PROBLEM WITH WRITING OF U COMPONENTS BY PROCESS %s!\n", ip); return 1; }
|
|
|
|
MPI_File_close(&fh);
|
|
|
|
|
|
|
|
// v component
|
|
|
|
sprintf(file_name, "%s_%06d_wf_v.wdat", md.outprefix, wffileid);
|
|
|
|
if(ip==0) printf("# [write_wave_functions] WRITING V COMPONENTS TO FILE `%s`\n", file_name);
|
|
|
|
MPI_File_open(comm, file_name, MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
|
|
|
|
MPI_File_seek(fh, my_offset, MPI_SEEK_SET);
|
|
|
|
MPI_File_write_all(fh, wf_v , nxyz*nwfip, MPI_DOUBLE_COMPLEX, &status);
|
|
|
|
MPI_Get_count(&status, MPI_DOUBLE_COMPLEX, &cnt);
|
|
|
|
if(cnt!=nxyz*nwfip) { printf("# PROBLEM WITH WRITING OF V COMPONENTS BY PROCESS %s!\n", ip); return 2; }
|
|
|
|
MPI_File_close(&fh);
|
|
|
|
|
|
|
|
// to be able to see the wave functions in VisIt add wtxt file
|
|
|
|
// see documentation of WDATA for more details
|
|
|
|
wdata_metadata wdmd;
|
|
|
|
wdmd.datadim = CODEDIM;
|
|
|
|
wdmd.nx = NX; wdmd.ny = NY; wdmd.nz = NZ;
|
|
|
|
wdmd.dx = DX; wdmd.dy = DY; wdmd.dz = DZ;
|
|
|
|
sprintf(wdmd.prefix, "%s_%06d", md.outprefix, wffileid);
|
|
|
|
wdmd.t0 = 0.0; wdmd.dt = 1.0; wdmd.cycles=nwf; wdmd.nvar=0;
|
|
|
|
wdata_variable vwf_u = {"wf_u", "complex", "none", "wdat"}; wdata_add_variable(&wdmd, &vwf_u);
|
|
|
|
wdata_variable vwf_v = {"wf_v", "complex", "none", "wdat"}; wdata_add_variable(&wdmd, &vwf_v);
|
|
|
|
sprintf(file_name, "%s_%06d.wtxt", md.outprefix, wffileid);
|
|
|
|
if(ip==0) wdata_write_metadata_to_file(&wdmd,file_name);
|
|
|
|
|
|
|
|
// write En and kz
|
|
|
|
my_offset=0;
|
|
|
|
#define __LINE_LGHT 128
|
|
|
|
char line[__LINE_LGHT];
|
|
|
|
sprintf(line, "%5d %12.8f %12.8f \n", 0, 0.0, 0.0); // line format
|
|
|
|
int _line_lgh = strlen(line); // test its lenght to get info about number of bytes per line
|
|
|
|
for(i=0; i<ip; i++) my_offset+=sizeof(char)*_line_lgh*wf_tbl[i];
|
|
|
|
int startidx=0;
|
|
|
|
for(i=0; i<ip; i++) startidx+=wf_tbl[i];
|
|
|
|
|
|
|
|
sprintf(file_name, "%s_%06d_Ekz.txt", md.outprefix, wffileid);
|
|
|
|
if(ip==0) printf("# [write_wave_functions] WRITING En AND kz TO FILE `%s`\n", file_name);
|
|
|
|
MPI_File_open(comm, file_name, MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
|
|
|
|
for(i=0; i<nwfip; i++)
|
|
|
|
{
|
|
|
|
sprintf(line, "%5d %12.8f %12.8f \n", startidx+i, my_kkz[i], my_qpe[i]); // prepare line
|
|
|
|
MPI_File_write_at(fh, my_offset, line , _line_lgh, MPI_CHAR, &status); // write it
|
|
|
|
MPI_Get_count(&status, MPI_CHAR, &cnt); // get status
|
|
|
|
if(cnt!=_line_lgh) { printf("# PROBLEM WITH WRITING OF En AND kz BY PROCESS %s!\n", ip); return 3; }
|
|
|
|
my_offset+=sizeof(char)*_line_lgh; // move pointer to next line
|
|
|
|
}
|
|
|
|
MPI_File_close(&fh);
|
|
|
|
#undef __LINE_LGHT
|
|
|
|
|
|
|
|
// clear memory
|
|
|
|
free(wf_tbl);
|
|
|
|
|
|
|
|
wffileid++; // store next id
|
|
|
|
free(my_kkz);
|
|
|
|
free(my_qpe);
|
|
|
|
|
|
|
|
return 0; // return OK status
|
|
|
|
}
|
|
|
|
``` |