source: pcp/src/perturbed.c@ b0aa9c

Last change on this file since b0aa9c was b0aa9c, checked in by Frederik Heber <heber@…>, 18 years ago

MinimisePerturbed(): verbosity changed, some comments

  • Property mode set to 100644
File size: 208.8 KB
Line 
1/** \file perturbed.c
2 * Perturbation calculation due to external magnetic field.
3 *
4 * Central function is MinimisePerturbed() wherein the actual minimisation of the two different operators with each
5 * three components takes place subsequently. Helpful routines are CalculatePerturbationOperator_P() - which applies a
6 * specified component of p on the current wave function - and CalculatePerturbationOperator_RxP() - which does the
7 * same for the RxP operator.
8 * The actual minimisation loop FindPerturbedMinimum() depends on the same routines also used for the occupied orbitals,
9 * however with a different energy functional and derivatives, evaluated in Calculate1stPerturbedDerivative() and
10 * Calculate2ndPerturbedDerivative(). InitPerturbedEnergyCalculation() calculates the total energy functional
11 * perturbed in second order for all wave functions, UpdatePerturbedEnergyCalculation() just updates the one
12 * for the wave function after it has been minimised during the line search. Both use CalculatePerturbedEnergy() which
13 * evaluates the energy functional (and the gradient if specified).
14 * Finally, FillCurrentDensity() evaluates the current density at a given point in space using the perturbed
15 * wave functions. Afterwards by calling CalculateMagneticSusceptibility() or
16 * CalculateChemicalShieldingByReciprocalCurrentDensity() susceptibility respectively shielding tensor are possible uses
17 * of this current density.
18 *
19 * There are also some test routines: TestCurrent() checks whether the integrated current is zero in each component.
20 * test_fft_symmetry() tests the "pulling out imaginary unit" before fourier transformation on a given wave function.
21 * CheckOrbitalOverlap() outputs the overlap matrix for the wave functions of a given minimisation state, this might
22 * be important for the additional \f$\Delta J{ij}\f$ contribution to the current density, which is non-zero for
23 * non-zero mutual overlap, which is evaluated if FillDeltaCurrentDensity() is called.
24 *
25 * Finally, there are also some smaller routines: truedist() gives the correct relative distance between two points
26 * in the unit cell under periodic boundary conditions with minimum image convention. ApplyTotalHamiltonian() returns
27 * the hamiltonian applied to a given wave function. sawtooth() is a sawtooth implementation which is needed in order
28 * to avoid flipping of position eigenvalues for nodes close to or on the cell boundary. CalculateOverlap()
29 * is used in the energy functional derivatives, keeping an overlap table between perturbed wave functions up to date.
30 * fft_Psi() is very similar to CalculateOneDensityR(), it does the extension of the wave function to the upper level
31 * RunStruct#Lev0 while fouriertransforming it to real space. cross() gives correct indices in evaluating a vector cross
32 * product. AllocCurrentDensity() and DisAllocCurrentDensity() mark the current density arrays as currently being in use or not.
33 *
34 Project: ParallelCarParrinello
35 \author Frederik Heber
36 \date 2006
37
38*/
39
40#include <stdlib.h>
41#include <stdio.h>
42#include <math.h>
43#include <string.h>
44#include <time.h>
45#include <gsl/gsl_matrix.h>
46#include <gsl/gsl_eigen.h>
47#include <gsl/gsl_complex.h>
48#include <gsl/gsl_complex_math.h>
49#include <gsl/gsl_sort_vector.h>
50#include <gsl/gsl_linalg.h>
51#include <gsl/gsl_multimin.h>
52
53#include "data.h"
54#include "density.h"
55#include "energy.h"
56#include "excor.h"
57#include "errors.h"
58#include "grad.h"
59#include "gramsch.h"
60#include "mergesort2.h"
61#include "helpers.h"
62#include "init.h"
63#include "myfft.h"
64#include "mymath.h"
65#include "output.h"
66#include "pcp.h"
67#include "perturbed.h"
68#include "run.h"
69#include "wannier.h"
70
71
72/** Minimisation of the PsiTypeTag#Perturbed_RxP0, PsiTypeTag#Perturbed_P0 and other orbitals.
73 * For each of the above PsiTypeTag we go through the following before the minimisation loop:
74 * -# ResetGramSchTagType() resets current type that is to be minimised to NotOrthogonal.
75 * -# UpdateActualPsiNo() steps on to next perturbed of current PsiTypeTag type.
76 * -# GramSch() orthonormalizes perturbed wave functions.
77 * -# TestGramSch() tests if orthonormality was achieved.
78 * -# InitDensityCalculation() gathers densities from all wave functions (and all processes), within SpeedMeasure() DensityTime.
79 * -# InitPerturbedEnergyCalculation() performs initial calculation of the perturbed energy functional.
80 * -# RunStruct#OldActualLocalPsiNo is set to RunStruct#ActualLocalPsiNo, immediately followed by UpdateGramSchOldActualPsiNo()
81 * to bring info on all processes on par.
82 * -# UpdatePerturbedEnergyCalculation() re-calculates Gradient and GradientTypes#H1cGradient for RunStruct#ActualLocalPsiNo
83 * -# EnergyAllReduce() gathers various energy terms and sums up into Energy#TotalEnergy.
84 *
85 * And during the minimisation loop:
86 * -# FindPerturbedMinimum() performs the gradient conjugation, the line search and wave function update.
87 * -# UpdateActualPsiNo() steps on to the next wave function, orthonormalizing by GramSch() if necessary.
88 * -# UpdateEnergyArray() shifts TotalEnergy values to make space for new one.
89 * -# There is no density update as the energy function does not depend on the changing perturbed density but only on the fixed
90 * unperturbed one.
91 * -# UpdatePerturbedEnergyCalculation() re-calculates the perturbed energy of the changed wave function.
92 * -# EnergyAllReduce() gathers energy terms and sums up.
93 * -# CheckCPULIM() checks if external Stop signal has been given.
94 * -# CalculateMinimumStop() checks whether we have dropped below a certain minimum change during minimisation of total energy.
95 * -# finally step counters LatticeLevel#Step and SpeedStruct#Steps are increased.
96 *
97 * After the minimisation loop:
98 * -# SetGramSchExtraPsi() removes extra Psis from orthogonaliy check.
99 * -# ResetGramSchTagType() sets GramSchToDoType to NotUsedtoOrtho.
100 *
101 * And after all minimisation runs are done:
102 * -# UpdateActualPsiNo() steps back to PsiTypeTag#Occupied type.
103 *
104 * At the end we return to Occupied wave functions.
105 * \param *P at hand
106 * \param *Stop flag to determine if epsilon stop conditions have met
107 * \param *SuperStop flag to determinte whether external signal's required end of calculations
108 */
109void MinimisePerturbed (struct Problem *P, int *Stop, int *SuperStop) {
110 struct RunStruct *R = &P->R;
111 struct Lattice *Lat = &P->Lat;
112 struct Psis *Psi = &Lat->Psi;
113 int type;
114
115 for (type=Perturbed_P0;type<=Perturbed_RxP2;type++) { // go through each perturbation group separately //
116 *Stop=0; // reset stop flag
117 if(P->Call.out[LeaderOut]) fprintf(stderr,"(%i)Beginning perturbed minimisation of type %s ...\n", P->Par.me, R->MinimisationName[type]);
118 //OutputOrbitalPositions(P, Occupied);
119 R->PsiStep = R->MaxPsiStep; // reset in-Psi-minimisation-counter, so that we really advance to the next wave function
120 UpdateActualPsiNo(P, type); // step on to next perturbed one
121 if(P->Call.out[MinOut]) fprintf(stderr, "(%i) Re-initializing perturbed psi array for type %s ", P->Par.me, R->MinimisationName[type]);
122 if (P->Call.ReadSrcFiles && ReadSrcPsiDensity(P,type,1, R->LevSNo)) {
123 SpeedMeasure(P, InitSimTime, StartTimeDo);
124 if(P->Call.out[MinOut]) fprintf(stderr,"from source file of recent calculation\n");
125 ReadSrcPsiDensity(P,type, 0, R->LevSNo);
126 ResetGramSchTagType(P, Psi, type, IsOrthogonal); // loaded values are orthonormal
127 SpeedMeasure(P, DensityTime, StartTimeDo);
128 //InitDensityCalculation(P);
129 SpeedMeasure(P, DensityTime, StopTimeDo);
130 R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // needed otherwise called routines in function below crash
131 UpdateGramSchOldActualPsiNo(P,Psi);
132 InitPerturbedEnergyCalculation(P, 1); // go through all orbitals calculate each H^{(0)}-eigenvalue, recalc HGDensity, cause InitDensityCalc zero'd it
133 UpdatePerturbedEnergyCalculation(P); // H1cGradient and Gradient must be current ones
134 EnergyAllReduce(P); // gather energies for minimum search
135 SpeedMeasure(P, InitSimTime, StopTimeDo);
136 }
137 if (P->Call.ReadSrcFiles != 1) {
138 SpeedMeasure(P, InitSimTime, StartTimeDo);
139 ResetGramSchTagType(P, Psi, type, NotOrthogonal); // perturbed now shall be orthonormalized
140 if (P->Call.ReadSrcFiles != 2) {
141 if (R->LevSNo == Lat->MaxLevel-1) { // is it the starting level? (see InitRunLevel())
142 if(P->Call.out[MinOut]) fprintf(stderr, "randomly.\n");
143 InitPsisValue(P, Psi->TypeStartIndex[type], Psi->TypeStartIndex[type+1]); // initialize perturbed array for this run
144 } else {
145 if(P->Call.out[MinOut]) fprintf(stderr, "from source file of last level.\n");
146 ReadSrcPerturbedPsis(P, type);
147 }
148 }
149 SpeedMeasure(P, InitGramSchTime, StartTimeDo);
150 GramSch(P, R->LevS, Psi, Orthogonalize);
151 SpeedMeasure(P, InitGramSchTime, StopTimeDo);
152 SpeedMeasure(P, InitDensityTime, StartTimeDo);
153 //InitDensityCalculation(P);
154 SpeedMeasure(P, InitDensityTime, StopTimeDo);
155 InitPerturbedEnergyCalculation(P, 1); // go through all orbitals calculate each H^{(0)}-eigenvalue, recalc HGDensity, cause InitDensityCalc zero'd it
156 R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // needed otherwise called routines in function below crash
157 UpdateGramSchOldActualPsiNo(P,Psi);
158 UpdatePerturbedEnergyCalculation(P); // H1cGradient and Gradient must be current ones
159 EnergyAllReduce(P); // gather energies for minimum search
160 SpeedMeasure(P, InitSimTime, StopTimeDo);
161 R->LevS->Step++;
162 EnergyOutput(P,0);
163 while (*Stop != 1) {
164 //debug(P,"FindPerturbedMinimum");
165 FindPerturbedMinimum(P); // find minimum
166 //debug(P,"UpdateActualPsiNo");
167 UpdateActualPsiNo(P, type); // step on to next perturbed Psi
168 //debug(P,"UpdateEnergyArray");
169 UpdateEnergyArray(P); // shift energy values in their array by one
170 //debug(P,"UpdatePerturbedEnergyCalculation");
171 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)
172 EnergyAllReduce(P); // gather from all processes and sum up to total energy
173 //ControlNativeDensity(P); // check total density (summed up PertMixed must be zero!)
174 //printf ("(%i,%i,%i)S(%i,%i,%i):\t %5d %10.5f\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, (int)iter, s_multi->f);
175 if (*SuperStop != 1)
176 *SuperStop = CheckCPULIM(P);
177 *Stop = CalculateMinimumStop(P, *SuperStop);
178 P->Speed.Steps++; // step on
179 R->LevS->Step++;
180 }
181 // now release normalization condition and minimize wrt to norm
182 if(P->Call.out[MinOut]) fprintf(stderr,"(%i) Writing %s srcpsi to disk\n", P->Par.me, R->MinimisationName[type]);
183 OutputSrcPsiDensity(P, type);
184// if (!TestReadnWriteSrcDensity(P,type))
185// Error(SomeError,"TestReadnWriteSrcDensity failed!");
186 }
187
188 TestGramSch(P,R->LevS,Psi, type); // functions are orthonormal?
189 // calculate current density summands
190 //if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Filling current density grid ...\n",P->Par.me);
191 SpeedMeasure(P, CurrDensTime, StartTimeDo);
192 if (*SuperStop != 1) {
193 if ((R->DoFullCurrent == 1) || ((R->DoFullCurrent == 2) && (CheckOrbitalOverlap(P) == 1))) { //test to check whether orbitals have mutual overlap and thus \\DeltaJ_{xc} must not be dropped
194 R->DoFullCurrent = 1; // set to 1 if it was 2 but Check...() yielded necessity
195 //debug(P,"Filling with Delta j ...");
196 //FillDeltaCurrentDensity(P);
197 }// else
198 //debug(P,"There is no overlap between orbitals.");
199 //debug(P,"Filling with j ...");
200 FillCurrentDensity(P);
201 }
202 SpeedMeasure(P, CurrDensTime, StopTimeDo);
203
204 SetGramSchExtraPsi(P,Psi,NotUsedToOrtho); // remove extra Psis from orthogonality check
205 ResetGramSchTagType(P, Psi, type, NotUsedToOrtho); // remove this group from the check for the next minimisation group as well!
206 }
207 UpdateActualPsiNo(P, Occupied); // step on back to an occupied one
208}
209
210/** Tests overlap matrix between each pair of orbitals for non-diagonal form.
211 * We simply check whether the overlap matrix Psis#lambda has off-diagonal entries greater MYEPSILON or not.
212 * \param *P Problem at hand
213 * \note The routine is meant as atest criteria if \f$\Delta J_[ij]\f$ contribution is necessary, as it is only non-zero if
214 * there is mutual overlap between the two orbitals.
215 */
216int CheckOrbitalOverlap(struct Problem *P)
217{
218 struct Lattice *Lat = &P->Lat;
219 struct Psis *Psi = &Lat->Psi;
220 int i,j;
221 int counter = 0;
222
223 // output matrix
224 if (P->Par.me == 0) fprintf(stderr, "(%i) S_ij =\n", P->Par.me);
225 for (i=0;i<Psi->NoOfPsis;i++) {
226 for (j=0;j<Psi->NoOfPsis;j++) {
227 if (fabs(Psi->lambda[i][j]) > MYEPSILON) counter++;
228 if (P->Par.me == 0) fprintf(stderr, "%e\t", Psi->lambda[i][j]); //Overlap[i][j]
229 }
230 if (P->Par.me == 0) fprintf(stderr, "\n");
231 }
232
233 fprintf(stderr, "(%i) CheckOverlap: %i overlaps found.\t", P->Par.me, counter);
234 if (counter > 0) return (1);
235 else return(0);
236}
237
238/** Initialization of perturbed energy.
239 * For each local wave function of the current minimisation type RunStruct#CurrentMin it is called:
240 * - CalculateNonLocalEnergyNoRT(): for the coefficient-dependent form factors
241 * - CalculatePerturbedEnergy(): for the perturbed energy, yet without gradient calculation
242 * - CalculateOverlap(): for the overlap between the perturbed wave functions of the current RunStruct#CurrentMin state.
243 *
244 * Afterwards for the two types AllPsiEnergyTypes#Perturbed1_0Energy and AllPsiEnergyTypes#Perturbed0_1Energy the
245 * energy contribution from each wave function is added up in Energy#AllLocalPsiEnergy.
246 * \param *P Problem at hand
247 * \param first state whether it is the first (1) or successive call (0), which avoids some initial calculations.
248 * \sa UpdatePerturbedEnergy()
249 * \note Afterwards EnergyAllReduce() must be called.
250 */
251void InitPerturbedEnergyCalculation(struct Problem *P, const int first)
252{
253 struct Lattice *Lat = &(P->Lat);
254 int p,i;
255 const enum PsiTypeTag state = P->R.CurrentMin;
256 for (p=Lat->Psi.TypeStartIndex[state]; p < Lat->Psi.TypeStartIndex[state+1]; p++) {
257 //if (p < 0 || p >= Lat->Psi.LocalNo) Error(SomeError,"InitPerturbedEnergyCalculation: p out of range");
258 CalculateNonLocalEnergyNoRT(P, p); // recalculating non-local form factors which are coefficient dependent!
259 CalculatePsiEnergy(P,p,1);
260 CalculatePerturbedEnergy(P, p, 0, first);
261 CalculateOverlap(P, p, state);
262 }
263 for (i=0; i<= Perturbed0_1Energy; i++) {
264 Lat->E->AllLocalPsiEnergy[i] = 0.0;
265 for (p=0; p < Lat->Psi.LocalNo; p++)
266 if (P->Lat.Psi.LocalPsiStatus[p].PsiType == state)
267 Lat->E->AllLocalPsiEnergy[i] += Lat->E->PsiEnergy[i][p];
268 }
269}
270
271
272/** Updating of perturbed energy.
273 * For current and former (if not the same) local wave function RunStruct#ActualLocal, RunStruct#OldActualLocalPsiNo it is called:
274 * - CalculateNonLocalEnergyNoRT(): for the form factors
275 * - CalculatePerturbedEnergy(): for the perturbed energy, gradient only for RunStruct#ActualLocal
276 * - CalculatePerturbedOverlap(): for the overlap between the perturbed wave functions
277 *
278 * Afterwards for the two types AllPsiEnergyTypes#Perturbed1_0Energy and AllPsiEnergyTypes#Perturbed0_1Energy the
279 * energy contribution from each wave function is added up in Energy#AllLocalPsiEnergy.
280 * \param *P Problem at hand
281 * \sa CalculatePerturbedEnergy() called from here.
282 * \note Afterwards EnergyAllReduce() must be called.
283 */
284void UpdatePerturbedEnergyCalculation(struct Problem *P)
285{
286 struct Lattice *Lat = &(P->Lat);
287 struct Psis *Psi = &Lat->Psi;
288 struct RunStruct *R = &P->R;
289 const enum PsiTypeTag state = R->CurrentMin;
290 int p = R->ActualLocalPsiNo;
291 const int p_old = R->OldActualLocalPsiNo;
292 int i;
293
294 if (p != p_old) {
295 //if (p_old < 0 || p_old >= Lat->Psi.LocalNo) Error(SomeError,"UpdatePerturbedEnergyCalculation: p_old out of range");
296 CalculateNonLocalEnergyNoRT(P, p_old);
297 CalculatePsiEnergy(P,p_old,0);
298 CalculatePerturbedEnergy(P, p_old, 0, 0);
299 CalculateOverlap(P, p_old, state);
300 }
301 //if (p < 0 || p >= Lat->Psi.LocalNo) Error(SomeError,"InitPerturbedEnergyCalculation: p out of range");
302 // recalculating non-local form factors which are coefficient dependent!
303 CalculateNonLocalEnergyNoRT(P,p);
304 CalculatePsiEnergy(P,p,0);
305 CalculatePerturbedEnergy(P, p, 1, 0);
306 CalculateOverlap(P, p, state);
307
308 for (i=0; i<= Perturbed0_1Energy; i++) {
309 Lat->E->AllLocalPsiEnergy[i] = 0.0;
310 for (p=0; p < Psi->LocalNo; p++)
311 if (Psi->LocalPsiStatus[p].PsiType == state)
312 Lat->E->AllLocalPsiEnergy[i] += Lat->E->PsiEnergy[i][p];
313 }
314}
315
316/** Calculates gradient and evaluates second order perturbed energy functional for specific wave function.
317 * The in second order perturbed energy functional reads as follows.
318 * \f[
319 * E^{(2)} = \sum_{kl} \langle \varphi_k^{(1)} | H^{(0)} \delta_{kl} - \lambda_{kl} | \varphi_l^{(1)} \rangle
320 * + \underbrace{\langle \varphi_l^{(0)} | H^{(1)} | \varphi_l^{(1)} \rangle + \langle \varphi_l^{(1)} | H^{(1)} | \varphi_l^{(0)} \rangle}_{2 {\cal R} \langle \varphi_l^{(1)} | H^{(1)} | \varphi_l^{(0)} \rangle}
321 * \f]
322 * And the gradient
323 * \f[
324 * \widetilde{\varphi}_k^{(1)} = - \sum_l ({\cal H}^{(0)} \delta_{kl} - \lambda_{kl} | \varphi_l^{(1)} \rangle + {\cal H}^{(1)} | \varphi_k^{(0)} \rangle
325 * \f]
326 * First, the HGDensity is recalculated if \a first says so - see ApplyTotalHamiltonian().
327 *
328 * Next, we need the perturbation hamiltonian acting on both the respective occupied and current wave function,
329 * see perturbed.c for respective function calls.
330 *
331 * Finally, the scalar product between the wave function and Hc_Gradient yields the eigenvalue of the hamiltonian,
332 * which is summed up over all reciprocal grid vectors and stored in OnePsiElementAddData#Lambda. The Gradient is
333 * the inverse of Hc_Gradient and with the following summation over all perturbed wave functions (MPI exchange of
334 * non-local coefficients) the gradient is computed. Here we need Psis#lambda, which is computed in CalculateHamiltonian().
335 *
336 * Also \f${\cal H}^{(1)} | \varphi_l^{(0)} \rangle\f$ is stored in GradientTypes#H1cGradient.
337 * \param *P Problem at hand, contains RunStruct, Lattice, LatticeLevel RunStruct#LevS
338 * \param l offset of perturbed wave function within Psi#LocalPsiStatus (\f$\varphi_l^{(1)}\f$)
339 * \param DoGradient (1 = yes, 0 = no) whether gradient shall be calculated or not
340 * \param first recaculate HGDensity (1) or not (0)
341 * \note DensityTypes#ActualPsiDensity must be recent for gradient calculation!
342 * \sa CalculateGradientNoRT() - same procedure for evaluation of \f${\cal H}^{(0)}| \varphi_l^{(1)} \rangle\f$
343 * \note without the simplification of \f$2 {\cal R} \langle \varphi_l^{(1)} | H^{(1)} | \varphi_l^{(0)} \rangle\f$ the
344 * calculation would be impossible due to non-local nature of perturbed wave functions. The position operator would
345 * be impossible to apply in a sensible manner.
346 */
347void CalculatePerturbedEnergy(struct Problem *P, const int l, const int DoGradient, const int first)
348{
349 struct Lattice *Lat = &P->Lat;
350 struct Psis *Psi = &Lat->Psi;
351 struct Energy *E = Lat->E;
352 struct PseudoPot *PP = &P->PP;
353 struct RunStruct *R = &P->R;
354 struct LatticeLevel *LevS = R->LevS;
355 const int state = R->CurrentMin;
356 const int l_normal = Psi->TypeStartIndex[Occupied] + (l - Psi->TypeStartIndex[state]); // offset l to \varphi_l^{(0)}
357 const int ActNum = l - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[1] * Psi->LocalPsiStatus[l].my_color_comm_ST_Psi;
358 int g, i, m, j;
359 double lambda, Lambda;
360 double RElambda10, RELambda10;
361 const fftw_complex *source = LevS->LPsi->LocalPsi[l];
362 fftw_complex *grad = P->Grad.GradientArray[ActualGradient];
363 fftw_complex *Hc_grad = P->Grad.GradientArray[HcGradient];
364 fftw_complex *H1c_grad = P->Grad.GradientArray[H1cGradient];
365 fftw_complex *TempPsi_0 = H1c_grad;
366 fftw_complex *varphi_1, *varphi_0;
367 struct OnePsiElement *OnePsiB, *LOnePsiB;
368 fftw_complex *LPsiDatB=NULL;
369 const int ElementSize = (sizeof(fftw_complex) / sizeof(double));
370 int RecvSource;
371 MPI_Status status;
372
373 // ============ Calculate H^(0) psi^(1) =============================
374 //if (Hc_grad != P->Grad.GradientArray[HcGradient]) Error(SomeError,"CalculatePerturbedEnergy: Hc_grad corrupted");
375 SetArrayToDouble0((double *)Hc_grad,2*R->InitLevS->MaxG);
376 ApplyTotalHamiltonian(P,source,Hc_grad, PP->fnl[l], 1, first);
377
378 // ============ ENERGY FUNCTIONAL Evaluation PART 1 ================
379 //if (l_normal < 0 || l_normal >= Psi->LocalNo) Error(SomeError,"CalculatePerturbedEnergy: l_normal out of range");
380 varphi_0 = LevS->LPsi->LocalPsi[l_normal];
381 //if (l < 0 || l >= Psi->LocalNo) Error(SomeError,"CalculatePerturbedEnergy: l out of range");
382 varphi_1 = LevS->LPsi->LocalPsi[l];
383 //if (TempPsi_0 != P->Grad.GradientArray[H1cGradient]) Error(SomeError,"CalculatePerturbedEnergy: TempPsi_0 corrupted");
384 SetArrayToDouble0((double *)TempPsi_0,2*R->InitLevS->MaxG);
385 switch (state) {
386 case Perturbed_P0:
387 CalculatePerturbationOperator_P(P,varphi_0,TempPsi_0,0); // \nabla_0 | \varphi_l^{(0)} \rangle
388 break;
389 case Perturbed_P1:
390 CalculatePerturbationOperator_P(P,varphi_0,TempPsi_0,1); // \nabla_1 | \varphi_l^{(0)} \rangle
391 break;
392 case Perturbed_P2:
393 CalculatePerturbationOperator_P(P,varphi_0,TempPsi_0,2); // \nabla_1 | \varphi_l^{(0)} \rangle
394 break;
395 case Perturbed_RxP0:
396 CalculatePerturbationOperator_RxP(P,varphi_0,TempPsi_0,l_normal,0); // r \times \nabla | \varphi_l^{(0)} \rangle
397 break;
398 case Perturbed_RxP1:
399 CalculatePerturbationOperator_RxP(P,varphi_0,TempPsi_0,l_normal,1); // r \times \nabla | \varphi_l^{(0)} \rangle
400 break;
401 case Perturbed_RxP2:
402 CalculatePerturbationOperator_RxP(P,varphi_0,TempPsi_0,l_normal,2); // r \times \nabla | \varphi_l^{(0)} \rangle
403 break;
404 default:
405 fprintf(stderr,"(%i) CalculatePerturbedEnergy called whilst not within perturbation run: CurrentMin = %i !\n",P->Par.me, R->CurrentMin);
406 break;
407 }
408
409 // ============ GRADIENT and EIGENVALUE Evaluation Part 1==============
410 lambda = 0.0;
411 if ((DoGradient) && (grad != NULL)) {
412 g = 0;
413 if (LevS->GArray[0].GSq == 0.0) {
414 lambda += Hc_grad[0].re*source[0].re;
415 //if (grad != P->Grad.GradientArray[ActualGradient]) Error(SomeError,"CalculatePerturbedEnergy: grad corrupted");
416 grad[0].re = -(Hc_grad[0].re + TempPsi_0[0].re);
417 grad[0].im = -(Hc_grad[0].im + TempPsi_0[0].im);
418 g++;
419 }
420 for (;g<LevS->MaxG;g++) {
421 lambda += 2.*(Hc_grad[g].re*source[g].re + Hc_grad[g].im*source[g].im);
422 //if (grad != P->Grad.GradientArray[ActualGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"CalculatePerturbedEnergy: grad corrupted");
423 grad[g].re = -(Hc_grad[g].re + TempPsi_0[g].re);
424 grad[g].im = -(Hc_grad[g].im + TempPsi_0[g].im);
425 }
426
427 m = -1;
428 for (j=0; j < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; j++) { // go through all wave functions
429 OnePsiB = &Psi->AllPsiStatus[j]; // grab OnePsiB
430 if (OnePsiB->PsiType == state) { // drop all but the ones of current min state
431 m++; // increase m if it is type-specific wave function
432 if (OnePsiB->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
433 LOnePsiB = &Psi->LocalPsiStatus[OnePsiB->MyLocalNo];
434 else
435 LOnePsiB = NULL;
436 if (LOnePsiB == NULL) { // if it's not local ... receive it from respective process into TempPsi
437 RecvSource = OnePsiB->my_color_comm_ST_Psi;
438 MPI_Recv( LevS->LPsi->TempPsi, LevS->MaxG*ElementSize, MPI_DOUBLE, RecvSource, PerturbedTag, P->Par.comm_ST_PsiT, &status );
439 LPsiDatB=LevS->LPsi->TempPsi;
440 } else { // .. otherwise send it to all other processes (Max_me... - 1)
441 for (i=0;i<P->Par.Max_me_comm_ST_PsiT;i++)
442 if (i != OnePsiB->my_color_comm_ST_Psi)
443 MPI_Send( LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo], LevS->MaxG*ElementSize, MPI_DOUBLE, i, PerturbedTag, P->Par.comm_ST_PsiT);
444 LPsiDatB=LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo];
445 } // LPsiDatB is now set to the coefficients of OnePsi either stored or MPI_Received
446
447 g = 0;
448 if (LevS->GArray[0].GSq == 0.0) { // perform the summation
449 //if (grad != P->Grad.GradientArray[ActualGradient]) Error(SomeError,"CalculatePerturbedEnergy: grad corrupted");
450 grad[0].re += Lat->Psi.lambda[ActNum][m]*LPsiDatB[0].re;
451 grad[0].im += Lat->Psi.lambda[ActNum][m]*LPsiDatB[0].im;
452 g++;
453 }
454 for (;g<LevS->MaxG;g++) {
455 //if (grad != P->Grad.GradientArray[ActualGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"CalculatePerturbedEnergy: grad corrupted");
456 grad[g].re += Lat->Psi.lambda[ActNum][m]*LPsiDatB[g].re;
457 grad[g].im += Lat->Psi.lambda[ActNum][m]*LPsiDatB[g].im;
458 }
459 }
460 }
461 } else {
462 lambda = GradSP(P,LevS,Hc_grad,source);
463 }
464 MPI_Allreduce ( &lambda, &Lambda, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
465 //fprintf(stderr,"(%i) Lambda[%i] = %lg\n",P->Par.me, l, Lambda);
466 //if (l < 0 || l >= Psi->LocalNo) Error(SomeError,"CalculatePerturbedEnergy: l out of range");
467 Lat->Psi.AddData[l].Lambda = Lambda;
468
469 // ============ ENERGY FUNCTIONAL Evaluation PART 2 ================
470 // varphi_1 jas negative symmetry, returning TempPsi_0 from CalculatePerturbedOperator also, thus real part of scalar product
471 // "-" due to purely imaginary wave function is on left hand side, thus becomes complex conjugated: i -> -i
472 // (-i goes into pert. op., "-" remains when on right hand side)
473 RElambda10 = GradSP(P,LevS,varphi_1,TempPsi_0) * sqrt(Psi->LocalPsiStatus[l].PsiFactor * Psi->LocalPsiStatus[l_normal].PsiFactor);
474 //RElambda01 = -GradSP(P,LevS,varphi_0,TempPsi_1) * sqrt(Psi->LocalPsiStatus[l].PsiFactor * Psi->LocalPsiStatus[l_normal].PsiFactor);
475
476 MPI_Allreduce ( &RElambda10, &RELambda10, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
477 //MPI_Allreduce ( &RElambda01, &RELambda01, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
478
479 //if (l < 0 || l >= Psi->LocalNo) Error(SomeError,"CalculatePerturbedEnergy: l out of range");
480 E->PsiEnergy[Perturbed1_0Energy][l] = RELambda10;
481 E->PsiEnergy[Perturbed0_1Energy][l] = RELambda10;
482// if (P->Par.me == 0) {
483// fprintf(stderr,"RE.Lambda10[%i-%i] = %lg\t RE.Lambda01[%i-%i] = %lg\n", l, l_normal, RELambda10, l_normal, l, RELambda01);
484// }
485 // GradImSP() is only applicable to a product of wave functions with uneven symmetry!
486 // Otherwise, due to the nature of symmetry, a sum over only half of the coefficients will in most cases not result in zero!
487}
488
489/** Applies \f$H^{(0)}\f$ to a given \a source.
490 * The DensityTypes#HGDensity is computed, the exchange potential added and the
491 * whole multiplied - coefficient by coefficient - with the current wave function, taken from its density coefficients,
492 * on the upper LatticeLevel (RunStruct#Lev0), which (DensityTypes#ActualPsiDensity) is updated beforehand.
493 * After an inverse fft (now G-dependent) the non-local potential is added and
494 * within the reciprocal basis set, the kinetic energy can be evaluated easily.
495 * \param *P Problem at hand
496 * \param *source pointer to source coefficient array, \f$| \varphi(G) \rangle\f$
497 * \param *dest pointer to dest coefficient array,\f$H^{(0)} | \varphi(G) \rangle\f$
498 * \param **fnl pointer to non-local form factor array
499 * \param PsiFactor occupation number of orbital
500 * \param first 1 - Re-calculate DensityTypes#HGDensity, 0 - don't
501 * \sa CalculateConDirHConDir() - same procedure
502 */
503void ApplyTotalHamiltonian(struct Problem *P, const fftw_complex *source, fftw_complex *dest, fftw_complex ***fnl, const double PsiFactor, const int first) {
504 struct Lattice *Lat = &P->Lat;
505 struct RunStruct *R = &P->R;
506 struct LatticeLevel *LevS = R->LevS;
507 struct LatticeLevel *Lev0 = R->Lev0;
508 struct Density *Dens0 = Lev0->Dens;
509 struct fft_plan_3d *plan = Lat->plan;
510 struct PseudoPot *PP = &P->PP;
511 struct Ions *I = &P->Ion;
512 fftw_complex *work = Dens0->DensityCArray[TempDensity];
513 fftw_real *HGcR = Dens0->DensityArray[HGcDensity];
514 fftw_complex *HGcRC = (fftw_complex*)HGcR;
515 fftw_complex *HGC = Dens0->DensityCArray[HGDensity];
516 fftw_real *HGCR = (fftw_real *)HGC;
517 fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
518 fftw_real *PsiCR = (fftw_real *)PsiC;
519 //const fftw_complex *dest_bak = dest;
520 int nx,ny,nz,iS,i0;
521 const int Nx = LevS->Plan0.plan->local_nx;
522 const int Ny = LevS->Plan0.plan->N[1];
523 const int Nz = LevS->Plan0.plan->N[2];
524 const int NUpx = LevS->NUp[0];
525 const int NUpy = LevS->NUp[1];
526 const int NUpz = LevS->NUp[2];
527 const double HGcRCFactor = 1./LevS->MaxN;
528 int g, Index, i, it;
529 fftw_complex vp,rp,rhog,TotalPsiDensity;
530 double Fac;
531
532 if (first) {
533 // recalculate HGDensity
534 //if (HGC != Dens0->DensityCArray[HGDensity]) Error(SomeError,"ApplyTotalHamiltonian: HGC corrupted");
535 SetArrayToDouble0((double *)HGC,2*Dens0->TotalSize);
536 g=0;
537 if (Lev0->GArray[0].GSq == 0.0) {
538 Index = Lev0->GArray[0].Index;
539 c_re(vp) = 0.0;
540 c_im(vp) = 0.0;
541 for (it = 0; it < I->Max_Types; it++) {
542 c_re(vp) += (c_re(I->I[it].SFactor[0])*PP->phi_ps_loc[it][0]);
543 c_im(vp) += (c_im(I->I[it].SFactor[0])*PP->phi_ps_loc[it][0]);
544 }
545 //if (HGC != Dens0->DensityCArray[HGDensity] || Index<0 || Index>=Dens0->LocalSizeC) Error(SomeError,"ApplyTotalHamiltonian: HGC corrupted");
546 c_re(HGC[Index]) = c_re(vp);
547 c_re(TotalPsiDensity) = c_re(Dens0->DensityCArray[TotalDensity][Index]);
548 c_im(TotalPsiDensity) = c_im(Dens0->DensityCArray[TotalDensity][Index]);
549
550 g++;
551 }
552 for (; g < Lev0->MaxG; g++) {
553 Index = Lev0->GArray[g].Index;
554 Fac = 4.*PI/(Lev0->GArray[g].GSq);
555 c_re(vp) = 0.0;
556 c_im(vp) = 0.0;
557 c_re(rp) = 0.0;
558 c_im(rp) = 0.0;
559 for (it = 0; it < I->Max_Types; it++) {
560 c_re(vp) += (c_re(I->I[it].SFactor[g])*PP->phi_ps_loc[it][g]);
561 c_im(vp) += (c_im(I->I[it].SFactor[g])*PP->phi_ps_loc[it][g]);
562 c_re(rp) += (c_re(I->I[it].SFactor[g])*PP->FacGauss[it][g]);
563 c_im(rp) += (c_im(I->I[it].SFactor[g])*PP->FacGauss[it][g]);
564 } // rp = n^{Gauss)(G)
565
566 // n^{tot} = n^0 + \lambda n^1 + ...
567 //if (isnan(c_re(Dens0->DensityCArray[TotalDensity][Index]))) { fprintf(stderr,"(%i) WARNING in CalculatePerturbedEnergy(): TotalDensity[%i] = NaN!\n", P->Par.me, Index); Error(SomeError, "NaN-Fehler!"); }
568 c_re(TotalPsiDensity) = c_re(Dens0->DensityCArray[TotalDensity][Index]);
569 c_im(TotalPsiDensity) = c_im(Dens0->DensityCArray[TotalDensity][Index]);
570
571 c_re(rhog) = c_re(TotalPsiDensity)*R->HGcFactor+c_re(rp);
572 c_im(rhog) = c_im(TotalPsiDensity)*R->HGcFactor+c_im(rp);
573 // rhog = n(G) + n^{Gauss}(G), rhoe = n(G)
574 //if (HGC != Dens0->DensityCArray[HGDensity] || Index<0 || Index>=Dens0->LocalSizeC) Error(SomeError,"ApplyTotalHamiltonian: HGC corrupted");
575 c_re(HGC[Index]) = c_re(vp)+Fac*c_re(rhog);
576 c_im(HGC[Index]) = c_im(vp)+Fac*c_im(rhog);
577 }
578 //
579 for (i=0; i<Lev0->MaxDoubleG; i++) {
580 //if (HGC != Dens0->DensityCArray[HGDensity] || Lev0->DoubleG[2*i+1]<0 || Lev0->DoubleG[2*i+1]>Dens0->LocalSizeC || Lev0->DoubleG[2*i]<0 || Lev0->DoubleG[2*i]>Dens0->LocalSizeC) Error(SomeError,"CalculatePerturbedEnergy: grad corrupted");
581 HGC[Lev0->DoubleG[2*i+1]].re = HGC[Lev0->DoubleG[2*i]].re;
582 HGC[Lev0->DoubleG[2*i+1]].im = -HGC[Lev0->DoubleG[2*i]].im;
583 }
584 }
585 // ============ GRADIENT and EIGENVALUE Evaluation Part 1==============
586 // \lambda_l^{(1)} = \langle \varphi_l^{(1)} | H^{(0)} | \varphi_l^{(1)} \rangle and gradient calculation
587 SpeedMeasure(P, LocTime, StartTimeDo);
588 // back-transform HGDensity: (G) -> (R)
589 //if (HGC != Dens0->DensityCArray[HGDensity]) Error(SomeError,"ApplyTotalHamiltonian: HGC corrupted");
590 if (first) fft_3d_complex_to_real(plan, Lev0->LevelNo, FFTNF1, HGC, work);
591 // evaluate exchange potential with this density, add up onto HGCR
592 //if (HGCR != (fftw_real *)Dens0->DensityCArray[HGDensity]) Error(SomeError,"ApplyTotalHamiltonian: HGCR corrupted");
593 if (first) CalculateXCPotentialNoRT(P, HGCR); // add V^{xc} on V^H + V^{ps}
594 // make sure that ActualPsiDensity is recent
595 CalculateOneDensityR(Lat, LevS, Dens0, source, Dens0->DensityArray[ActualDensity], R->FactorDensityR*PsiFactor, 1);
596 for (nx=0;nx<Nx;nx++)
597 for (ny=0;ny<Ny;ny++)
598 for (nz=0;nz<Nz;nz++) {
599 i0 = nz*NUpz+Nz*NUpz*(ny*NUpy+Ny*NUpy*nx*NUpx);
600 iS = nz+Nz*(ny+Ny*nx);
601 //if (HGcR != Dens0->DensityArray[HGcDensity] || iS<0 || iS>=LevS->Dens->LocalSizeR) Error(SomeError,"ApplyTotalHamiltonian: HGC corrupted");
602 HGcR[iS] = HGCR[i0]*PsiCR[i0]; /* Matrix Vector Mult */
603 }
604 // (R) -> (G)
605 //if (HGcRC != (fftw_complex *)Dens0->DensityArray[HGcDensity]) Error(SomeError,"ApplyTotalHamiltonian: HGcRC corrupted");
606 fft_3d_real_to_complex(plan, LevS->LevelNo, FFTNF1, HGcRC, work);
607 SpeedMeasure(P, LocTime, StopTimeDo);
608 /* NonLocalPP */
609 SpeedMeasure(P, NonLocTime, StartTimeDo);
610 //if (dest != dest_bak) Error(SomeError,"ApplyTotalHamiltonian: dest corrupted");
611 CalculateAddNLPot(P, dest, fnl, PsiFactor); // wave function hidden in form factors fnl, also resets Hc_grad beforehand
612 SpeedMeasure(P, NonLocTime, StopTimeDo);
613
614 /* create final vector */
615 for (g=0;g<LevS->MaxG;g++) {
616 Index = LevS->GArray[g].Index; /* FIXME - factoren */
617 //if (dest != dest_bak || g<0 || g>=LevS->MaxG) Error(SomeError,"ApplyTotalHamiltonian: dest corrupted");
618 dest[g].re += PsiFactor*(HGcRC[Index].re*HGcRCFactor + 0.5*LevS->GArray[g].GSq*source[g].re);
619 dest[g].im += PsiFactor*(HGcRC[Index].im*HGcRCFactor + 0.5*LevS->GArray[g].GSq*source[g].im);
620 }
621}
622
623#define stay_above 0.001 //!< value above which the coefficient of the wave function will always remain
624
625/** Finds the minimum of perturbed energy in regards of actual wave function.
626 * The following happens step by step:
627 * -# The Gradient is copied into GradientTypes#GraSchGradient (which is nothing but a pointer to
628 * one array in LPsiDat) and orthonormalized via GramSch() to all occupied wave functions
629 * except to the current perturbed one.
630 * -# Then comes pre-conditioning, analogous to CalculatePreConGrad().
631 * -# The Gradient is projected onto the current perturbed wave function and this is subtracted, i.e.
632 * vector is the conjugate gradient.
633 * -# Finally, Calculate1stPerturbedDerivative() and Calculate2ndPerturbedDerivative() are called and
634 * with these results and the current total energy, CalculateDeltaI() finds the parameter for the one-
635 * dimensional minimisation. The current wave function is set to newly found minimum and approximated
636 * total energy is printed.
637 *
638 * \param *P Problem at hand
639 * \sa CalculateNewWave() and functions therein
640 */
641void FindPerturbedMinimum(struct Problem *P)
642{
643 struct Lattice *Lat = &P->Lat;
644 struct RunStruct *R = &P->R;
645 struct Psis *Psi = &Lat->Psi;
646 struct PseudoPot *PP = &P->PP;
647 struct LatticeLevel *LevS = R->LevS;
648 struct LatticeLevel *Lev0 = R->Lev0;
649 struct Density *Dens = Lev0->Dens;
650 struct Energy *En = Lat->E;
651 struct FileData *F = &P->Files;
652 int g,p,i;
653 int step = R->PsiStep;
654 double *GammaDiv = &Lat->Psi.AddData[R->ActualLocalPsiNo].Gamma;
655 const int ElementSize = (sizeof(fftw_complex) / sizeof(double));
656 fftw_complex *source = LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];
657 fftw_complex *grad = P->Grad.GradientArray[ActualGradient];
658 fftw_complex *GradOrtho = P->Grad.GradientArray[GraSchGradient];
659 fftw_complex *PCgrad = P->Grad.GradientArray[PreConGradient];
660 fftw_complex *PCOrtho = P->Grad.GradientArray[GraSchGradient];
661 fftw_complex *ConDir = P->Grad.GradientArray[ConDirGradient];
662 fftw_complex *ConDir_old = P->Grad.GradientArray[OldConDirGradient];
663 fftw_complex *Ortho = P->Grad.GradientArray[GraSchGradient];
664 const fftw_complex *Hc_grad = P->Grad.GradientArray[HcGradient];
665 const fftw_complex *H1c_grad = P->Grad.GradientArray[H1cGradient];
666 fftw_complex *HConDir = Dens->DensityCArray[ActualDensity];
667 const double PsiFactor = Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor;
668 //double Lambda = Lat->Psi.AddData[R->ActualLocalPsiNo].Lambda;
669 double T;
670 double x, K; //, dK;
671 double dS[2], S[2], Gamma, GammaDivOld = *GammaDiv;
672 double LocalSP, PsiSP;
673 double dEdt0, ddEddt0, ConDirHConDir, ConDirConDir;//, sourceHsource;
674 double E0, E, delta;
675 //double E0, E, dE, ddE, delta, dcos, dsin;
676 //double EI, dEI, ddEI, deltaI, dcosI, dsinI;
677 //double HartreeddEddt0, XCddEddt0;
678 double d[4],D[4], Diff;
679 const int Num = Psi->NoOfPsis;
680
681 // ORTHOGONALIZED-GRADIENT
682 for (g=0;g<LevS->MaxG;g++) {
683 //if (GradOrtho != P->Grad.GradientArray[GraSchGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: GradOrtho corrupted");
684 GradOrtho[g].re = grad[g].re; //+Lambda*source[g].re;
685 GradOrtho[g].im = grad[g].im; //+Lambda*source[g].im;
686 }
687 // include the ExtraPsi (which is the GraSchGradient!)
688 SetGramSchExtraPsi(P, Psi, NotOrthogonal);
689 // exclude the minimised Psi
690 SetGramSchActualPsi(P, Psi, NotUsedToOrtho);
691 SpeedMeasure(P, GramSchTime, StartTimeDo);
692 // makes conjugate gradient orthogonal to all other orbits
693 //fprintf(stderr,"CalculateCGGradient: GramSch() for extra orbital\n");
694 GramSch(P, LevS, Psi, Orthogonalize);
695 SpeedMeasure(P, GramSchTime, StopTimeDo);
696 //if (grad != P->Grad.GradientArray[ActualGradient]) Error(SomeError,"FindPerturbedMinimum: grad corrupted");
697 memcpy(grad, GradOrtho, ElementSize*LevS->MaxG*sizeof(double));
698 //memcpy(PCOrtho, GradOrtho, ElementSize*LevS->MaxG*sizeof(double));
699
700 // PRE-CONDITION-GRADIENT
701 //if (fabs(T) < MYEPSILON) T = 1;
702 T = 0.;
703 for (i=0;i<Num;i++)
704 T += Psi->lambda[i][i];
705 for (g=0;g<LevS->MaxG;g++) {
706 x = .5*LevS->GArray[g].GSq;
707 // FIXME: Good way of accessing reciprocal Lev0 Density coefficients on LevS! (not so trivial)
708 //x += sqrt(Dens->DensityCArray[HGDensity][g].re*Dens->DensityCArray[HGDensity][g].re+Dens->DensityCArray[HGDensity][g].im*Dens->DensityCArray[HGDensity][g].im);
709 x -= T/(double)Num;
710 K = x/(x*x+stay_above*stay_above);
711 //if (PCOrtho != P->Grad.GradientArray[GraSchGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: PCOrtho corrupted");
712 c_re(PCOrtho[g]) = K*c_re(grad[g]);
713 c_im(PCOrtho[g]) = K*c_im(grad[g]);
714 }
715 SetGramSchExtraPsi(P, Psi, NotOrthogonal);
716 SpeedMeasure(P, GramSchTime, StartTimeDo);
717 // preconditioned direction is orthogonalized
718 //fprintf(stderr,"CalculatePreConGrad: GramSch() for extra orbital\n");
719 GramSch(P, LevS, Psi, Orthogonalize);
720 SpeedMeasure(P, GramSchTime, StopTimeDo);
721 //if (PCgrad != P->Grad.GradientArray[PreConGradient]) Error(SomeError,"FindPerturbedMinimum: PCgrad corrupted");
722 memcpy(PCgrad, PCOrtho, ElementSize*LevS->MaxG*sizeof(double));
723
724 //debug(P, "Before ConDir");
725 //fprintf(stderr,"|(%i)|^2 = %lg\t |PCgrad|^2 = %lg\t |PCgrad,(%i)| = %lg\n", R->ActualLocalPsiNo, GradSP(P,LevS,source,source),GradSP(P,LevS,PCgrad,PCgrad), R->ActualLocalPsiNo, GradSP(P,LevS,PCgrad,source));
726 // CONJUGATE-GRADIENT
727 LocalSP = GradSP(P, LevS, PCgrad, grad);
728 MPI_Allreduce ( &LocalSP, &PsiSP, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
729 *GammaDiv = dS[0] = PsiSP;
730 dS[1] = GammaDivOld;
731 S[0]=dS[0]; S[1]=dS[1];
732 /*MPI_Allreduce ( dS, S, 2, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_PsiT);*/
733 if (step) { // only in later steps is the scalar product used, but always condir stored in oldcondir and Ortho (working gradient)
734 if (fabs(S[1]) < MYEPSILON) fprintf(stderr,"CalculateConDir: S[1] = %lg\n",S[1]);
735 Gamma = S[0]/S[1];
736 if (fabs(S[1]) < MYEPSILON) {
737 if (fabs(S[0]) < MYEPSILON)
738 Gamma = 1.0;
739 else
740 Gamma = 0.0;
741 }
742 for (g=0; g < LevS->MaxG; g++) {
743 //if (ConDir != P->Grad.GradientArray[ConDirGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
744 c_re(ConDir[g]) = c_re(PCgrad[g]) + Gamma*c_re(ConDir_old[g]);
745 c_im(ConDir[g]) = c_im(PCgrad[g]) + Gamma*c_im(ConDir_old[g]);
746 //if (ConDir_old != P->Grad.GradientArray[OldConDirGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: ConDir_old corrupted");
747 c_re(ConDir_old[g]) = c_re(ConDir[g]);
748 c_im(ConDir_old[g]) = c_im(ConDir[g]);
749 //if (Ortho != P->Grad.GradientArray[GraSchGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: Ortho corrupted");
750 c_re(Ortho[g]) = c_re(ConDir[g]);
751 c_im(Ortho[g]) = c_im(ConDir[g]);
752 }
753 } else {
754 Gamma = 0.0;
755 for (g=0; g < LevS->MaxG; g++) {
756 //if (ConDir != P->Grad.GradientArray[ConDirGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
757 c_re(ConDir[g]) = c_re(PCgrad[g]);
758 c_im(ConDir[g]) = c_im(PCgrad[g]);
759 //if (ConDir_old != P->Grad.GradientArray[OldConDirGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: ConDir_old corrupted");
760 c_re(ConDir_old[g]) = c_re(ConDir[g]);
761 c_im(ConDir_old[g]) = c_im(ConDir[g]);
762 //if (Ortho != P->Grad.GradientArray[GraSchGradient] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: Ortho corrupted");
763 c_re(Ortho[g]) = c_re(ConDir[g]);
764 c_im(Ortho[g]) = c_im(ConDir[g]);
765 }
766 }
767 // orthonormalize
768 SetGramSchExtraPsi(P, Psi, NotOrthogonal);
769 SpeedMeasure(P, GramSchTime, StartTimeDo);
770 //fprintf(stderr,"CalculateConDir: GramSch() for extra orbital\n");
771 GramSch(P, LevS, Psi, Orthogonalize);
772 SpeedMeasure(P, GramSchTime, StopTimeDo);
773 //if (ConDir != P->Grad.GradientArray[ConDirGradient]) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
774 memcpy(ConDir, Ortho, ElementSize*LevS->MaxG*sizeof(double));
775 //debug(P, "Before LineSearch");
776 //fprintf(stderr,"|(%i)|^2 = %lg\t |ConDir|^2 = %lg\t |ConDir,(%i)| = %lg\n", R->ActualLocalPsiNo, GradSP(P,LevS,source,source),GradSP(P,LevS,ConDir,ConDir), R->ActualLocalPsiNo, GradSP(P,LevS,ConDir,source));
777 SetGramSchActualPsi(P, Psi, IsOrthogonal);
778
779 //fprintf(stderr,"(%i) Testing conjugate gradient for Orthogonality ...\n", P->Par.me);
780 //TestForOrth(P,LevS,ConDir);
781
782 // ONE-DIMENSIONAL LINE-SEARCH
783
784 // ========= dE / dt | 0 ============
785 p = Lat->Psi.TypeStartIndex[Occupied] + (R->ActualLocalPsiNo - Lat->Psi.TypeStartIndex[R->CurrentMin]);
786 //if (Hc_grad != P->Grad.GradientArray[HcGradient]) Error(SomeError,"FindPerturbedMinimum: Hc_grad corrupted");
787 //if (H1c_grad != P->Grad.GradientArray[H1cGradient]) Error(SomeError,"FindPerturbedMinimum: H1c_grad corrupted");
788 d[0] = Calculate1stPerturbedDerivative(P, LevS->LPsi->LocalPsi[p], source, ConDir, Hc_grad, H1c_grad);
789 //CalculateConDirHConDir(P, ConDir, PsiFactor, &d[1], &d[2], &d[3]);
790 //if (ConDir != P->Grad.GradientArray[ConDirGradient]) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
791 CalculateCDfnl(P, ConDir, PP->CDfnl); // calculate needed non-local form factors
792 //if (HConDir != Dens->DensityCArray[ActualDensity]) Error(SomeError,"FindPerturbedMinimum: HConDir corrupted");
793 SetArrayToDouble0((double *)HConDir,Dens->TotalSize*2);
794 //if (ConDir != P->Grad.GradientArray[ConDirGradient]) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
795 ApplyTotalHamiltonian(P,ConDir,HConDir, PP->CDfnl, PsiFactor, 0); // applies H^(0) with total perturbed density!
796 d[1] = GradSP(P,LevS,ConDir,HConDir);
797 d[2] = GradSP(P,LevS,ConDir,ConDir);
798 d[3] = 0.;
799
800 // gather results
801 MPI_Allreduce ( &d, &D, 4, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
802 // ========== ddE / ddt | 0 =========
803 dEdt0 = D[0];
804 for (i=MAXOLD-1; i > 0; i--)
805 En->dEdt0[i] = En->dEdt0[i-1];
806 En->dEdt0[0] = dEdt0;
807 ConDirHConDir = D[1];
808 ConDirConDir = D[2];
809 ddEddt0 = 0.0;
810 //if (ConDir != P->Grad.GradientArray[ConDirGradient]) Error(SomeError,"FindPerturbedMinimum: ConDir corrupted");
811 //if (H1c_grad != P->Grad.GradientArray[H1cGradient]) Error(SomeError,"FindPerturbedMinimum: H1c_grad corrupted");
812 ddEddt0 = Calculate2ndPerturbedDerivative(P, LevS->LPsi->LocalPsi[p], source, ConDir, Lat->Psi.AddData[R->ActualLocalPsiNo].Lambda * Psi->LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor, ConDirHConDir, ConDirConDir);
813
814 for (i=MAXOLD-1; i > 0; i--)
815 En->ddEddt0[i] = En->ddEddt0[i-1];
816 En->ddEddt0[0] = ddEddt0;
817 E0 = En->TotalEnergy[0];
818 // delta
819 //if (isnan(E0)) { fprintf(stderr,"(%i) WARNING in CalculateLineSearch(): E0_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
820 //if (isnan(dEdt0)) { fprintf(stderr,"(%i) WARNING in CalculateLineSearch(): dEdt0_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
821 //if (isnan(ddEddt0)) { fprintf(stderr,"(%i) WARNING in CalculateLineSearch(): ddEddt0_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
822
823 ////deltaI = CalculateDeltaI(E0, dEdt0, ddEddt0,
824 //// &EI, &dEI, &ddEI, &dcosI, &dsinI);
825 ////delta = deltaI; E = EI; dE = dEI; ddE = ddEI; dcos = dcosI; dsin = dsinI;
826 if (ddEddt0 > 0) {
827 delta = - dEdt0/ddEddt0;
828 E = E0 + delta * dEdt0 + delta*delta/2. * ddEddt0;
829 } else {
830 delta = 0.;
831 E = E0;
832 fprintf(stderr,"(%i) Taylor approximation leads not to minimum!\n",P->Par.me);
833 }
834
835 // shift energy delta values
836 for (i=MAXOLD-1; i > 0; i--) {
837 En->delta[i] = En->delta[i-1];
838 En->ATE[i] = En->ATE[i-1];
839 }
840 // store new one
841 En->delta[0] = delta;
842 En->ATE[0] = E;
843 if (En->TotalEnergy[1] != 0.)
844 Diff = fabs(En->TotalEnergy[1] - E0)/(En->TotalEnergy[1] - E0)*fabs((E0 - En->ATE[1])/E0);
845 else
846 Diff = 0.;
847 R->Diffcount += pow(Diff,2);
848
849 // reinstate actual density (only needed for UpdateDensityCalculation) ...
850 //CalculateOneDensityR(Lat, LevS, Dens, source, Dens->DensityArray[ActualDensity], R->FactorDensityR*Psi->LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor, 1);
851 // ... before changing actual local Psi
852 for (g = 0; g < LevS->MaxG; g++) { // Here all coefficients are updated for the new found wave function
853 //if (isnan(ConDir[g].re)) { fprintf(stderr,"WARNGING: CalculateLineSearch(): ConDir_%i(%i) = NaN!\n", R->ActualLocalPsiNo, g); Error(SomeError, "NaN-Fehler!"); }
854 //if (source != LevS->LPsi->LocalPsi[R->ActualLocalPsiNo] || g<0 || g>=LevS->MaxG) Error(SomeError,"FindPerturbedMinimum: source corrupted");
855 ////c_re(source[g]) = c_re(source[g])*dcos + c_re(ConDir[g])*dsin;
856 ////c_im(source[g]) = c_im(source[g])*dcos + c_im(ConDir[g])*dsin;
857 c_re(source[g]) = c_re(source[g]) + c_re(ConDir[g])*delta;
858 c_im(source[g]) = c_im(source[g]) + c_im(ConDir[g])*delta;
859 }
860 if (P->Call.out[StepLeaderOut]) {
861 fprintf(stderr, "(%i,%i,%i)S(%i,%i,%i):\tTE: %e\tATE: %e\t Diff: %e\t --- d: %e\tdEdt0: %e\tddEddt0: %e\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, E0, E, Diff,delta, dEdt0, ddEddt0);
862 //fprintf(stderr, "(%i,%i,%i)S(%i,%i,%i):\tp0: %e p1: %e p2: %e \tATE: %e\t Diff: %e\t --- d: %e\tdEdt0: %e\tddEddt0: %e\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, En->parts[0], En->parts[1], En->parts[2], E, Diff,delta, dEdt0, ddEddt0);
863 }
864 if (P->Par.me == 0) {
865 fprintf(F->MinimisationFile, "%i\t%i\t%i\t%e\t%e\t%e\t%e\t%e\n",R->MinStep, R->ActualLocalPsiNo, R->PsiStep, E0, E, delta, dEdt0, ddEddt0);
866 fflush(F->MinimisationFile);
867 }
868}
869
870/** Applies perturbation operator \f$\nabla_{index}\f$ to \a *source.
871 * As wave functions are stored in the reciprocal basis set, the application is straight-forward,
872 * for every G vector, the by \a index specified component is multiplied with the respective
873 * coefficient. Afterwards, 1/i is applied by flipping real and imaginary components (and an additional minus sign on the new imaginary term).
874 * \param *P Problem at hand
875 * \param *source complex coefficients of wave function \f$\varphi(G)\f$
876 * \param *dest returned complex coefficients of wave function \f$\widehat{p}_{index}|\varphi(G)\f$
877 * \param index_g vectorial index of operator to be applied
878 */
879void CalculatePerturbationOperator_P(struct Problem *P, const fftw_complex *source, fftw_complex *dest, const int index_g)
880{
881 struct RunStruct *R = &P->R;
882 struct LatticeLevel *LevS = R->LevS;
883 //const fftw_complex *dest_bak = dest;
884 int g = 0;
885 if (LevS->GArray[0].GSq == 0.0) {
886 //if (dest != dest_bak) Error(SomeError,"CalculatePerturbationOperator_P: dest corrupted");
887 dest[0].re = LevS->GArray[0].G[index_g]*source[0].im;
888 dest[0].im = -LevS->GArray[0].G[index_g]*source[0].re;
889 g++;
890 }
891 for (;g<LevS->MaxG;g++) {
892 //if (dest != dest_bak || g<0 || g>=LevS->MaxG) Error(SomeError,"CalculatePerturbationOperator_P: g out of range");
893 dest[g].re = LevS->GArray[g].G[index_g]*source[g].im;
894 dest[g].im = -LevS->GArray[g].G[index_g]*source[g].re;
895 }
896 // don't put dest[0].im = 0! Otherwise real parts of perturbed01/10 are not the same anymore!
897}
898
899/** Applies perturbation operator \f$\widehat{r}_{index}\f$ to \a *source.
900 * The \a *source wave function is blown up onto upper level LatticeLevel RunStruct#Lev0, fourier
901 * transformed. Afterwards, for each point on the real mesh the coefficient is multiplied times the real
902 * vector pointing within the cell to the mesh point, yet on LatticeLevel RunStruct#LevS. The new wave
903 * function is inverse fourier transformed and the resulting reciprocal coefficients stored in *dest.
904 * \param *P Problem at hand
905 * \param *source source coefficients
906 * \param *source2 second source coefficients, e.g. in the evaluation of a scalar product
907 * \param *dest destination coefficienta array, is overwrittten!
908 * \param index_r index of real vector.
909 * \param wavenr index of respective PsiTypeTag#Occupied(!) OnePsiElementAddData for the needed Wanner centre of the wave function.
910 */
911void CalculatePerturbationOperator_R(struct Problem *P, const fftw_complex *source, fftw_complex *dest, const fftw_complex *source2, const int index_r, const int wavenr)
912{
913 struct Lattice *Lat = &P->Lat;
914 struct RunStruct *R = &P->R;
915 struct LatticeLevel *Lev0 = R->Lev0;
916 struct LatticeLevel *LevS = R->LevS;
917 struct Density *Dens0 = Lev0->Dens;
918 struct fft_plan_3d *plan = Lat->plan;
919 fftw_complex *TempPsi = Dens0->DensityCArray[Temp2Density];
920 fftw_real *TempPsiR = (fftw_real *) TempPsi;
921 fftw_complex *workC = Dens0->DensityCArray[TempDensity];
922 fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
923 fftw_real *PsiCR = (fftw_real *) PsiC;
924 fftw_complex *tempdestRC = (fftw_complex *)Dens0->DensityArray[TempDensity];
925 fftw_complex *posfac, *destsnd, *destrcv;
926 double x[NDIM], fac[NDIM], Wcentre[NDIM];
927 const int k_normal = Lat->Psi.TypeStartIndex[Occupied] + (wavenr - Lat->Psi.TypeStartIndex[R->CurrentMin]);
928 int n[NDIM], n0, g, Index, pos, iS, i0;
929 int N[NDIM], NUp[NDIM];
930 const int N0 = LevS->Plan0.plan->local_nx;
931 N[0] = LevS->Plan0.plan->N[0];
932 N[1] = LevS->Plan0.plan->N[1];
933 N[2] = LevS->Plan0.plan->N[2];
934 NUp[0] = LevS->NUp[0];
935 NUp[1] = LevS->NUp[1];
936 NUp[2] = LevS->NUp[2];
937 Wcentre[0] = Lat->Psi.AddData[k_normal].WannierCentre[0];
938 Wcentre[1] = Lat->Psi.AddData[k_normal].WannierCentre[1];
939 Wcentre[2] = Lat->Psi.AddData[k_normal].WannierCentre[2];
940 // init pointers and values
941 const int myPE = P->Par.me_comm_ST_Psi;
942 const double FFTFactor = 1./LevS->MaxN;
943 double vector;
944 //double result, Result;
945
946 // blow up source coefficients
947 LockDensityArray(Dens0,TempDensity,real); // tempdestRC
948 LockDensityArray(Dens0,Temp2Density,imag); // TempPsi
949 LockDensityArray(Dens0,ActualPsiDensity,imag); // PsiC
950 //if (tempdestRC != (fftw_complex *)Dens0->DensityArray[TempDensity]) Error(SomeError,"CalculatePerturbationOperator_R: tempdestRC corrupted");
951 SetArrayToDouble0((double *)tempdestRC ,Dens0->TotalSize*2);
952 //if (TempPsi != Dens0->DensityCArray[Temp2Density]) Error(SomeError,"CalculatePerturbationOperator_R: TempPsi corrupted");
953 SetArrayToDouble0((double *)TempPsi ,Dens0->TotalSize*2);
954 //if (PsiC != Dens0->DensityCArray[ActualPsiDensity]) Error(SomeError,"CalculatePerturbationOperator_R: PsiC corrupted");
955 SetArrayToDouble0((double *)PsiC,Dens0->TotalSize*2);
956 for (g=0; g<LevS->MaxG; g++) {
957 Index = LevS->GArray[g].Index;
958 posfac = &LevS->PosFactorUp[LevS->MaxNUp*g];
959 destrcv = &tempdestRC[LevS->MaxNUp*Index];
960 for (pos=0; pos < LevS->MaxNUp; pos++) {
961 //if (destrcv != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->LocalSizeC) Error(SomeError,"CalculatePerturbationOperator_R: destrcv corrupted");
962 destrcv [pos].re = (( source[g].re)*posfac[pos].re-(source[g].im)*posfac[pos].im);
963 destrcv [pos].im = (( source[g].re)*posfac[pos].im+(source[g].im)*posfac[pos].re);
964 }
965 }
966 for (g=0; g<LevS->MaxDoubleG; g++) {
967 destsnd = &tempdestRC [LevS->DoubleG[2*g]*LevS->MaxNUp];
968 destrcv = &tempdestRC [LevS->DoubleG[2*g+1]*LevS->MaxNUp];
969 for (pos=0; pos<LevS->MaxNUp; pos++) {
970 //if (destrcv != &tempdestRC [LevS->DoubleG[2*g+1]*LevS->MaxNUp] || LevS->DoubleG[2*g]*LevS->MaxNUp+pos<0 || LevS->DoubleG[2*g]*LevS->MaxNUp+pos>=Dens0->LocalSizeC|| LevS->DoubleG[2*g+1]*LevS->MaxNUp+pos<0 || LevS->DoubleG[2*g+1]*LevS->MaxNUp+pos>=Dens0->LocalSizeC) Error(SomeError,"CalculatePerturbationOperator_R: destrcv corrupted");
971 destrcv [pos].re = destsnd [pos].re;
972 destrcv [pos].im = -destsnd [pos].im;
973 }
974 }
975 // fourier transform blown up wave function
976 //if (tempdestRC != (fftw_complex *)Dens0->DensityArray[TempDensity]) Error(SomeError,"CalculatePerturbationOperator_R: tempdestRC corrupted");
977 //if (workC != Dens0->DensityCArray[TempDensity]) Error(SomeError,"CalculatePerturbationOperator_R: workC corrupted");
978 fft_3d_complex_to_real(plan,LevS->LevelNo, FFTNFUp, tempdestRC , workC);
979 //if (tempdestRC != (fftw_complex *)Dens0->DensityArray[TempDensity]) Error(SomeError,"CalculatePerturbationOperator_R: tempdestRC corrupted");
980 //if (TempPsiR != (fftw_real *)Dens0->DensityCArray[Temp2Density]) Error(SomeError,"CalculatePerturbationOperator_R: TempPsiR corrupted");
981 DensityRTransformPos(LevS,(fftw_real*)tempdestRC ,TempPsiR );
982 UnLockDensityArray(Dens0,TempDensity,real); // TempdestRC
983
984 //result = 0.;
985 // for every point on the real grid multiply with component of position vector
986 for (n0=0; n0<N0; n0++)
987 for (n[1]=0; n[1]<N[1]; n[1]++)
988 for (n[2]=0; n[2]<N[2]; n[2]++) {
989 n[0] = n0 + N0 * myPE;
990 fac[0] = (double)(n[0])/(double)((N[0]));
991 fac[1] = (double)(n[1])/(double)((N[1]));
992 fac[2] = (double)(n[2])/(double)((N[2]));
993 RMat33Vec3(x,Lat->RealBasis,fac);
994 iS = n[2] + N[2]*(n[1] + N[1]*n0); // mind splitting of x axis due to multiple processes
995 i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
996 //PsiCR[iS] = ((double)n[0]/(double)N[0]*Lat->RealBasis[0] - fabs(Wcentre[0]))*TempPsiR[i0] - ((double)n[1]/(double)N[1]*Lat->RealBasis[4] - fabs(Wcentre[1]))*TempPsi2R[i0];
997 //fprintf(stderr,"(%i) R[%i] = (%lg,%lg,%lg)\n",P->Par.me, i0, x[0], x[1], x[2]);
998 //else fprintf(stderr,"(%i) WCentre[%i] = %e \n",P->Par.me, index_r, Wcentre[index_r]);
999 vector = sawtooth(Lat,MinImageConv(Lat,x[index_r],Wcentre[index_r],index_r),index_r);
1000 //vector = 1.;//sin((double)(n[index_r])/(double)((N[index_r]))*2*PI);
1001 PsiCR[iS] = vector * TempPsiR[i0];
1002 //fprintf(stderr,"(%i) vector(%i/%i,%i/%i,%i/%i): %lg\tx[%i] = %e\tWcentre[%i] = %e\tTempPsiR[%i] = %e\tPsiCR[%i] = %e\n",P->Par.me, n[0], N[0], n[1], N[1], n[2], N[2], vector, index_r, x[index_r],index_r, Wcentre[index_r],i0,TempPsiR[i0],iS,PsiCR[iS]);
1003
1004 //truedist(Lat,x[cross(index_r,2)],Wcentre[cross(index_r,2)],cross(index_r,2)) * TempPsiR[i0];
1005 //tmp += truedist(Lat,x[index_r],WCentre[index_r],index_r) * RealPhiR[i0];
1006 //tmp += sawtooth(Lat,truedist(Lat,x[index_r],WCentre[index_r],index_r), index_r)*RealPhiR[i0];
1007 //(Fehler mit falschem Ort ist vor dieser Stelle!): ueber result = RealPhiR[i0] * (x[index_r]) * RealPhiR[i0]; gecheckt
1008 //result += TempPsiR[i0] * PsiCR[iS];
1009 }
1010 UnLockDensityArray(Dens0,Temp2Density,imag); // TempPsi
1011 //MPI_Allreduce( &result, &Result, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
1012 //if (P->Par.me == 0) fprintf(stderr,"(%i) PerturbationOpertator_R: %e\n",P->Par.me, Result/LevS->MaxN);
1013 // inverse fourier transform
1014 fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, PsiC, workC);
1015 //fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, Psi2C, workC);
1016
1017 // copy to destination array
1018 for (g=0; g<LevS->MaxG; g++) {
1019 Index = LevS->GArray[g].Index;
1020 dest[g].re = ( PsiC[Index].re)*FFTFactor;
1021 dest[g].im = ( PsiC[Index].im)*FFTFactor;
1022 }
1023 UnLockDensityArray(Dens0,ActualPsiDensity,imag); //PsiC
1024 //if (LevS->GArray[0].GSq == 0)
1025 // dest[0].im = 0; // imaginary of G=0 is zero
1026}
1027/*
1028{
1029 struct RunStruct *R = &P->R;
1030 struct LatticeLevel *Lev0 = R->Lev0;
1031 struct LatticeLevel *LevS = R->LevS;
1032 struct Lattice *Lat = &P->Lat;
1033 struct fft_plan_3d *plan = Lat->plan;
1034 struct Density *Dens0 = Lev0->Dens;
1035 fftw_complex *tempdestRC = Dens0->DensityCArray[TempDensity];
1036 fftw_real *tempdestR = (fftw_real *) tempdestRC;
1037 fftw_complex *work = Dens0->DensityCArray[Temp2Density];
1038 fftw_complex *PsiC = (fftw_complex *) Dens0->DensityCArray[ActualPsiDensity];;
1039 fftw_real *PsiCR = (fftw_real *) PsiC;
1040 fftw_real *RealPhiR = (fftw_real *) Dens0->DensityArray[Temp2Density];
1041 fftw_complex *posfac, *destsnd, *destrcv;
1042 double x[NDIM], fac[NDIM], WCentre[NDIM];
1043 int n[NDIM], N0, n0, g, Index, pos, iS, i0;
1044
1045 // init pointers and values
1046 int myPE = P->Par.me_comm_ST_Psi;
1047 double FFTFactor = 1./LevS->MaxN;
1048 int N[NDIM], NUp[NDIM];
1049 N[0] = LevS->Plan0.plan->N[0];
1050 N[1] = LevS->Plan0.plan->N[1];
1051 N[2] = LevS->Plan0.plan->N[2];
1052 NUp[0] = LevS->NUp[0];
1053 NUp[1] = LevS->NUp[1];
1054 NUp[2] = LevS->NUp[2];
1055 N0 = LevS->Plan0.plan->local_nx;
1056 wavenr = Lat->Psi.TypeStartIndex[Occupied] + (wavenr - Lat->Psi.TypeStartIndex[R->CurrentMin]);
1057 Wcentre[0] = Lat->Psi.AddData[wavenr].WannierCentre[0];
1058 Wcentre[1] = Lat->Psi.AddData[wavenr].WannierCentre[1];
1059 Wcentre[2] = Lat->Psi.AddData[wavenr].WannierCentre[2];
1060
1061 // blow up source coefficients
1062 SetArrayToDouble0((double *)tempdestRC,Dens0->TotalSize*2);
1063 SetArrayToDouble0((double *)RealPhiR,Dens0->TotalSize*2);
1064 SetArrayToDouble0((double *)PsiC,Dens0->TotalSize*2);
1065 for (g=0; g<LevS->MaxG; g++) {
1066 Index = LevS->GArray[g].Index;
1067 posfac = &LevS->PosFactorUp[LevS->MaxNUp*g];
1068 destrcv = &tempdestRC[LevS->MaxNUp*Index];
1069 for (pos=0; pos<LevS->MaxNUp; pos++) {
1070 destrcv[pos].re = (( source[g].re)*posfac[pos].re-( source[g].im)*posfac[pos].im);
1071 destrcv[pos].im = (( source[g].re)*posfac[pos].im+( source[g].im)*posfac[pos].re);
1072 }
1073 }
1074 for (g=0; g<LevS->MaxDoubleG; g++) {
1075 destsnd = &tempdestRC[LevS->DoubleG[2*g]*LevS->MaxNUp];
1076 destrcv = &tempdestRC[LevS->DoubleG[2*g+1]*LevS->MaxNUp];
1077 for (pos=0; pos<LevS->MaxNUp; pos++) {
1078 destrcv[pos].re = destsnd[pos].re;
1079 destrcv[pos].im = -destsnd[pos].im;
1080 }
1081 }
1082
1083 // fourier transform blown up wave function
1084 fft_3d_complex_to_real(plan,LevS->LevelNo, FFTNFUp, tempdestRC, work);
1085 DensityRTransformPos(LevS,tempdestR,RealPhiR);
1086
1087 //fft_Psi(P,source,RealPhiR,0,0);
1088
1089 // for every point on the real grid multiply with component of position vector
1090 for (n0=0; n0<N0; n0++)
1091 for (n[1]=0; n[1]<N[1]; n[1]++)
1092 for (n[2]=0; n[2]<N[2]; n[2]++) {
1093 n[0] = n0 + N0 * myPE;
1094 fac[0] = (double)(n[0])/(double)((N[0]));
1095 fac[1] = (double)(n[1])/(double)((N[1]));
1096 fac[2] = (double)(n[2])/(double)((N[2]));
1097 RMat33Vec3(x,Lat->RealBasis,fac);
1098 iS = n[2] + N[2]*(n[1] + N[1]*n0); // mind splitting of x axis due to multiple processes
1099 i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
1100 //PsiCR[iS] = (x[index_r]) * RealPhiR[i0]; //- WCentre[index_r]
1101 PsiCR[iS] = truedist(Lat,x[index_r],WCentre[index_r],index_r) * RealPhiR[i0];
1102 //PsiCR[iS] = truedist(Lat,x[index_r],0.,index_r) * RealPhiR[i0];
1103 //PsiCR[iS] = sawtooth(Lat,truedist(Lat,x[index_r],WCentre[index_r],index_r), index_r)*RealPhiR[i0];
1104 //(Fehler mit falschem Ort ist vor dieser Stelle!): ueber result = RealPhiR[i0] * (x[index_r]) * RealPhiR[i0]; gecheckt
1105 }
1106
1107 // inverse fourier transform
1108 fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, PsiC, work);
1109
1110 // copy to destination array
1111 for (g=0; g<LevS->MaxG; g++) {
1112 Index = LevS->GArray[g].Index;
1113 dest[g].re = ( PsiC[Index].re)*FFTFactor;
1114 dest[g].im = ( PsiC[Index].im)*FFTFactor;
1115 if (LevS->GArray[g].GSq == 0)
1116 dest[g].im = 0; // imaginary of G=0 is zero
1117 }
1118}*/
1119
1120/** Prints the positions of all unperturbed orbitals to screen.
1121 * \param *P Problem at hand
1122 * \param type PsiTypeTag specifying group of orbitals
1123 * \sa CalculatePerturbationOperator_R()
1124 */
1125void OutputOrbitalPositions(struct Problem *P, const enum PsiTypeTag type)
1126{
1127 struct Lattice *Lat = &P->Lat;
1128 struct Psis *Psi = &Lat->Psi;
1129 struct RunStruct *R = &P->R;
1130 struct LatticeLevel *LevS = R->LevS;
1131 fftw_complex *temp = LevS->LPsi->TempPsi;
1132 fftw_complex *source;
1133 int wavenr, index;
1134 double result[NDIM], Result[NDIM];
1135 //double imsult[NDIM], Imsult[NDIM];
1136 double norm[NDIM], Norm[NDIM];
1137 //double imnorm[NDIM], imNorm[NDIM];
1138 double Wcentre[NDIM];
1139
1140 // for every unperturbed wave function
1141 for (wavenr=Psi->TypeStartIndex[type]; wavenr<Psi->TypeStartIndex[type+1]; wavenr++) {
1142 source = LevS->LPsi->LocalPsi[wavenr];
1143 Wcentre[0] = Psi->AddData[wavenr].WannierCentre[0];
1144 Wcentre[1] = Psi->AddData[wavenr].WannierCentre[1];
1145 Wcentre[2] = Psi->AddData[wavenr].WannierCentre[2];
1146 for (index=0; index<NDIM; index++) {
1147 SetArrayToDouble0((double *)temp,2*R->InitLevS->MaxG);
1148 // apply position operator
1149 CalculatePerturbationOperator_R(P,source,temp,source,index, wavenr + Psi->TypeStartIndex[R->CurrentMin]);
1150 // take scalar product
1151 result[index] = GradSP(P,LevS,source,temp);
1152 //imsult[index] = GradImSP(P,LevS,source,temp);
1153 norm[index] = GradSP(P,LevS,source,source);
1154 //imnorm[index] = GradImSP(P,LevS,source,source);
1155 MPI_Allreduce( result, Result, NDIM, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
1156 //MPI_Allreduce( imsult, Imsult, NDIM, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
1157 MPI_Allreduce( norm, Norm, NDIM, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
1158 //MPI_Allreduce( imnorm, imNorm, NDIM, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
1159 }
1160 // print output to stderr
1161 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Position of Orbital %i: (%e,%e,%e)\n",P->Par.me, wavenr, Result[0]/Norm[0]+Wcentre[0], Result[1]/Norm[1]+Wcentre[1], Result[2]/Norm[2]+Wcentre[2]);
1162 //fprintf(stderr,"(%i) Position of Orbital %i wrt Wannier: (%e,%e,%e)\n",P->Par.me, wavenr, Result[0]/Norm[0], Result[1]/Norm[1], Result[2]/Norm[2]);
1163 //fprintf(stderr,"(%i) with Norm: (%e,%e,%e) + i (%e,%e,%e)\n",P->Par.me, Norm[0], Norm[1], Norm[2], imNorm[0], imNorm[1], imNorm[2]);
1164 //if (P->Par.me == 0) fprintf(stderr,"(%i) Position of Orbital %i: (%e,%e,%e)\n",P->Par.me, wavenr, Result[0]/Norm[0], Result[1]/Norm[1], Result[2]/Norm[2]);
1165 }
1166}
1167
1168#define borderstart 0.9
1169
1170/** Applies perturbation operator \f$(\widehat{r} \times \nabla)_{index}\f$ to \a *source.
1171 * The source is fourier-transformed by transforming it to a density (on the next higher level RunStruct#Lev0)
1172 * and at the same time multiply it with the respective component of the reciprocal G vector - the momentum. This
1173 * is done by callinf fft_Psi(). Thus we get \f$\nabla_k | \varphi (R) \rangle\f$.
1174 *
1175 * Next, we apply the two of three components of the position operator r, which ones stated by cross(), while going
1176 * in a loop through every point of the grid. In order to do this sensibly, truedist() is used to map the coordinates
1177 * onto -L/2...L/2, by subtracting the OneElementPsiAddData#WannierCentre R and wrapping. Also, due to the breaking up
1178 * of the x axis into equally sized chunks for each coefficient sharing process, we need to step only over local
1179 * x-axis grid points, however shift them to the global position when being used as position. In the end, we get
1180 * \f$\epsilon_{index,j,k} (\widehat{r}-R)_j \nabla_k | \varphi (R) \rangle\f$.
1181 *
1182 * One last fft brings the wave function back to reciprocal basis and it is copied to \a *dest.
1183 * \param *P Problem at hand
1184 * \param *source complex coefficients of wave function \f$\varphi(G)\f$
1185 * \param *dest returned complex coefficients of wave function \f$(\widehat{r} \times \widehat{p})_{index}|\varphi(G)\rangle\f$
1186 * \param phi0nr number within LocalPsi of the unperturbed pendant of the given perturbed wavefunction \a *source.
1187 * \param index_rxp index desired of the vector product
1188 * \sa CalculateConDirHConDir() - the procedure of fft and inverse fft is very similar.
1189 */
1190void CalculatePerturbationOperator_RxP(struct Problem *P, const fftw_complex *source, fftw_complex *dest, const int phi0nr, const int index_rxp)
1191
1192{
1193 struct Lattice *Lat = &P->Lat;
1194 struct RunStruct *R = &P->R;
1195 struct LatticeLevel *Lev0 = R->Lev0;
1196 struct LatticeLevel *LevS = R->LevS;
1197 struct Density *Dens0 = Lev0->Dens;
1198 struct fft_plan_3d *plan = Lat->plan;
1199 fftw_complex *TempPsi = Dens0->DensityCArray[Temp2Density];
1200 fftw_real *TempPsiR = (fftw_real *) TempPsi;
1201 fftw_complex *TempPsi2 = (fftw_complex *)Dens0->DensityArray[Temp2Density];
1202 fftw_real *TempPsi2R = (fftw_real *) TempPsi2;
1203 fftw_complex *workC = Dens0->DensityCArray[TempDensity];
1204 fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
1205 fftw_real *PsiCR = (fftw_real *) PsiC;
1206 double x[NDIM], fac[NDIM], Wcentre[NDIM];
1207 int n[NDIM], n0, g, Index, iS, i0; //pos,
1208 int N[NDIM], NUp[NDIM];
1209 const int N0 = LevS->Plan0.plan->local_nx;
1210 N[0] = LevS->Plan0.plan->N[0];
1211 N[1] = LevS->Plan0.plan->N[1];
1212 N[2] = LevS->Plan0.plan->N[2];
1213 NUp[0] = LevS->NUp[0];
1214 NUp[1] = LevS->NUp[1];
1215 NUp[2] = LevS->NUp[2];
1216 Wcentre[0] = Lat->Psi.AddData[phi0nr].WannierCentre[0];
1217 Wcentre[1] = Lat->Psi.AddData[phi0nr].WannierCentre[1];
1218 Wcentre[2] = Lat->Psi.AddData[phi0nr].WannierCentre[2];
1219 // init pointers and values
1220 const int myPE = P->Par.me_comm_ST_Psi;
1221 const double FFTFactor = 1./LevS->MaxN; //
1222// double max[NDIM], max_psi[NDIM];
1223// double max_n[NDIM];
1224 int index[4];
1225// double smooth, wall[NDIM];
1226// for (g=0;g<NDIM;g++) {
1227// max[g] = 0.;
1228// max_psi[g] = 0.;
1229// max_n[g] = -1.;
1230// }
1231
1232 //fprintf(stderr,"(%i) Wannier[%i] (%2.13e, %2.13e, %2.13e)\n", P->Par.me, phi0nr, 10.-Wcentre[0], 10.-Wcentre[1], 10.-Wcentre[2]);
1233 for (g=0;g<4;g++)
1234 index[g] = cross(index_rxp,g);
1235
1236 // blow up source coefficients
1237 LockDensityArray(Dens0,Temp2Density,imag); // TempPsi
1238 LockDensityArray(Dens0,Temp2Density,real); // TempPsi2
1239 LockDensityArray(Dens0,ActualPsiDensity,imag); // PsiC
1240
1241 fft_Psi(P,source,TempPsiR ,index[1],7);
1242 fft_Psi(P,source,TempPsi2R,index[3],7);
1243
1244 //result = 0.;
1245 // for every point on the real grid multiply with component of position vector
1246 for (n0=0; n0<N0; n0++)
1247 for (n[1]=0; n[1]<N[1]; n[1]++)
1248 for (n[2]=0; n[2]<N[2]; n[2]++) {
1249 n[0] = n0 + N0 * myPE;
1250 fac[0] = (double)(n[0])/(double)((N[0]));
1251 fac[1] = (double)(n[1])/(double)((N[1]));
1252 fac[2] = (double)(n[2])/(double)((N[2]));
1253 RMat33Vec3(x,Lat->RealBasis,fac);
1254// fac[0] = (fac[0] > .9) ? fac[0]-0.9 : 0.;
1255// fac[1] = (fac[1] > .9) ? fac[1]-0.9 : 0.;
1256// fac[2] = (fac[2] > .9) ? fac[2]-0.9 : 0.;
1257// RMat33Vec3(wall,Lat->RealBasis,fac);
1258// smooth = exp(wall[0]*wall[0]+wall[1]*wall[1]+wall[2]*wall[2]); // smoothing near the borders of the virtual cell
1259 iS = n[2] + N[2]*(n[1] + N[1]*n0); // mind splitting of x axis due to multiple processes
1260 i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
1261
1262// if (fabs(truedist(Lat,x[index[1]],Wcentre[index[1]],index[1])) >= borderstart * sqrt(Lat->RealBasisSQ[index[1]])/2.)
1263// if (max[index[1]] < sawtooth(Lat,truedist(Lat,x[index[1]],Wcentre[index[1]],index[1]),index[1]) * TempPsiR [i0]) {
1264// max[index[1]] = sawtooth(Lat,truedist(Lat,x[index[1]],Wcentre[index[1]],index[1]),index[1]) * TempPsiR [i0];
1265// max_psi[index[1]] = TempPsiR [i0];
1266// max_n[index[1]] = truedist(Lat,x[index[1]],Wcentre[index[1]],index[1]);
1267// }
1268//
1269// if (fabs(truedist(Lat,x[index[3]],Wcentre[index[3]],index[3])) >= borderstart * sqrt(Lat->RealBasisSQ[index[3]])/2.)
1270// if (max[index[3]] < sawtooth(Lat,truedist(Lat,x[index[3]],Wcentre[index[3]],index[3]),index[3]) * TempPsiR [i0]) {
1271// max[index[3]] = sawtooth(Lat,truedist(Lat,x[index[3]],Wcentre[index[3]],index[3]),index[3]) * TempPsiR [i0];
1272// max_psi[index[3]] = TempPsiR [i0];
1273// max_n[index[3]] = truedist(Lat,x[index[3]],Wcentre[index[3]],index[3]);
1274// }
1275
1276 PsiCR[iS] = //vector * TempPsiR[i0];
1277 sawtooth(Lat,MinImageConv(Lat,x[index[0]],Wcentre[index[0]],index[0]),index[0]) * TempPsiR [i0]
1278 -sawtooth(Lat,MinImageConv(Lat,x[index[2]],Wcentre[index[2]],index[2]),index[2]) * TempPsi2R[i0];
1279// ShiftGaugeOrigin(P,truedist(Lat,x[index[0]],Wcentre[index[0]],index[0]),index[0]) * TempPsiR [i0]
1280// -ShiftGaugeOrigin(P,truedist(Lat,x[index[2]],Wcentre[index[2]],index[2]),index[2]) * TempPsi2R[i0];
1281// PsiCR[iS] = (x[index[0]] - Wcentre[index[0]]) * TempPsiR [i0] - (x[index[2]] - Wcentre[index[2]]) * TempPsi2R[i0];
1282 }
1283 //if (P->Par.me == 0) fprintf(stderr,"(%i) PerturbationOpertator_R(xP): %e\n",P->Par.me, Result/LevS->MaxN);
1284 UnLockDensityArray(Dens0,Temp2Density,imag); // TempPsi
1285 UnLockDensityArray(Dens0,Temp2Density,real); // TempPsi2
1286
1287// // print maximum values
1288// fprintf (stderr,"(%i) RxP: Maximum values = (",P->Par.me);
1289// for (g=0;g<NDIM;g++)
1290// fprintf(stderr,"%lg\t", max[g]);
1291// fprintf(stderr,"\b)\t(");
1292// for (g=0;g<NDIM;g++)
1293// fprintf(stderr,"%lg\t", max_psi[g]);
1294// fprintf(stderr,"\b)\t");
1295// fprintf (stderr,"at (");
1296// for (g=0;g<NDIM;g++)
1297// fprintf(stderr,"%lg\t", max_n[g]);
1298// fprintf(stderr,"\b)\n");
1299
1300 // inverse fourier transform
1301 //if (PsiC != Dens0->DensityCArray[ActualPsiDensity]) Error(SomeError,"CalculatePerturbationOperator_RxP: PsiC corrupted");
1302 fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, PsiC, workC);
1303
1304 // copy to destination array
1305 SetArrayToDouble0((double *)dest, 2*R->InitLevS->MaxG);
1306 for (g=0; g<LevS->MaxG; g++) {
1307 Index = LevS->GArray[g].Index;
1308 dest[g].re += ( PsiC[Index].re)*FFTFactor; // factor confirmed, see grad.c:CalculateConDirHConDir()
1309 dest[g].im += ( PsiC[Index].im)*FFTFactor;
1310 //fprintf(stderr,"(%i) PsiC[(%lg,%lg,%lg)] = %lg +i %lg\n", P->Par.me, LevS->GArray[g].G[0], LevS->GArray[g].G[1], LevS->GArray[g].G[2], dest[g].re, dest[g].im);
1311 }
1312 UnLockDensityArray(Dens0,ActualPsiDensity,imag); // PsiC
1313 //if (LevS->GArray[0].GSq == 0.)
1314 //dest[0].im = 0.; // don't do this, see ..._P()
1315}
1316
1317/** Applies perturbation operator \f$-(\nabla \times \widehat{r})_{index}\f$ to \a *source.
1318 * Is analogous to CalculatePerturbationOperator_RxP(), only the order is reversed, first position operator, then
1319 * momentum operator
1320 * \param *P Problem at hand
1321 * \param *source complex coefficients of wave function \f$\varphi(G)\f$
1322 * \param *dest returned complex coefficients of wave function \f$(\widehat{r} \times \widehat{p})_{index}|\varphi(G)\rangle\f$
1323 * \param phi0nr number within LocalPsi of the unperturbed pendant of the given perturbed wavefunction \a *source.
1324 * \param index_pxr index of position operator
1325 * \note Only third component is important due to initial rotiation of cell such that B field is aligned with z axis.
1326 * \sa CalculateConDirHConDir() - the procedure of fft and inverse fft is very similar.
1327 * \bug routine is not tested (but should work), as it offers no advantage over CalculatePerturbationOperator_RxP()
1328 */
1329void CalculatePerturbationOperator_PxR(struct Problem *P, const fftw_complex *source, fftw_complex *dest, const int phi0nr, const int index_pxr)
1330
1331{
1332 struct Lattice *Lat = &P->Lat;
1333 struct RunStruct *R = &P->R;
1334 struct LatticeLevel *Lev0 = R->Lev0;
1335 struct LatticeLevel *LevS = R->LevS;
1336 struct Density *Dens0 = Lev0->Dens;
1337 struct fft_plan_3d *plan = Lat->plan;
1338 fftw_complex *TempPsi = Dens0->DensityCArray[Temp2Density];
1339 fftw_real *TempPsiR = (fftw_real *) TempPsi;
1340 fftw_complex *workC = Dens0->DensityCArray[TempDensity];
1341 fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
1342 fftw_real *PsiCR = (fftw_real *) PsiC;
1343 fftw_complex *Psi2C = Dens0->DensityCArray[ActualDensity];
1344 fftw_real *Psi2CR = (fftw_real *) Psi2C;
1345 fftw_complex *tempdestRC = (fftw_complex *)Dens0->DensityArray[Temp2Density];
1346 fftw_complex *posfac, *destsnd, *destrcv;
1347 double x[NDIM], fac[NDIM], Wcentre[NDIM];
1348 int n[NDIM], n0, g, Index, pos, iS, i0;
1349 int N[NDIM], NUp[NDIM];
1350 const int N0 = LevS->Plan0.plan->local_nx;
1351 N[0] = LevS->Plan0.plan->N[0];
1352 N[1] = LevS->Plan0.plan->N[1];
1353 N[2] = LevS->Plan0.plan->N[2];
1354 NUp[0] = LevS->NUp[0];
1355 NUp[1] = LevS->NUp[1];
1356 NUp[2] = LevS->NUp[2];
1357 Wcentre[0] = Lat->Psi.AddData[phi0nr].WannierCentre[0];
1358 Wcentre[1] = Lat->Psi.AddData[phi0nr].WannierCentre[1];
1359 Wcentre[2] = Lat->Psi.AddData[phi0nr].WannierCentre[2];
1360 // init pointers and values
1361 const int myPE = P->Par.me_comm_ST_Psi;
1362 const double FFTFactor = 1./LevS->MaxN;
1363
1364 // blow up source coefficients
1365 SetArrayToDouble0((double *)tempdestRC ,Dens0->TotalSize*2);
1366 SetArrayToDouble0((double *)TempPsi ,Dens0->TotalSize*2);
1367 SetArrayToDouble0((double *)PsiC,Dens0->TotalSize*2);
1368 SetArrayToDouble0((double *)Psi2C,Dens0->TotalSize*2);
1369 for (g=0; g<LevS->MaxG; g++) {
1370 Index = LevS->GArray[g].Index;
1371 posfac = &LevS->PosFactorUp[LevS->MaxNUp*g];
1372 destrcv = &tempdestRC[LevS->MaxNUp*Index];
1373 for (pos=0; pos < LevS->MaxNUp; pos++) {
1374 destrcv [pos].re = (( source[g].re)*posfac[pos].re-( source[g].im)*posfac[pos].im);
1375 destrcv [pos].im = (( source[g].re)*posfac[pos].im+( source[g].im)*posfac[pos].re);
1376 }
1377 }
1378 for (g=0; g<LevS->MaxDoubleG; g++) {
1379 destsnd = &tempdestRC [LevS->DoubleG[2*g]*LevS->MaxNUp];
1380 destrcv = &tempdestRC [LevS->DoubleG[2*g+1]*LevS->MaxNUp];
1381 for (pos=0; pos<LevS->MaxNUp; pos++) {
1382 destrcv [pos].re = destsnd [pos].re;
1383 destrcv [pos].im = -destsnd [pos].im;
1384 }
1385 }
1386 // fourier transform blown up wave function
1387 fft_3d_complex_to_real(plan,LevS->LevelNo, FFTNFUp, tempdestRC , workC);
1388 DensityRTransformPos(LevS,(fftw_real*)tempdestRC ,TempPsiR );
1389
1390 //fft_Psi(P,source,TempPsiR ,cross(index_pxr,1),7);
1391 //fft_Psi(P,source,TempPsi2R,cross(index_pxr,3),7);
1392
1393 //result = 0.;
1394 // for every point on the real grid multiply with component of position vector
1395 for (n0=0; n0<N0; n0++)
1396 for (n[1]=0; n[1]<N[1]; n[1]++)
1397 for (n[2]=0; n[2]<N[2]; n[2]++) {
1398 n[0] = n0 + N0 * myPE;
1399 fac[0] = (double)(n[0])/(double)((N[0]));
1400 fac[1] = (double)(n[1])/(double)((N[1]));
1401 fac[2] = (double)(n[2])/(double)((N[2]));
1402 RMat33Vec3(x,Lat->RealBasis,fac);
1403 iS = n[2] + N[2]*(n[1] + N[1]*n0); // mind splitting of x axis due to multiple processes
1404 i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
1405// PsiCR[iS] = sawtooth(Lat,truedist(Lat,x[cross(index_pxr,1)],Wcentre[cross(index_pxr,1)],cross(index_pxr,1)),cross(index_pxr,1)) * TempPsiR[i0];
1406// Psi2CR[iS] = sawtooth(Lat,truedist(Lat,x[cross(index_pxr,3)],Wcentre[cross(index_pxr,3)],cross(index_pxr,3)),cross(index_pxr,3)) * TempPsiR[i0];
1407 PsiCR[iS] = ShiftGaugeOrigin(P,MinImageConv(Lat,x[cross(index_pxr,1)],Wcentre[cross(index_pxr,1)],cross(index_pxr,1)),cross(index_pxr,1)) * TempPsiR[i0];
1408 Psi2CR[iS] = ShiftGaugeOrigin(P,MinImageConv(Lat,x[cross(index_pxr,3)],Wcentre[cross(index_pxr,3)],cross(index_pxr,3)),cross(index_pxr,3)) * TempPsiR[i0];
1409 }
1410
1411 // inverse fourier transform
1412 fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, PsiC, workC);
1413 fft_3d_real_to_complex(plan,LevS->LevelNo, FFTNF1, Psi2C, workC);
1414
1415 // copy to destination array
1416 for (g=0; g<LevS->MaxG; g++) {
1417 Index = LevS->GArray[g].Index;
1418 dest[g].re = -LevS->GArray[g].G[cross(index_pxr,0)]*( PsiC[Index].im)*FFTFactor;
1419 dest[g].im = -LevS->GArray[g].G[cross(index_pxr,0)]*(-PsiC[Index].re)*FFTFactor;
1420 dest[g].re -= -LevS->GArray[g].G[cross(index_pxr,2)]*( Psi2C[Index].im)*FFTFactor;
1421 dest[g].im -= -LevS->GArray[g].G[cross(index_pxr,2)]*(-Psi2C[Index].re)*FFTFactor;
1422 }
1423 if (LevS->GArray[0].GSq == 0.)
1424 dest[0].im = 0.; // don't do this, see ..._P()
1425}
1426
1427/** Evaluates first derivative of perturbed energy functional with respect to minimisation parameter \f$\Theta\f$.
1428 * \f[
1429 * \frac{\delta {\cal E}^{(2)}} {\delta \Theta} =
1430 * 2 {\cal R} \langle \widetilde{\varphi}_i^{(1)} | {\cal H}^{(0)} | \varphi_i^{(1)} \rangle
1431 * - \sum_l \lambda_{il} \langle \widetilde{\varphi}_i^{(1)} | \varphi_l^{(1)} \rangle
1432 * - \sum_k \lambda_{ki} \langle \varphi_k^{(1)} | \widetilde{\varphi}_i^{(1)} \rangle
1433 * + 2 {\cal R} \langle \widetilde{\varphi}_i^{(1)} | {\cal H}^{(1)} | \varphi_i^{(0)} \rangle
1434 * \f]
1435 *
1436 * The summation over all Psis has again to be done with an MPI exchange of non-local coefficients, as the conjugate
1437 * directions are not the same in situations where PePGamma > 1 (Psis split up among processes = multiple minimisation)
1438 * \param *P Problem at hand
1439 * \param source0 unperturbed wave function \f$\varphi_l^{(0)}\f$
1440 * \param source perturbed wave function \f$\varphi_l^{(1)} (G)\f$
1441 * \param ConDir normalized conjugate direction \f$\widetilde{\varphi}_l^{(1)} (G)\f$
1442 * \param Hc_grad complex coefficients of \f$H^{(0)} | \varphi_l^{(1)} (G) \rangle\f$, see GradientArray#HcGradient
1443 * \param H1c_grad complex coefficients of \f$H^{(1)} | \varphi_l^{(0)} (G) \rangle\f$, see GradientArray#H1cGradient
1444 * \sa CalculateLineSearch() - used there, \sa CalculateConDirHConDir() - same principles
1445 * \warning The MPI_Allreduce for the scalar product in the end has not been done and must not have been done for given
1446 * parameters yet!
1447 */
1448double Calculate1stPerturbedDerivative(struct Problem *P, const fftw_complex *source0, const fftw_complex *source, const fftw_complex *ConDir, const fftw_complex *Hc_grad, const fftw_complex *H1c_grad)
1449{
1450 struct RunStruct *R = &P->R;
1451 struct Psis *Psi = &P->Lat.Psi;
1452 struct LatticeLevel *LevS = R->LevS;
1453 double result = 0., E0 = 0., Elambda = 0., E1 = 0.;//, E2 = 0.;
1454 int i,m,j;
1455 const int state = R->CurrentMin;
1456 //const int l_normal = R->ActualLocalPsiNo - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[Occupied];
1457 const int ActNum = R->ActualLocalPsiNo - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[1] * Psi->LocalPsiStatus[R->ActualLocalPsiNo].my_color_comm_ST_Psi;
1458 //int l = R->ActualLocalPsiNo;
1459 //int l_normal = Psi->TypeStartIndex[Occupied] + (l - Psi->TypeStartIndex[state]); // offset l to \varphi_l^{(0)}
1460 struct OnePsiElement *OnePsiB, *LOnePsiB;
1461 //fftw_complex *HConGrad = LevS->LPsi->TempPsi;
1462 fftw_complex *LPsiDatB=NULL;
1463 const int ElementSize = (sizeof(fftw_complex) / sizeof(double));
1464 int RecvSource;
1465 MPI_Status status;
1466
1467 //CalculateCDfnl(P,ConDir,PP->CDfnl);
1468 //ApplyTotalHamiltonian(P,ConDir,HConDir, PP->CDfnl, 1, 0);
1469 //E0 = (GradSP(P, LevS, ConDir, Hc_grad) + GradSP(P, LevS, source, HConDir)) * Psi->LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor;
1470 E0 = 2.*GradSP(P, LevS, ConDir, Hc_grad) * Psi->LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor;
1471 result = E0;
1472 //fprintf(stderr,"(%i) 1st: E0 = \t\t%lg\n", P->Par.me, E0);
1473
1474 m = -1;
1475 for (j=0; j < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; j++) { // go through all wave functions
1476 OnePsiB = &Psi->AllPsiStatus[j]; // grab OnePsiB
1477 if (OnePsiB->PsiType == state) { // drop all but the ones of current min state
1478 m++; // increase m if it is type-specific wave function
1479 if (OnePsiB->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
1480 LOnePsiB = &Psi->LocalPsiStatus[OnePsiB->MyLocalNo];
1481 else
1482 LOnePsiB = NULL;
1483 if (LOnePsiB == NULL) { // if it's not local ... receive it from respective process into TempPsi
1484 RecvSource = OnePsiB->my_color_comm_ST_Psi;
1485 MPI_Recv( LevS->LPsi->TempPsi, LevS->MaxG*ElementSize, MPI_DOUBLE, RecvSource, PerturbedTag, P->Par.comm_ST_PsiT, &status );
1486 LPsiDatB=LevS->LPsi->TempPsi;
1487 } else { // .. otherwise send it to all other processes (Max_me... - 1)
1488 for (i=0;i<P->Par.Max_me_comm_ST_PsiT;i++)
1489 if (i != OnePsiB->my_color_comm_ST_Psi)
1490 MPI_Send( LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo], LevS->MaxG*ElementSize, MPI_DOUBLE, i, PerturbedTag, P->Par.comm_ST_PsiT);
1491 LPsiDatB=LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo];
1492 } // LPsiDatB is now set to the coefficients of OnePsi either stored or MPI_Received
1493
1494 Elambda -= 2.*Psi->lambda[ActNum][m]*GradSP(P, LevS, ConDir, LPsiDatB) * OnePsiB->PsiFactor; // lambda is symmetric
1495 }
1496 }
1497 result += Elambda;
1498 //fprintf(stderr,"(%i) 1st: Elambda = \t%lg\n", P->Par.me, Elambda);
1499
1500 E1 = 2.*GradSP(P,LevS,ConDir,H1c_grad) * sqrt(Psi->AllPsiStatus[ActNum].PsiFactor*Psi->LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor);
1501 result += E1;
1502 //fprintf(stderr,"(%i) 1st: E1 = \t\t%lg\n", P->Par.me, E1);
1503
1504 return result;
1505}
1506
1507
1508/** Evaluates second derivative of perturbed energy functional with respect to minimisation parameter \f$\Theta\f$.
1509 * \f[
1510 * \frac{\delta^2 {\cal E}^{(2)}} {\delta \Theta^2} =
1511 * 2 \bigl( \langle \widetilde{\varphi}_l^{(1)} | {\cal H}^{(0)} | \widetilde{\varphi}_l^{(1)} \rangle
1512 * - \langle \varphi_l^{(1)} | {\cal H}^{(0)} | \varphi_l^{(1)} \rangle \bigr )
1513 * + 2 \sum_{i,i \neq l } \lambda_{il} \langle \varphi_i^{(1)} | \varphi_l^{(1)} \rangle
1514 * - 2 {\cal R} \langle \varphi_l^{(1)} | {\cal H}^{(1)} | \varphi_l^{(0)} \rangle
1515 * \f]
1516 *
1517 * The energy eigenvalues of \a ConDir and \a source must be supplied, they can be calculated via CalculateConDirHConDir() and/or
1518 * by the due to CalculatePerturbedEnergy() already present OnePsiElementAddData#Lambda eigenvalue. The summation over the
1519 * unperturbed lambda within the scalar product of perturbed wave functions is evaluated with Psis#lambda and Psis#Overlap.
1520 * Afterwards, the ConDir density is calculated and also the i-th perturbed density to first degree. With these in a sum over
1521 * all real mesh points the exchange-correlation first and second derivatives and also the Hartree potential ones can be calculated
1522 * and summed up.
1523 * \param *P Problem at hand
1524 * \param source0 unperturbed wave function \f$\varphi_l^{(0)}\f$
1525 * \param source wave function \f$\varphi_l^{(1)}\f$
1526 * \param ConDir conjugated direction \f$\widetilde{\varphi}_l^{(1)}\f$
1527 * \param sourceHsource eigenvalue of wave function \f$\langle \varphi_l^{(1)} | H^{(0)} | \varphi_l^{(1)}\rangle\f$
1528 * \param ConDirHConDir perturbed eigenvalue of conjugate direction \f$\langle \widetilde{\varphi}_l^{(1)} | H^{(0)} | \widetilde{\varphi}_l^{(1)}\rangle\f$
1529 * \param ConDirConDir norm of conjugate direction \f$\langle \widetilde{\varphi}_l^{(1)} | \widetilde{\varphi}_l^{(1)}\rangle\f$
1530 * \warning No MPI_AllReduce() takes place, parameters have to be reduced already.
1531 */
1532double Calculate2ndPerturbedDerivative(struct Problem *P, const fftw_complex *source0,const fftw_complex *source, const fftw_complex *ConDir,const double sourceHsource, const double ConDirHConDir, const double ConDirConDir)
1533{
1534 struct RunStruct *R = &P->R;
1535 struct Psis *Psi = &P->Lat.Psi;
1536 //struct Lattice *Lat = &P->Lat;
1537 //struct Energy *E = Lat->E;
1538 double result = 0.;
1539 double Con0 = 0., Elambda = 0.;//, E0 = 0., E1 = 0.;
1540 //int i;
1541 const int state = R->CurrentMin;
1542 //const int l_normal = R->ActualLocalPsiNo - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[Occupied];
1543 const int ActNum = R->ActualLocalPsiNo - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[1] * Psi->LocalPsiStatus[R->ActualLocalPsiNo].my_color_comm_ST_Psi;
1544
1545 Con0 = 2.*ConDirHConDir;
1546 result += Con0;
1547 ////E0 = -2.*sourceHsource;
1548 ////result += E0;
1549 ////E1 = -E->PsiEnergy[Perturbed1_0Energy][R->ActualLocalPsiNo] - E->PsiEnergy[Perturbed0_1Energy][R->ActualLocalPsiNo];
1550 ////result += E1;
1551 //fprintf(stderr,"(%i) 2nd: E1 = \t%lg\n", P->Par.me, E1);
1552
1553 ////for (i=0;i<Lat->Psi.NoOfPsis;i++) {
1554 //// if (i != ActNum) Elambda += Psi->lambda[i][ActNum]*Psi->Overlap[i][ActNum]+ Psi->lambda[ActNum][i]*Psi->Overlap[ActNum][i]; // overlap contains PsiFactor
1555 ////}
1556 ////Elambda = Psi->lambda[ActNum][ActNum]*Psi->Overlap[ActNum][ActNum];
1557 Elambda = 2.*Psi->lambda[ActNum][ActNum]*ConDirConDir;
1558 result -= Elambda;
1559
1560 //fprintf(stderr,"(%i) 2ndPerturbedDerivative: Result = Con0 + E0 + E1 + Elambda + dEdt0_XC + ddEddt0_XC + dEdt0_H + ddEddt0_H = %lg + %lg + %lg + %lg + %lg + %lg + %lg + %lg = %lg\n", P->Par.me, Con0, E0, E1, Elambda, VolumeFactorR*dEdt0_XC, VolumeFactorR*ddEddt0_XC, dEdt0_H, ddEddt0_H, result);
1561
1562 return (result);
1563}
1564
1565/** Returns index of specific component in 3x3 cross product.
1566 * \param i vector product component index, ranging from 0..NDIM
1567 * \param j index specifies which one of the four vectors in x*y - y*x, ranging from 0..3 (0,1 positive sign, 2,3 negative sign)
1568 * \return Component 0..2 of vector to be taken to evaluate a vector product
1569 * \sa crossed() - is the same but vice versa, return value must be specified, \a i is returned.
1570 */
1571inline int cross(int i, int j)
1572{
1573 const int matrix[NDIM*4] = {1,2,2,1,2,0,0,2,0,1,1,0};
1574 if (i>=0 && i<NDIM && j>=0 && j<4)
1575 return (matrix[i*4+j]);
1576 else {
1577 Error(SomeError,"cross: i or j out of range!");
1578 return (0);
1579 }
1580}
1581
1582/** Returns index of resulting vector component in 3x3 cross product.
1583 * In the column specified by the \a j index \a i is looked for and the found row index returned.
1584 * \param i vector component index, ranging from 0..NDIM
1585 * \param j index specifies which one of the four vectors in x*y - y*x, ranging from 0..3 (0,1 positive sign, 2,3 negative sign)
1586 * \return Component 0..2 of resulting vector
1587 * \sa cross() - is the same but vice versa, return value must be specified, \a i is returned.
1588 */
1589inline int crossed(int i, int j)
1590{
1591 const int matrix[NDIM*4] = {1,2,2,1,2,0,0,2,0,1,1,0};
1592 int k;
1593 if (i>=0 && i<NDIM && j>=0 && j<4) {
1594 for (k=0;k<NDIM;k++)
1595 if (matrix[4*k+j] == i) return(k);
1596 Error(SomeError,"crossed: given component not found!");
1597 return(-1);
1598 } else {
1599 Error(SomeError,"crossed: i or j out of range!");
1600 return (-1);
1601 }
1602}
1603
1604#define Nsin 16 //!< should be dependent on MaxG/MaxN per axis!
1605
1606/** Returns sawtooth shaped profile for position operator within cell.
1607 * This is a mapping from -L/2...L/2 (L = length of unit cell derived from Lattice#RealBasisSQ) to -L/2 to L/2 with a smooth transition:
1608 * \f[
1609 * f(x): x \rightarrow \left \{
1610 * \begin{array}{l}
1611 * -\frac{L}{2} \cdot \sin \left ( \frac{x}{0,05\cdot L} \cdot \frac{\pi}{2} \right ), 0<x<0,05\cdot L \\
1612 * (x - 0,05\cdot L) \cdot \frac{10}{9} - \frac{L}{2}, 0,05\cdot L \leq x<0,95\cdot L \\
1613 * \frac{L}{2} \cdot \cos \left ( \frac{x-0,95\cdot L}{0,05\cdot L} \cdot \frac{\pi}{2} \right), 0,95\cdot L<x<L
1614 * \end{array} \right \}
1615 * \f]
1616 * \param *Lat pointer to Lattice structure for Lattice#RealBasisSQ
1617 * \param L parameter x
1618 * \param index component index for Lattice#RealBasisSQ
1619 */
1620inline double sawtooth(struct Lattice *Lat, double L, const int index)
1621{
1622 double axis = sqrt(Lat->RealBasisSQ[index]);
1623 double sawstart = Lat->SawtoothStart;
1624 double sawend = 1. - sawstart;
1625 double sawfactor = (sawstart+sawend)/(sawend-sawstart);
1626 //return(L);
1627
1628 //fprintf(stderr, "sawstart: %e\tsawend: %e\tsawfactor: %e\tL: %e\n", sawstart, sawend, sawfactor, L);
1629 // transform and return (sawtooth profile checked, 04.08.06)
1630 L += axis/2.; // transform to 0 ... L
1631 if (L < (sawstart*axis)) return (-axis/(2*sawfactor)*sin(L/(sawstart*axis)*PI/2.)); // first smooth transition from 0 ... -L/2
1632 if (L > (sawend*axis)) return ( axis/(2*sawfactor)*cos((L-sawend*axis)/(sawstart*axis)*PI/2.)); // second smooth transition from +L/2 ... 0
1633 //fprintf(stderr,"L %e\t sawstart %e\t sawend %e\t sawfactor %e\t axis%e\n", L, sawstart, sawend, sawfactor, axis);
1634 //return ((L - sawstart*axis) - axis/(2*sawfactor)); // area in between scale to -L/2 ... +L/2
1635 return (L - axis/2); // area in between return as it was
1636}
1637
1638/** Shifts the origin of the gauge according to the CSDGT method.
1639 * \f[
1640 * d(r) = r - \sum_{I_s,I_a} (r-R_{I_s,I_a}) exp{(-\alpha_{I_s,I_a}(r-R_{I_s,I_a})^4)}
1641 * \f]
1642 * This trafo is necessary as the current otherweise (CSGT) sensitively depends on the current around
1643 * the core region inadequately/only moderately well approximated by a plane-wave-pseudo-potential-method.
1644 * \param *P Problem at hand, containing Lattice and Ions
1645 * \param r parameter r
1646 * \param index index of the basis vector
1647 * \return \f$d(r)\f$
1648 * \note Continuous Set of Damped Gauge Transformations according to Keith and Bader
1649 */
1650inline double ShiftGaugeOrigin(struct Problem *P, double r, const int index)
1651{
1652 struct Ions *I = &P->Ion;
1653 struct Lattice *Lat = &P->Lat;
1654 double x, tmp;
1655 int is,ia;
1656
1657 // loop over all ions to calculate the sum
1658 x = r;
1659 for (is=0; is < I->Max_Types; is++)
1660 for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
1661 tmp = (r - I->I[is].R[NDIM*ia]);
1662 x -= tmp*exp(- I->I[is].alpha[ia] * tpow(tmp,4));
1663 }
1664
1665 return(sawtooth(Lat,x,index)); // still use sawtooth due to the numerical instability around the border region of the cell
1666}
1667
1668/** Print sawtooth() for each node along one axis.
1669 * \param *P Problem at hand, containing RunStruct, Lattice and LatticeLevel RunStruct#LevS
1670 * \param index index of axis
1671 */
1672void TestSawtooth(struct Problem *P, const int index)
1673{
1674 struct RunStruct *R = &P->R;
1675 struct LatticeLevel *LevS = R->LevS;
1676 struct Lattice *Lat =&P->Lat;
1677 double x;
1678 int n;
1679 int N[NDIM];
1680 N[0] = LevS->Plan0.plan->N[0];
1681 N[1] = LevS->Plan0.plan->N[1];
1682 N[2] = LevS->Plan0.plan->N[2];
1683
1684 for (n=0;n<N[index];n++) {
1685 x = (double)n/(double)N[index] * sqrt(Lat->RealBasisSQ[index]);
1686 //fprintf(stderr,"(%i) x %e\t Axis/2 %e\n",P->Par.me, x, sqrt(Lat->RealBasisSQ[index])/2. );
1687 x = MinImageConv(Lat, x, sqrt(Lat->RealBasisSQ[index])/2., index);
1688 fprintf(stderr,"%e\t%e\n", x, sawtooth(Lat,x,index));
1689 }
1690}
1691
1692/** Secures minimum image convention between two given points \a R[] and \a r[] within periodic boundary.
1693 * Each distance component within a periodic boundary must always be between -L/2 ... L/2
1694 * \param *Lat pointer to Lattice structure
1695 * \param R[] first vector, NDIM, each must be between 0...L
1696 * \param r[] second vector, NDIM, each must be between 0...L
1697 * \param index of component
1698 * \return component between -L/2 ... L/2
1699 */
1700inline double MinImageConv(struct Lattice *Lat, const double R, const double r, const int index)
1701{
1702 double axis = sqrt(Lat->RealBasisSQ[index]);
1703 double result = 0.;
1704
1705 if (fabs(result = R - r + axis) < axis/2.) { }
1706 else if (fabs(result = R - r) <= axis/2.) { }
1707 else if (fabs(result = R - r - axis) < axis/2.) { }
1708 else Error(SomeError, "MinImageConv: None of the three cases applied!");
1709 return (result);
1710}
1711
1712
1713/** Fouriertransforms given \a source.
1714 * By the use of the symmetry parameter an additional imaginary unit and/or the momentum operator can
1715 * be applied at the same time.
1716 * \param *P Problem at hand
1717 * \param *Psi source array of reciprocal coefficients
1718 * \param *PsiR destination array, becoming filled with real coefficients
1719 * \param index_g component of G vector (only needed for symmetry=4..7)
1720 * \param symmetry 0 - do nothing, 1 - factor by "-1", 2 - factor by "i", 3 - factor by "1/i = -i", from 4 to 7 the same
1721 * but additionally with momentum operator
1722 */
1723void fft_Psi(struct Problem *P, const fftw_complex *Psi, fftw_real *PsiR, const int index_g, const int symmetry)
1724{
1725 struct Lattice *Lat = &P->Lat;
1726 struct RunStruct *R = &P->R;
1727 struct LatticeLevel *Lev0 = R->Lev0;
1728 struct LatticeLevel *LevS = R->LevS;
1729 struct Density *Dens0 = Lev0->Dens;
1730 struct fft_plan_3d *plan = Lat->plan;
1731 fftw_complex *tempdestRC = (fftw_complex *)Dens0->DensityArray[TempDensity];
1732 fftw_complex *work = Dens0->DensityCArray[TempDensity];
1733 fftw_complex *posfac, *destpos, *destRCS, *destRCD;
1734 int i, Index, pos;
1735
1736 LockDensityArray(Dens0,TempDensity,imag); // tempdestRC
1737 SetArrayToDouble0((double *)tempdestRC, Dens0->TotalSize*2);
1738 SetArrayToDouble0((double *)PsiR, Dens0->TotalSize*2);
1739 switch (symmetry) {
1740 case 0:
1741 for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is positive
1742 Index = LevS->GArray[i].Index;
1743 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
1744 destpos = &tempdestRC[LevS->MaxNUp*Index];
1745 for (pos=0; pos < LevS->MaxNUp; pos++) {
1746 //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
1747 destpos[pos].re = (Psi[i].re)*posfac[pos].re-(Psi[i].im)*posfac[pos].im;
1748 destpos[pos].im = (Psi[i].re)*posfac[pos].im+(Psi[i].im)*posfac[pos].re;
1749 }
1750 }
1751 break;
1752 case 1:
1753 for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is - positive
1754 Index = LevS->GArray[i].Index;
1755 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
1756 destpos = &tempdestRC[LevS->MaxNUp*Index];
1757 for (pos=0; pos < LevS->MaxNUp; pos++) {
1758 //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
1759 destpos[pos].re = -((Psi[i].re)*posfac[pos].re-(Psi[i].im)*posfac[pos].im);
1760 destpos[pos].im = -((Psi[i].re)*posfac[pos].im+(Psi[i].im)*posfac[pos].re);
1761 }
1762 }
1763 break;
1764 case 2:
1765 for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is negative
1766 Index = LevS->GArray[i].Index;
1767 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
1768 destpos = &tempdestRC[LevS->MaxNUp*Index];
1769 for (pos=0; pos < LevS->MaxNUp; pos++) {
1770 //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
1771 destpos[pos].re = (-Psi[i].im)*posfac[pos].re-(Psi[i].re)*posfac[pos].im;
1772 destpos[pos].im = (-Psi[i].im)*posfac[pos].im+(Psi[i].re)*posfac[pos].re;
1773 }
1774 }
1775 break;
1776 case 3:
1777 for (i=0;i<LevS->MaxG;i++) { // incoming is negative, outgoing is positive
1778 Index = LevS->GArray[i].Index;
1779 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
1780 destpos = &tempdestRC[LevS->MaxNUp*Index];
1781 for (pos=0; pos < LevS->MaxNUp; pos++) {
1782 //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
1783 destpos[pos].re = (Psi[i].im)*posfac[pos].re-(-Psi[i].re)*posfac[pos].im;
1784 destpos[pos].im = (Psi[i].im)*posfac[pos].im+(-Psi[i].re)*posfac[pos].re;
1785 }
1786 }
1787 break;
1788 case 4:
1789 for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is positive
1790 Index = LevS->GArray[i].Index;
1791 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
1792 destpos = &tempdestRC[LevS->MaxNUp*Index];
1793 for (pos=0; pos < LevS->MaxNUp; pos++) {
1794 //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
1795 destpos[pos].re = LevS->GArray[i].G[index_g]*((Psi[i].re)*posfac[pos].re-(Psi[i].im)*posfac[pos].im);
1796 destpos[pos].im = LevS->GArray[i].G[index_g]*((Psi[i].re)*posfac[pos].im+(Psi[i].im)*posfac[pos].re);
1797 }
1798 }
1799 break;
1800 case 5:
1801 for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is - positive
1802 Index = LevS->GArray[i].Index;
1803 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
1804 destpos = &tempdestRC[LevS->MaxNUp*Index];
1805 for (pos=0; pos < LevS->MaxNUp; pos++) {
1806 //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
1807 destpos[pos].re = -LevS->GArray[i].G[index_g]*((Psi[i].re)*posfac[pos].re-(Psi[i].im)*posfac[pos].im);
1808 destpos[pos].im = -LevS->GArray[i].G[index_g]*((Psi[i].re)*posfac[pos].im+(Psi[i].im)*posfac[pos].re);
1809 }
1810 }
1811 break;
1812 case 6:
1813 for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is negative
1814 Index = LevS->GArray[i].Index;
1815 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
1816 destpos = &tempdestRC[LevS->MaxNUp*Index];
1817 for (pos=0; pos < LevS->MaxNUp; pos++) {
1818 //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
1819 destpos[pos].re = LevS->GArray[i].G[index_g]*((-Psi[i].im)*posfac[pos].re-(Psi[i].re)*posfac[pos].im);
1820 destpos[pos].im = LevS->GArray[i].G[index_g]*((-Psi[i].im)*posfac[pos].im+(Psi[i].re)*posfac[pos].re);
1821 }
1822 }
1823 break;
1824 case 7:
1825 for (i=0;i<LevS->MaxG;i++) { // incoming is negative, outgoing is positive
1826 Index = LevS->GArray[i].Index;
1827 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
1828 destpos = &tempdestRC[LevS->MaxNUp*Index];
1829 for (pos=0; pos < LevS->MaxNUp; pos++) {
1830 //if (destpos != &tempdestRC[LevS->MaxNUp*Index] || LevS->MaxNUp*Index+pos<0 || LevS->MaxNUp*Index+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destpos corrupted");
1831 destpos[pos].re = LevS->GArray[i].G[index_g]*((Psi[i].im)*posfac[pos].re-(-Psi[i].re)*posfac[pos].im);
1832 destpos[pos].im = LevS->GArray[i].G[index_g]*((Psi[i].im)*posfac[pos].im+(-Psi[i].re)*posfac[pos].re);
1833 }
1834 }
1835 break;
1836 }
1837 for (i=0; i<LevS->MaxDoubleG; i++) {
1838 destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
1839 destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
1840 for (pos=0; pos < LevS->MaxNUp; pos++) {
1841 //if (destRCD != &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp] || LevS->DoubleG[2*i+1]*LevS->MaxNUp+pos<0 || LevS->DoubleG[2*i+1]*LevS->MaxNUp+pos>=Dens0->TotalSize) Error(SomeError,"fft_Psi: destRCD corrupted");
1842 destRCD[pos].re = destRCS[pos].re;
1843 destRCD[pos].im = -destRCS[pos].im;
1844 }
1845 }
1846 fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
1847 DensityRTransformPos(LevS,(fftw_real*)tempdestRC, PsiR);
1848 UnLockDensityArray(Dens0,TempDensity,imag); // tempdestRC
1849}
1850
1851/** Locks all NDIM_NDIM current density arrays
1852 * \param Dens0 Density structure to be locked (in the current parts)
1853 */
1854void AllocCurrentDensity(struct Density *Dens0) {
1855 // real
1856 LockDensityArray(Dens0,CurrentDensity0,real); // CurrentDensity[B_index]
1857 LockDensityArray(Dens0,CurrentDensity1,real); // CurrentDensity[B_index]
1858 LockDensityArray(Dens0,CurrentDensity2,real); // CurrentDensity[B_index]
1859 LockDensityArray(Dens0,CurrentDensity3,real); // CurrentDensity[B_index]
1860 LockDensityArray(Dens0,CurrentDensity4,real); // CurrentDensity[B_index]
1861 LockDensityArray(Dens0,CurrentDensity5,real); // CurrentDensity[B_index]
1862 LockDensityArray(Dens0,CurrentDensity6,real); // CurrentDensity[B_index]
1863 LockDensityArray(Dens0,CurrentDensity7,real); // CurrentDensity[B_index]
1864 LockDensityArray(Dens0,CurrentDensity8,real); // CurrentDensity[B_index]
1865 // imaginary
1866 LockDensityArray(Dens0,CurrentDensity0,imag); // CurrentDensity[B_index]
1867 LockDensityArray(Dens0,CurrentDensity1,imag); // CurrentDensity[B_index]
1868 LockDensityArray(Dens0,CurrentDensity2,imag); // CurrentDensity[B_index]
1869 LockDensityArray(Dens0,CurrentDensity3,imag); // CurrentDensity[B_index]
1870 LockDensityArray(Dens0,CurrentDensity4,imag); // CurrentDensity[B_index]
1871 LockDensityArray(Dens0,CurrentDensity5,imag); // CurrentDensity[B_index]
1872 LockDensityArray(Dens0,CurrentDensity6,imag); // CurrentDensity[B_index]
1873 LockDensityArray(Dens0,CurrentDensity7,imag); // CurrentDensity[B_index]
1874 LockDensityArray(Dens0,CurrentDensity8,imag); // CurrentDensity[B_index]
1875}
1876
1877/** Reset and unlocks all NDIM_NDIM current density arrays
1878 * \param Dens0 Density structure to be unlocked/resetted (in the current parts)
1879 */
1880void DisAllocCurrentDensity(struct Density *Dens0) {
1881 //int i;
1882 // real
1883// for(i=0;i<NDIM*NDIM;i++)
1884// SetArrayToDouble0((double *)Dens0->DensityArray[i], Dens0->TotalSize*2);
1885 UnLockDensityArray(Dens0,CurrentDensity0,real); // CurrentDensity[B_index]
1886 UnLockDensityArray(Dens0,CurrentDensity1,real); // CurrentDensity[B_index]
1887 UnLockDensityArray(Dens0,CurrentDensity2,real); // CurrentDensity[B_index]
1888 UnLockDensityArray(Dens0,CurrentDensity3,real); // CurrentDensity[B_index]
1889 UnLockDensityArray(Dens0,CurrentDensity4,real); // CurrentDensity[B_index]
1890 UnLockDensityArray(Dens0,CurrentDensity5,real); // CurrentDensity[B_index]
1891 UnLockDensityArray(Dens0,CurrentDensity6,real); // CurrentDensity[B_index]
1892 UnLockDensityArray(Dens0,CurrentDensity7,real); // CurrentDensity[B_index]
1893 UnLockDensityArray(Dens0,CurrentDensity8,real); // CurrentDensity[B_index]
1894 // imaginary
1895// for(i=0;i<NDIM*NDIM;i++)
1896// SetArrayToDouble0((double *)Dens0->DensityCArray[i], Dens0->TotalSize*2);
1897 UnLockDensityArray(Dens0,CurrentDensity0,imag); // CurrentDensity[B_index]
1898 UnLockDensityArray(Dens0,CurrentDensity1,imag); // CurrentDensity[B_index]
1899 UnLockDensityArray(Dens0,CurrentDensity2,imag); // CurrentDensity[B_index]
1900 UnLockDensityArray(Dens0,CurrentDensity3,imag); // CurrentDensity[B_index]
1901 UnLockDensityArray(Dens0,CurrentDensity4,imag); // CurrentDensity[B_index]
1902 UnLockDensityArray(Dens0,CurrentDensity5,imag); // CurrentDensity[B_index]
1903 UnLockDensityArray(Dens0,CurrentDensity6,imag); // CurrentDensity[B_index]
1904 UnLockDensityArray(Dens0,CurrentDensity7,imag); // CurrentDensity[B_index]
1905 UnLockDensityArray(Dens0,CurrentDensity8,imag); // CurrentDensity[B_index]
1906}
1907
1908// these defines safe-guard same symmetry for same kind of wave function
1909#define Psi0symmetry 0 // //0 //0 //0 // regard psi0 as real
1910#define Psi1symmetry 0 // //3 //0 //0 // regard psi0 as real
1911#define Psip0symmetry 6 //6 //6 //6 //6 // momentum times "i" due to operation on left hand
1912#define Psip1symmetry 7 //7 //4 //6 //7 // momentum times "-i" as usual (right hand)
1913
1914/** Evaluates the 3x3 current density arrays.
1915 * The formula we want to evaluate is as follows
1916 * \f[
1917 * j_k(r) = \langle \psi_k^{(0)} | \Bigl ( p|r'\rangle\langle r' | + | r' \rangle \langle r' | p \Bigr )
1918 \Bigl [ | \psi_k^{(r\times p )} \rangle - r' \times | \psi_k^{(p)} \rangle \Bigr ] \cdot B.
1919 * \f]
1920 * Most of the DensityTypes-arrays are locked for temporary use. Pointers are set to their
1921 * start address and afterwards the current density arrays locked and reset'ed. Then for every
1922 * unperturbed wave function we do:
1923 * -# FFT unperturbed p-perturbed and rxp-perturbed wave function
1924 * -# FFT wave function with applied momentum operator for all three indices
1925 * -# For each index of the momentum operator:
1926 * -# FFT p-perturbed wave function
1927 * -# For every index of the external field:
1928 * -# FFT rxp-perturbed wave function
1929 * -# Evaluate current density for these momentum index and external field indices
1930 *
1931 * Afterwards the temporary densities are unlocked and the density ones gathered from all Psi-
1932 * sharing processes.
1933 *
1934 * \param *P Problem at hand, containing Lattice and RunStruct
1935 */
1936void FillCurrentDensity(struct Problem *P)
1937{
1938 struct Lattice *Lat = &P->Lat;
1939 struct RunStruct *R = &P->R;
1940 struct Psis *Psi = &Lat->Psi;
1941 struct LatticeLevel *LevS = R->LevS;
1942 struct LatticeLevel *Lev0 = R->Lev0;
1943 struct Density *Dens0 = Lev0->Dens;
1944 fftw_complex *Psi0;
1945 fftw_real *Psi0R, *Psip0R;
1946 fftw_real *CurrentDensity[NDIM*NDIM];
1947 fftw_real *Psi1R;
1948 fftw_real *Psip1R;
1949 fftw_real *tempArray; // intendedly the same
1950 double r_bar[NDIM], x[NDIM], fac[NDIM];
1951 double Current;//, current;
1952 const double UnitsFactor = 1.; ///LevS->MaxN; // 1/N (from ff-backtransform)
1953 int i, index, B_index;
1954 int k, j, i0;
1955 int n[NDIM], n0;
1956 int N[NDIM];
1957 N[0] = Lev0->Plan0.plan->N[0];
1958 N[1] = Lev0->Plan0.plan->N[1];
1959 N[2] = Lev0->Plan0.plan->N[2];
1960 const int N0 = Lev0->Plan0.plan->local_nx;
1961 //int ActNum;
1962 const int myPE = P->Par.me_comm_ST_Psi;
1963 const int type = R->CurrentMin;
1964 MPI_Status status;
1965 int cross_lookup_1[4], cross_lookup_3[4], l_1 = 0, l_3 = 0;
1966
1967 //fprintf(stderr,"(%i) FactoR %e\n", P->Par.me, R->FactorDensityR);
1968
1969 // Init values and pointers
1970 if (P->Call.out[PsiOut]) {
1971 fprintf(stderr,"(%i) LockArray: ", P->Par.me);
1972 for(i=0;i<MaxDensityTypes;i++)
1973 fprintf(stderr,"(%i,%i) ",Dens0->LockArray[i],Dens0->LockCArray[i]);
1974 fprintf(stderr,"\n");
1975 }
1976 LockDensityArray(Dens0,Temp2Density,real); // Psi1R
1977 LockDensityArray(Dens0,Temp2Density,imag); // Psip1R and tempArray
1978 LockDensityArray(Dens0,GapDensity,real); // Psi0R
1979 LockDensityArray(Dens0,GapLocalDensity,real); // Psip0R
1980
1981 Psi0R = (fftw_real *)Dens0->DensityArray[GapDensity];
1982 Psip0R = (fftw_real *)Dens0->DensityArray[GapLocalDensity];
1983 Psi1R = (fftw_real *)Dens0->DensityArray[Temp2Density];
1984 tempArray = Psip1R = (fftw_real *)Dens0->DensityCArray[Temp2Density];
1985 SetArrayToDouble0((double *)Psi0R,Dens0->TotalSize*2);
1986 SetArrayToDouble0((double *)Psip0R,Dens0->TotalSize*2);
1987 SetArrayToDouble0((double *)Psi1R,Dens0->TotalSize*2);
1988 SetArrayToDouble0((double *)Psip1R,Dens0->TotalSize*2);
1989
1990 if (P->Call.out[PsiOut]) {
1991 fprintf(stderr,"(%i) LockArray: ", P->Par.me);
1992 for(i=0;i<MaxDensityTypes;i++)
1993 fprintf(stderr,"(%i,%i) ",Dens0->LockArray[i],Dens0->LockCArray[i]);
1994 fprintf(stderr,"\n");
1995 }
1996
1997 // don't put the following stuff into a for loop, they might not be continuous! (preprocessor values: CurrentDensity...)
1998 CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
1999 CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
2000 CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
2001 CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
2002 CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
2003 CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
2004 CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
2005 CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
2006 CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
2007
2008 // initialize the array if it is the first of all six perturbation run
2009 if ((R->DoFullCurrent == 0) && (R->CurrentMin == Perturbed_P0)) { // reset if FillDelta...() hasn't done it before
2010 debug(P,"resetting CurrentDensity...");
2011 for (B_index=0; B_index<NDIM*NDIM; B_index++) // initialize current density array
2012 SetArrayToDouble0((double *)CurrentDensity[B_index],Dens0->TotalSize*2); // DensityArray is fftw_real, no 2*LocalSizeR here!
2013 }
2014
2015 switch(type) { // set j (which is linked to the index from derivation wrt to B^{ext})
2016 case Perturbed_P0:
2017 case Perturbed_P1:
2018 case Perturbed_P2:
2019 j = type - Perturbed_P0;
2020 l_1 = crossed(j,1);
2021 l_3 = crossed(j,3);
2022 for(k=0;k<4;k++) {
2023 cross_lookup_1[k] = cross(l_1,k);
2024 cross_lookup_3[k] = cross(l_3,k);
2025 }
2026 break;
2027 case Perturbed_RxP0:
2028 case Perturbed_RxP1:
2029 case Perturbed_RxP2:
2030 j = type - Perturbed_RxP0;
2031 break;
2032 default:
2033 j = 0;
2034 Error(SomeError,"FillCurrentDensity() called while not in perturbed minimisation!");
2035 break;
2036 }
2037
2038 int wished = -1;
2039 FILE *file = fopen(P->Call.MainParameterFile,"r");
2040 if (!ParseForParameter(1,file,"Orbital",0,1,1,int_type,&wished, 1, optional)) {
2041 fprintf(stderr,"Desired Orbital missing!\n");
2042 wished = -1;
2043 } else if (wished != -1) {
2044 fprintf(stderr,"Desired Orbital is: %i.\n", wished);
2045 } else {
2046 fprintf(stderr,"Desired Orbital is: All.\n");
2047 }
2048 fclose(file);
2049
2050 // Commence grid filling
2051 for (k=Psi->TypeStartIndex[Occupied];k<Psi->TypeStartIndex[Occupied+1];k++) // every local wave functions adds up its part of the current
2052 if ((k + P->Par.me_comm_ST_PsiT*(Psi->TypeStartIndex[UnOccupied]-Psi->TypeStartIndex[Occupied]) == wished) || (wished == -1)) { // compare with global number
2053 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i)Calculating Current Density Summand of type %s for Psi (%i/%i) ... \n", P->Par.me, R->MinimisationName[type], Psi->LocalPsiStatus[k].MyGlobalNo, k);
2054 //ActNum = k - Psi->TypeStartIndex[Occupied] + Psi->TypeStartIndex[1] * Psi->LocalPsiStatus[k].my_color_comm_ST_Psi; // global number of unperturbed Psi
2055 Psi0 = LevS->LPsi->LocalPsi[k]; // Local unperturbed psi
2056
2057 // now some preemptive ffts for the whole grid
2058 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Bringing |Psi0> one level up and fftransforming\n", P->Par.me);
2059 fft_Psi(P, Psi0, Psi0R, 0, Psi0symmetry); //0 // 0 //0
2060
2061 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Bringing |Psi1> one level up and fftransforming\n", P->Par.me);
2062 fft_Psi(P, LevS->LPsi->LocalPsi[Psi->TypeStartIndex[type]+k], Psi1R, 0, Psi1symmetry); //3 //0 //0
2063
2064 for (index=0;index<NDIM;index++) { // for all NDIM components of momentum operator
2065
2066 if ((P->Call.out[StepLeaderOut]) && (!index)) fprintf(stderr,"(%i) Bringing p|Psi0> one level up and fftransforming\n", P->Par.me);
2067 fft_Psi(P, Psi0, Psip0R, index, Psip0symmetry); //6 //6 //6
2068
2069 if ((P->Call.out[StepLeaderOut]) && (!index)) fprintf(stderr,"(%i) Bringing p|Psi1> one level up and fftransforming\n", P->Par.me);
2070 fft_Psi(P, LevS->LPsi->LocalPsi[Psi->TypeStartIndex[type]+k], Psip1R, index, Psip1symmetry); //4 //6 //7
2071
2072 // then for every point on the grid in real space ...
2073
2074 //if (Psi1R != (fftw_real *)Dens0->DensityArray[Temp2Density] || i0<0 || i0>=Dens0->LocalSizeR) Error(SomeError,"fft_Psi: Psi1R corrupted");
2075 //Psi1R[i0] = (Psi1_rxp_R[j])[i0] - (r_bar[cross(j,0)] * (Psi1_p_R[cross(j,1)])[i0] - r_bar[cross(j,2)] * (Psi1_p_R[cross(j,3)])[i0]); //
2076 //if (Psip1R != (fftw_real *)Dens0->DensityCArray[Temp2Density] || i0<0 || i0>=Dens0->LocalSizeR) Error(SomeError,"fft_Psi: Psip1R corrupted");
2077 //Psip1R[i0] = Psi1_rxp_pR[i0] - (r_bar[cross(j,0)] * (Psi1_p_pR[cross(j,1)])[i0] - r_bar[cross(j,2)] * (Psi1_p_pR[cross(j,3)])[i0]); //
2078
2079 switch(type) {
2080 case Perturbed_P0:
2081 case Perturbed_P1:
2082 case Perturbed_P2:
2083 for (n0=0;n0<N0;n0++) // only local points on x axis
2084 for (n[1]=0;n[1]<N[1];n[1]++)
2085 for (n[2]=0;n[2]<N[2];n[2]++) {
2086 i0 = n[2]+N[2]*(n[1]+N[1]*n0);
2087 n[0]=n0 + N0*myPE; // global relative coordinate: due to partitoning of x-axis in PEPGamma>1 case
2088 fac[0] = (double)n[0]/(double)N[0];
2089 fac[1] = (double)n[1]/(double)N[1];
2090 fac[2] = (double)n[2]/(double)N[2];
2091 RMat33Vec3(x, Lat->RealBasis, fac); // relative coordinate times basis matrix gives absolute ones
2092 for (i=0;i<NDIM;i++) // build gauge-translated r_bar evaluation point
2093 r_bar[i] =
2094 sawtooth(Lat,MinImageConv(Lat, x[i], Psi->AddData[k].WannierCentre[i], i),i);
2095// ShiftGaugeOrigin(P,truedist(Lat, x[i], Psi->AddData[k].WannierCentre[i], i),i);
2096 //truedist(Lat, x[i], Psi->AddData[k].WannierCentre[i], i);
2097
2098 Current = Psip0R[i0] * (r_bar[cross_lookup_1[0]] * Psi1R[i0]);
2099 Current += (Psi0R[i0] * r_bar[cross_lookup_1[0]] * Psip1R[i0]);
2100 Current *= .5 * UnitsFactor * Psi->LocalPsiStatus[k].PsiFactor * R->FactorDensityR; // factor confirmed, see CalculateOneDensityR() and InitDensityCalculation()
2101 ////if (CurrentDensity[index+j*NDIM] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index+j*NDIM] || i0<0 || i0>=Dens0->LocalSizeR || (index+j*NDIM)<0 || (index+j*NDIM)>=NDIM*NDIM) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
2102 CurrentDensity[index+l_1*NDIM][i0] -= Current; // note: sign of cross product resides in Current itself (here: plus)
2103
2104 Current = - Psip0R[i0] * (r_bar[cross_lookup_3[2]] * Psi1R[i0]);
2105 Current += - (Psi0R[i0] * r_bar[cross_lookup_3[2]] * Psip1R[i0]);
2106 Current *= .5 * UnitsFactor * Psi->LocalPsiStatus[k].PsiFactor * R->FactorDensityR; // factor confirmed, see CalculateOneDensityR() and InitDensityCalculation()
2107 ////if (CurrentDensity[index+j*NDIM] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index+j*NDIM] || i0<0 || i0>=Dens0->LocalSizeR || (index+j*NDIM)<0 || (index+j*NDIM)>=NDIM*NDIM) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
2108 CurrentDensity[index+l_3*NDIM][i0] -= Current; // note: sign of cross product resides in Current itself (here: minus)
2109 }
2110 break;
2111 case Perturbed_RxP0:
2112 case Perturbed_RxP1:
2113 case Perturbed_RxP2:
2114 for (n0=0;n0<N0;n0++) // only local points on x axis
2115 for (n[1]=0;n[1]<N[1];n[1]++)
2116 for (n[2]=0;n[2]<N[2];n[2]++) {
2117 i0 = n[2]+N[2]*(n[1]+N[1]*n0);
2118 Current = (Psip0R[i0] * Psi1R[i0] + Psi0R[i0] * Psip1R[i0]);
2119 Current *= .5 * UnitsFactor * Psi->LocalPsiStatus[k].PsiFactor * R->FactorDensityR; // factor confirmed, see CalculateOneDensityR() and InitDensityCalculation()
2120 ////if (CurrentDensity[index+j*NDIM] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index+j*NDIM] || i0<0 || i0>=Dens0->LocalSizeR || (index+j*NDIM)<0 || (index+j*NDIM)>=NDIM*NDIM) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
2121 CurrentDensity[index+j*NDIM][i0] += Current;
2122 }
2123 break;
2124 default:
2125 break;
2126 }
2127 }
2128 //OutputCurrentDensity(P);
2129 }
2130
2131 //debug(P,"Unlocking arrays");
2132 //debug(P,"GapDensity");
2133 UnLockDensityArray(Dens0,GapDensity,real); // Psi0R
2134 //debug(P,"GapLocalDensity");
2135 UnLockDensityArray(Dens0,GapLocalDensity,real); // Psip0R
2136 //debug(P,"Temp2Density");
2137 UnLockDensityArray(Dens0,Temp2Density,real); // Psi1R
2138
2139// if (P->Call.out[StepLeaderOut])
2140// fprintf(stderr,"\n\n");
2141
2142 //debug(P,"MPI operation");
2143 // and in the end gather partial densities from other processes
2144 if (type == Perturbed_RxP2) // exchange all (due to shared wave functions) only after last pertubation run
2145 for (index=0;index<NDIM*NDIM;index++) {
2146 //if (tempArray != (fftw_real *)Dens0->DensityCArray[Temp2Density]) Error(SomeError,"FillCurrentDensity: tempArray corrupted");
2147 //debug(P,"tempArray to zero");
2148 SetArrayToDouble0((double *)tempArray, Dens0->TotalSize*2);
2149 ////if (CurrentDensity[index] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index]) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
2150 //debug(P,"CurrentDensity exchange");
2151 MPI_Allreduce( CurrentDensity[index], tempArray, Dens0->LocalSizeR, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_PsiT); // gather results from all wave functions ...
2152 switch(Psi->PsiST) { // ... and also from SpinUp/Downs
2153 default:
2154 //debug(P,"CurrentDensity = tempArray");
2155 for (i=0;i<Dens0->LocalSizeR;i++) {
2156 ////if (CurrentDensity[index] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index] || i<0 || i>=Dens0->LocalSizeR) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
2157 CurrentDensity[index][i] = tempArray[i];
2158 }
2159 break;
2160 case SpinUp:
2161 //debug(P,"CurrentDensity exchange spinup");
2162 MPI_Sendrecv(tempArray, Dens0->LocalSizeR, MPI_DOUBLE, P->Par.me_comm_ST, CurrentTag1,
2163 CurrentDensity[index], Dens0->LocalSizeR, MPI_DOUBLE, P->Par.me_comm_ST, CurrentTag2, P->Par.comm_STInter, &status );
2164 //debug(P,"CurrentDensity += tempArray");
2165 for (i=0;i<Dens0->LocalSizeR;i++) {
2166 ////if (CurrentDensity[index] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index] || i<0 || i>=Dens0->LocalSizeR) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
2167 CurrentDensity[index][i] += tempArray[i];
2168 }
2169 break;
2170 case SpinDown:
2171 //debug(P,"CurrentDensity exchange spindown");
2172 MPI_Sendrecv(tempArray, Dens0->LocalSizeR, MPI_DOUBLE, P->Par.me_comm_ST, CurrentTag2,
2173 CurrentDensity[index], Dens0->LocalSizeR, MPI_DOUBLE, P->Par.me_comm_ST, CurrentTag1, P->Par.comm_STInter, &status );
2174 //debug(P,"CurrentDensity += tempArray");
2175 for (i=0;i<Dens0->LocalSizeR;i++) {
2176 ////if (CurrentDensity[index] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index] || i<0 || i>=Dens0->LocalSizeR) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
2177 CurrentDensity[index][i] += tempArray[i];
2178 }
2179 break;
2180 }
2181 }
2182 //debug(P,"Temp2Density");
2183 UnLockDensityArray(Dens0,Temp2Density,imag); // Psip1R and tempArray
2184 //debug(P,"CurrentDensity end");
2185}
2186
2187/** Structure holding Problem at hand and two indices, defining the greens function to be inverted.
2188 */
2189struct params
2190{
2191 struct Problem *P;
2192 int *k;
2193 int *l;
2194 int *iter;
2195 fftw_complex *x_l;
2196};
2197
2198/** Wrapper function to solve G_kl x = b for x.
2199 * \param *x above x
2200 * \param *param additional parameters, here Problem at hand
2201 * \return evaluated to be minimized functional \f$\frac{1}{2}x \cdot Ax - xb\f$ at \a x on return
2202 */
2203static double DeltaCurrent_f(const gsl_vector * x, void * param)
2204{
2205 struct Problem *P = ((struct params *)param)->P;
2206 struct RunStruct *R = &P->R;
2207 struct LatticeLevel *LevS = R->LevS;
2208 struct Psis *Psi = &P->Lat.Psi;
2209 struct PseudoPot *PP = &P->PP;
2210 const double PsiFactor = Psi->AllPsiStatus[*((struct params *)param)->k].PsiFactor;
2211 double result = 0.;
2212 fftw_complex *TempPsi = LevS->LPsi->TempPsi;
2213 fftw_complex *TempPsi2 = LevS->LPsi->TempPsi2;
2214 int u;
2215
2216 //fprintf(stderr,"Evaluating f(%i,%i) for %i-th time\n", *((struct params *)param)->k, *((struct params *)param)->l, *((struct params *)param)->iter);
2217
2218 // extract gsl_vector
2219 for (u=0;u<LevS->MaxG;u++) {
2220 TempPsi[u].re = gsl_vector_get(x, 2*u);
2221 TempPsi[u].im = gsl_vector_get(x, 2*u+1);
2222 }
2223 // generate fnl
2224 CalculateCDfnl(P, TempPsi, PP->CDfnl); // calculate needed non-local form factors
2225 // Apply Hamiltonian to x
2226 ApplyTotalHamiltonian(P,TempPsi,TempPsi2, PP->CDfnl,PsiFactor,0);
2227 // take scalar product to get eigen value
2228 result = .5 * PsiFactor * (((*((struct params *)param)->k == *((struct params *)param)->l ? GradSP(P,LevS,TempPsi,TempPsi2) : 0.) - Psi->lambda[*((struct params *)param)->k][*((struct params *)param)->l])) - GradSP(P,LevS,TempPsi,LevS->LPsi->LocalPsi[*((struct params *)param)->l]);
2229 return result;
2230}
2231
2232/** Wrapper function to solve G_kl x = b for x.
2233 * \param *x above x
2234 * \param *param additional parameters, here Problem at hand
2235 * \param *g gradient vector on return
2236 * \return error code
2237 */
2238static void DeltaCurrent_df(const gsl_vector * x, void * param, gsl_vector * g)
2239{
2240 struct Problem *P = ((struct params *)param)->P;
2241 struct RunStruct *R = &P->R;
2242 struct LatticeLevel *LevS = R->LevS;
2243 struct Psis *Psi = &P->Lat.Psi;
2244 struct PseudoPot *PP = &P->PP;
2245 const double PsiFactor = Psi->AllPsiStatus[*((struct params *)param)->k].PsiFactor;
2246 fftw_complex *TempPsi = LevS->LPsi->TempPsi;
2247 fftw_complex *TempPsi2 = LevS->LPsi->TempPsi2;
2248 fftw_complex *x_l = ((struct params *)param)->x_l;
2249 int u;
2250
2251 //fprintf(stderr,"Evaluating df(%i,%i) for %i-th time\n", *((struct params *)param)->k, *((struct params *)param)->l, *((struct params *)param)->iter);
2252
2253 // extract gsl_vector
2254 for (u=0;u<LevS->MaxG;u++) {
2255 TempPsi[u].re = gsl_vector_get(x, 2*u);
2256 TempPsi[u].im = gsl_vector_get(x, 2*u+1);
2257 }
2258 // generate fnl
2259 CalculateCDfnl(P, TempPsi, PP->CDfnl); // calculate needed non-local form factors
2260 // Apply Hamiltonian to x
2261 ApplyTotalHamiltonian(P,TempPsi,TempPsi2, PP->CDfnl,PsiFactor,0);
2262 // put into returning vector
2263 for (u=0;u<LevS->MaxG;u++) {
2264 gsl_vector_set(g, 2*u, TempPsi2[u].re - x_l[u].re);
2265 gsl_vector_set(g, 2*u+1, TempPsi2[u].im - x_l[u].im);
2266 }
2267}
2268
2269/** Wrapper function to solve G_kl x = b for x.
2270 * \param *x above x
2271 * \param *param additional parameters, here Problem at hand
2272 * \param *f evaluated to be minimized functional \f$\frac{1}{2}x \cdot Ax - xb\f$ at \a x on return
2273 * \param *g gradient vector on return
2274 * \return error code
2275 */
2276static void DeltaCurrent_fdf(const gsl_vector * x, void * param, double * f, gsl_vector * g)
2277{
2278 struct Problem *P = ((struct params *)param)->P;
2279 struct RunStruct *R = &P->R;
2280 struct LatticeLevel *LevS = R->LevS;
2281 struct Psis *Psi = &P->Lat.Psi;
2282 struct PseudoPot *PP = &P->PP;
2283 const double PsiFactor = Psi->AllPsiStatus[*((struct params *)param)->k].PsiFactor;
2284 fftw_complex *TempPsi = LevS->LPsi->TempPsi;
2285 fftw_complex *TempPsi2 = LevS->LPsi->TempPsi2;
2286 fftw_complex *x_l = ((struct params *)param)->x_l;
2287 int u;
2288
2289 //fprintf(stderr,"Evaluating fdf(%i,%i) for %i-th time\n", *((struct params *)param)->k, *((struct params *)param)->l, *((struct params *)param)->iter);
2290
2291 // extract gsl_vector
2292 for (u=0;u<LevS->MaxG;u++) {
2293 TempPsi[u].re = gsl_vector_get(x, 2*u);
2294 TempPsi[u].im = gsl_vector_get(x, 2*u+1);
2295 }
2296 // generate fnl
2297 CalculateCDfnl(P, TempPsi, PP->CDfnl); // calculate needed non-local form factors
2298 // Apply Hamiltonian to x
2299 ApplyTotalHamiltonian(P,TempPsi,TempPsi2, PP->CDfnl,PsiFactor,0);
2300 // put into returning vector
2301 for (u=0;u<LevS->MaxG;u++) {
2302 gsl_vector_set(g, 2*u, TempPsi[u].re - x_l[u].re);
2303 gsl_vector_set(g, 2*u+1, TempPsi[u].im - x_l[u].im);
2304 }
2305
2306 *f = .5 * PsiFactor * (((*((struct params *)param)->k == *((struct params *)param)->l ? GradSP(P,LevS,TempPsi,TempPsi2) : 0.) - Psi->lambda[*((struct params *)param)->k][*((struct params *)param)->l])) - GradSP(P,LevS,TempPsi,LevS->LPsi->LocalPsi[*((struct params *)param)->l]);
2307}
2308
2309/** Evaluates the \f$\Delta j_k(r')\f$ component of the current density.
2310 * \f[
2311 * \Delta j_k(r') = \frac{e}{m} \sum_l \langle \varphi^{(0)}_k | \left ( p |r'\rangle \langle r'| + | r'\rangle\langle r'|p \right ) {\cal G}_{kl} (d_k - d_l) \times p | \varphi^{(1)}_l \rangle \cdot B
2312 * \f]
2313 * \param *P Problem at hand
2314 * \note result has not yet been MPI_Allreduced for ParallelSimulationData#comm_ST_inter or ParallelSimulationData#comm_ST_PsiT groups!
2315 * \warning the routine is checked but does not yet produce sensible results.
2316 */
2317void FillDeltaCurrentDensity(struct Problem *P)
2318{
2319 struct Lattice *Lat = &P->Lat;
2320 struct RunStruct *R = &P->R;
2321 struct Psis *Psi = &Lat->Psi;
2322 struct LatticeLevel *Lev0 = R->Lev0;
2323 struct LatticeLevel *LevS = R->LevS;
2324 struct Density *Dens0 = Lev0->Dens;
2325 int i,j,s;
2326 int k,l,u, in, dex, index,i0;
2327 //const int Num = Psi->NoOfPsis;
2328 int RecvSource;
2329 MPI_Status status;
2330 struct OnePsiElement *OnePsiB, *LOnePsiB, *OnePsiA, *LOnePsiA;
2331 const int ElementSize = (sizeof(fftw_complex) / sizeof(double));
2332 int n[NDIM], n0;
2333 int N[NDIM];
2334 N[0] = Lev0->Plan0.plan->N[0];
2335 N[1] = Lev0->Plan0.plan->N[1];
2336 N[2] = Lev0->Plan0.plan->N[2];
2337 const int N0 = Lev0->Plan0.plan->local_nx;
2338 fftw_complex *LPsiDatB;
2339 fftw_complex *Psi0, *Psi1;
2340 fftw_real *Psi0R, *Psip0R;
2341 fftw_real *Psi1R, *Psip1R;
2342 fftw_complex *x_l = LevS->LPsi->TempPsi;//, **x_l_bak;
2343 fftw_real *CurrentDensity[NDIM*NDIM];
2344 int mem_avail, MEM_avail;
2345 double Current;
2346 const double UnitsFactor = 1.;
2347 int cross_lookup[4];
2348 struct params param;
2349 double factor; // temporary factor in Psi1 pre-evaluation
2350
2351 LockDensityArray(Dens0,GapDensity,real); // Psi0R
2352 LockDensityArray(Dens0,GapLocalDensity,real); // Psip0R
2353 LockDensityArray(Dens0,Temp2Density,imag); // Psi1
2354 LockDensityArray(Dens0,GapUpDensity,real); // Psi1R
2355 LockDensityArray(Dens0,GapDownDensity,real); // Psip1R
2356
2357 CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
2358 CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
2359 CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
2360 CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
2361 CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
2362 CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
2363 CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
2364 CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
2365 CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
2366
2367 Psi0R = (fftw_real *)Dens0->DensityArray[GapDensity];
2368 Psip0R = (fftw_real *)Dens0->DensityArray[GapLocalDensity];
2369 Psi1 = (fftw_complex *) Dens0->DensityCArray[Temp2Density];
2370 Psi1R = (fftw_real *)Dens0->DensityArray[GapUpDensity];
2371 Psip1R = (fftw_real *)Dens0->DensityArray[GapDownDensity];
2372
2373// if (R->CurrentMin == Perturbed_P0)
2374// for (B_index=0; B_index<NDIM*NDIM; B_index++) { // initialize current density array
2375// debug(P,"resetting CurrentDensity...");
2376// SetArrayToDouble0((double *)CurrentDensity[B_index],Dens0->TotalSize*2); // DensityArray is fftw_real, no 2*LocalSizeR here!
2377// }
2378 //if (Psi1 != (fftw_complex *) Dens0->DensityCArray[Temp2Density]) Error(SomeError,"FillDeltaCurrentDensity: Psi1 corrupted");
2379 SetArrayToDouble0((double *)Psi1,2*Dens0->TotalSize);
2380
2381// gsl_vector *x = gsl_vector_alloc(Num);
2382// gsl_matrix *G = gsl_matrix_alloc(Num,Num);
2383// gsl_permutation *p = gsl_permutation_alloc(Num);
2384 //int signum;
2385 // begin of GSL linearer CG solver stuff
2386 int iter, Status;
2387
2388 const gsl_multimin_fdfminimizer_type *T;
2389 gsl_multimin_fdfminimizer *minset;
2390
2391 /* Position of the minimum (1,2). */
2392 //double par[2] = { 1.0, 2.0 };
2393
2394 gsl_vector *x;
2395 gsl_multimin_function_fdf my_func;
2396
2397 param.P = P;
2398 param.k = &k;
2399 param.l = &l;
2400 param.iter = &iter;
2401 param.x_l = x_l;
2402
2403 my_func.f = &DeltaCurrent_f;
2404 my_func.df = &DeltaCurrent_df;
2405 my_func.fdf = &DeltaCurrent_fdf;
2406 my_func.n = 2*LevS->MaxG;
2407 my_func.params = (void *)&param;
2408
2409 T = gsl_multimin_fdfminimizer_conjugate_pr;
2410 minset = gsl_multimin_fdfminimizer_alloc (T, 2*LevS->MaxG);
2411 x = gsl_vector_alloc (2*LevS->MaxG);
2412 // end of GSL CG stuff
2413
2414
2415// // construct G_kl = - (H^{(0)} \delta_{kl} -\langle \varphi^{(0)}_k |H^{(0)}| \varphi^{(0)}_l|rangle)^{-1} = A^{-1}
2416// for (k=0;k<Num;k++)
2417// for (l=0;l<Num;l++)
2418// gsl_matrix_set(G, k, l, k == l ? 0. : Psi->lambda[k][l]);
2419// // and decompose G_kl = L U
2420
2421 mem_avail = MEM_avail = 0;
2422// x_l_bak = x_l = (fftw_complex **) Malloc(sizeof(fftw_complex *)*Num,"FillDeltaCurrentDensity: *x_l");
2423// for (i=0;i<Num;i++) {
2424// x_l[i] = NULL;
2425// x_l[i] = (fftw_complex *) malloc(sizeof(fftw_complex)*LevS->MaxG);
2426// if (x_l[i] == NULL) {
2427// mem_avail = 1; // there was not enough memory for this node
2428// fprintf(stderr,"(%i) FillDeltaCurrentDensity: x_l[%i] ... insufficient memory.\n",P->Par.me,i);
2429// }
2430// }
2431// MPI_Allreduce(&mem_avail,&MEM_avail,1,MPI_INT,MPI_SUM,P->Par.comm_ST); // sum results from all processes
2432
2433 if (MEM_avail != 0) { // means at least node couldn't allocate sufficient memory, skipping...
2434 fprintf(stderr,"(%i) FillDeltaCurrentDensity: x_l[], not enough memory: %i! Skipping FillDeltaCurrentDensity evaluation.", P->Par.me, MEM_avail);
2435 } else {
2436 // sum over k and calculate \Delta j_k(r')
2437 k=-1;
2438 for (i=0; i < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; i++) { // go through all wave functions
2439 //fprintf(stderr,"(%i) GlobalNo: %d\tLocalNo: %d\n", P->Par.me,Psi->AllPsiStatus[i].MyGlobalNo,Psi->AllPsiStatus[i].MyLocalNo);
2440 OnePsiA = &Psi->AllPsiStatus[i]; // grab OnePsiA
2441 if (OnePsiA->PsiType == Occupied) { // drop the extra and perturbed ones
2442 k++;
2443 if (OnePsiA->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
2444 LOnePsiA = &Psi->LocalPsiStatus[OnePsiA->MyLocalNo];
2445 else
2446 LOnePsiA = NULL;
2447 if (LOnePsiA != NULL) {
2448 Psi0=LevS->LPsi->LocalPsi[OnePsiA->MyLocalNo];
2449
2450 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Bringing |Psi0> one level up and fftransforming\n", P->Par.me);
2451 //if (Psi0R != (fftw_real *)Dens0->DensityArray[GapDensity]) Error(SomeError,"FillDeltaCurrentDensity: Psi0R corrupted");
2452 fft_Psi(P,Psi0,Psi0R, 0, Psi0symmetry); //0 // 0 //0
2453
2454 for (in=0;in<NDIM;in++) { // in is the index from derivation wrt to B^{ext}
2455 l = -1;
2456 for (j=0; j < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; j++) { // go through all wave functions
2457 OnePsiB = &Psi->AllPsiStatus[j]; // grab OnePsiA
2458 if (OnePsiB->PsiType == Occupied)
2459 l++;
2460 if ((OnePsiB != OnePsiA) && (OnePsiB->PsiType == Occupied)) { // drop the same and the extra ones
2461 if (OnePsiB->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
2462 LOnePsiB = &Psi->LocalPsiStatus[OnePsiB->MyLocalNo];
2463 else
2464 LOnePsiB = NULL;
2465 if (LOnePsiB == NULL) { // if it's not local ... receive x from respective process
2466 RecvSource = OnePsiB->my_color_comm_ST_Psi;
2467 MPI_Recv( x_l, LevS->MaxG*ElementSize, MPI_DOUBLE, RecvSource, HamiltonianTag, P->Par.comm_ST_PsiT, &status );
2468 } else { // .. otherwise setup wave function as x ...
2469 // Evaluate cross product: \epsilon_{ijm} (d_k - d_l)_j p_m | \varphi^{(0)} \rangle = b_i ... and
2470 LPsiDatB=LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo];
2471 //LPsiDatx=LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo+Psi->TypeStartIndex[Perturbed_P0]];
2472 //CalculatePerturbationOperator_P(P,LPsiDatB,LPsiDatB_p0,cross(in,1),0);
2473 //CalculatePerturbationOperator_P(P,LPsiDatB,LPsiDatB_p1,cross(in,3),0);
2474 for (dex=0;dex<4;dex++)
2475 cross_lookup[dex] = cross(in,dex);
2476 for(s=0;s<LevS->MaxG;s++) {
2477 //if (x_l != x_l_bak || s<0 || s>LevS->MaxG) Error(SomeError,"FillDeltaCurrentDensity: x_l[] corrupted");
2478 factor =
2479 (MinImageConv(Lat,Psi->AddData[LOnePsiA->MyLocalNo].WannierCentre[cross_lookup[0]],
2480 Psi->AddData[LOnePsiB->MyLocalNo].WannierCentre[cross_lookup[0]],cross_lookup[0]) * LevS->GArray[s].G[cross_lookup[1]] -
2481 MinImageConv(Lat,Psi->AddData[LOnePsiA->MyLocalNo].WannierCentre[cross_lookup[2]],
2482 Psi->AddData[LOnePsiB->MyLocalNo].WannierCentre[cross_lookup[2]],cross_lookup[2]) * LevS->GArray[s].G[cross_lookup[3]]);
2483 x_l[s].re = factor * (-LPsiDatB[s].im); // switched due to factorization with "-i G"
2484 x_l[s].im = factor * (LPsiDatB[s].re);
2485 }
2486 // ... and send it to all other processes (Max_me... - 1)
2487 for (u=0;u<P->Par.Max_me_comm_ST_PsiT;u++)
2488 if (u != OnePsiB->my_color_comm_ST_Psi)
2489 MPI_Send( x_l, LevS->MaxG*ElementSize, MPI_DOUBLE, u, HamiltonianTag, P->Par.comm_ST_PsiT);
2490 } // x_l row is now filled (either by receiving result or evaluating it on its own)
2491 // Solve Ax = b by minimizing 1/2 xAx -xb (gradient is residual Ax - b) with conjugate gradient polak-ribiere
2492
2493 debug(P,"fill starting point x with values from b");
2494 /* Starting point, x = b */
2495 for (u=0;u<LevS->MaxG;u++) {
2496 gsl_vector_set (x, 2*u, x_l[u].re);
2497 gsl_vector_set (x, 2*u+1, x_l[u].im);
2498 }
2499
2500 gsl_multimin_fdfminimizer_set (minset, &my_func, x, 0.01, 1e-4);
2501
2502 fprintf(stderr,"(%i) Start solving for (%i,%i) and index %i\n",P->Par.me, k,l,in);
2503 // start solving
2504 iter = 0;
2505 do
2506 {
2507 iter++;
2508 Status = gsl_multimin_fdfminimizer_iterate (minset);
2509
2510 if (Status)
2511 break;
2512
2513 Status = gsl_multimin_test_gradient (minset->gradient, 1e-3);
2514
2515 if (Status == GSL_SUCCESS)
2516 fprintf (stderr,"(%i) Minimum found after %i iterations.\n", P->Par.me, iter);
2517
2518 } while (Status == GSL_CONTINUE && iter < 100);
2519
2520 debug(P,"Put solution into Psi1");
2521 // ... and what do we do now? Put solution into Psi1!
2522 for(s=0;s<LevS->MaxG;s++) {
2523 //if (Psi1 != (fftw_complex *) Dens0->DensityCArray[Temp2Density] || s<0 || s>LevS->MaxG) Error(SomeError,"FillDeltaCurrentDensity: Psi1 corrupted");
2524 Psi1[s].re = gsl_vector_get (minset->x, 2*s);
2525 Psi1[s].im = gsl_vector_get (minset->x, 2*s+1);
2526 }
2527
2528 // // Solve A^{-1} b_i = x
2529 // for(s=0;s<LevS->MaxG;s++) {
2530 // // REAL PART
2531 // // retrieve column from gathered matrix
2532 // for(u=0;u<Num;u++)
2533 // gsl_vector_set(x,u,x_l[u][s].re);
2534 //
2535 // // solve: sum_l A_{kl}^(-1) b_l (s) = x_k (s)
2536 // gsl_linalg_LU_svx (G, p, x);
2537 //
2538 // // put solution back into x_l[s]
2539 // for(u=0;u<Num;u++) {
2540 // //if (x_l != x_l_bak || s<0 || s>=LevS->MaxG) Error(SomeError,"FillDeltaCurrentDensity: x_l[] corrupted");
2541 // x_l[u][s].re = gsl_vector_get(x,u);
2542 // }
2543 //
2544 // // IMAGINARY PART
2545 // // retrieve column from gathered matrix
2546 // for(u=0;u<Num;u++)
2547 // gsl_vector_set(x,u,x_l[u][s].im);
2548 //
2549 // // solve: sum_l A_{kl}^(-1) b_l (s) = x_k (s)
2550 // gsl_linalg_LU_svx (G, p, x);
2551 //
2552 // // put solution back into x_l[s]
2553 // for(u=0;u<Num;u++) {
2554 // //if (x_l != x_l_bak || s<0 || s>=LevS->MaxG) Error(SomeError,"FillDeltaCurrentDensity: x_l[] corrupted");
2555 // x_l[u][s].im = gsl_vector_get(x,u);
2556 // }
2557 // } // now we have in x_l a vector similar to "Psi1" which we use to evaluate the current density
2558 //
2559 // // evaluate \Delta J_k ... mind the minus sign from G_kl!
2560 // // fill Psi1
2561 // for(s=0;s<LevS->MaxG;s++) {
2562 // //if (Psi1 != (fftw_complex *) Dens0->DensityCArray[Temp2Density] || s<0 || s>LevS->MaxG) Error(SomeError,"FillDeltaCurrentDensity: Psi1 corrupted");
2563 // Psi1[s].re = x_l[k][s].re;
2564 // Psi1[s].im = x_l[k][s].im;
2565 // }
2566
2567 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Bringing |Psi1> one level up and fftransforming\n", P->Par.me);
2568 //if (Psi1R != (fftw_real *)Dens0->DensityArray[GapUpDensity]) Error(SomeError,"FillDeltaCurrentDensity: Psi1R corrupted");
2569 fft_Psi(P,Psi1,Psi1R, 0, Psi1symmetry); //2 // 0 //0
2570
2571 for (index=0;index<NDIM;index++) { // for all NDIM components of momentum operator
2572
2573 if ((P->Call.out[StepLeaderOut]) && (!index)) fprintf(stderr,"(%i) Bringing p|Psi0> one level up and fftransforming\n", P->Par.me);
2574 //if (Psip0R != (fftw_real *)Dens0->DensityArray[GapLocalDensity]) Error(SomeError,"FillDeltaCurrentDensity: Psip0R corrupted");
2575 fft_Psi(P,Psi0,Psip0R, index, Psip0symmetry); //6 //6 //6
2576
2577 if ((P->Call.out[StepLeaderOut]) && (!index)) fprintf(stderr,"(%i) Bringing p|Psi1> one level up and fftransforming\n", P->Par.me);
2578 //if (Psip1R != (fftw_real *)Dens0->DensityArray[GapDownDensity]) Error(SomeError,"FillDeltaCurrentDensity: Psip1R corrupted");
2579 fft_Psi(P,Psi1,Psip1R, index, Psip1symmetry); //4 //6 //6
2580
2581 // then for every point on the grid in real space ...
2582 for (n0=0;n0<N0;n0++) // only local points on x axis
2583 for (n[1]=0;n[1]<N[1];n[1]++)
2584 for (n[2]=0;n[2]<N[2];n[2]++) {
2585 i0 = n[2]+N[2]*(n[1]+N[1]*n0);
2586 // and take the product
2587 Current = (Psip0R[i0] * Psi1R[i0] + Psi0R[i0] * Psip1R[i0]);
2588 Current *= 0.5 * UnitsFactor * Psi->AllPsiStatus[OnePsiA->MyGlobalNo].PsiFactor * R->FactorDensityR;
2589 ////if (CurrentDensity[index+in*NDIM] != (fftw_real *) Dens0->DensityArray[CurrentDensity0 + index+in*NDIM]) Error(SomeError,"FillCurrentDensity: CurrentDensity[] corrupted");
2590 //if (i0<0 || i0>=Dens0->LocalSizeR) Error(SomeError,"FillDeltaCurrentDensity: i0 out of range");
2591 //if ((index+in*NDIM)<0 || (index+in*NDIM)>=NDIM*NDIM) Error(SomeError,"FillDeltaCurrentDensity: index out of range");
2592 CurrentDensity[index+in*NDIM][i0] += Current; // minus sign is from G_kl
2593 }
2594 }
2595 }
2596 }
2597 }
2598 }
2599 }
2600 }
2601 }
2602 UnLockDensityArray(Dens0,GapDensity,real); // Psi0R
2603 UnLockDensityArray(Dens0,GapLocalDensity,real); // Psip0R
2604 UnLockDensityArray(Dens0,Temp2Density,imag); // Psi1
2605 UnLockDensityArray(Dens0,GapUpDensity,real); // Psi1R
2606 UnLockDensityArray(Dens0,GapDownDensity,real); // Psip1R
2607// for (i=0;i<Num;i++)
2608// if (x_l[i] != NULL) Free(x_l[i], "bla", "bla");
2609// Free(x_l, "bla");
2610 gsl_multimin_fdfminimizer_free (minset);
2611 gsl_vector_free (x);
2612// gsl_matrix_free(G);
2613// gsl_permutation_free(p);
2614// gsl_vector_free(x);
2615}
2616
2617
2618/** Evaluates the overlap integral between \a state wave functions.
2619 * \f[
2620 * S_{kl} = \langle \varphi_k^{(1)} | \varphi_l^{(1)} \rangle
2621 * \f]
2622 * The scalar product is calculated via GradSP(), MPI_Allreduced among comm_ST_Psi and the result
2623 * stored in Psis#Overlap. The rows have to be MPI exchanged, as otherwise processes will add
2624 * to the TotalEnergy overlaps calculated with old wave functions - they have been minimised after
2625 * the product with exchanged coefficients was taken.
2626 * \param *P Problem at hand
2627 * \param l local number of perturbed wave function.
2628 * \param state PsiTypeTag minimisation state of wave functions to be overlapped
2629 */
2630void CalculateOverlap(struct Problem *P, const int l, const enum PsiTypeTag state)
2631{
2632 struct RunStruct *R = &P->R;
2633 struct Lattice *Lat = &(P->Lat);
2634 struct Psis *Psi = &Lat->Psi;
2635 struct LatticeLevel *LevS = R->LevS;
2636 struct OnePsiElement *OnePsiB, *LOnePsiB;
2637 fftw_complex *LPsiDatB=NULL, *LPsiDatA=NULL;
2638 const int ElementSize = (sizeof(fftw_complex) / sizeof(double));
2639 int RecvSource;
2640 MPI_Status status;
2641 int i,j,m,p;
2642 //const int l_normal = l - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[Occupied];
2643 const int ActNum = l - Psi->TypeStartIndex[state] + Psi->TypeStartIndex[1] * Psi->LocalPsiStatus[l].my_color_comm_ST_Psi;
2644 double *sendbuf, *recvbuf;
2645 double tmp,TMP;
2646 const int gsize = P->Par.Max_me_comm_ST_PsiT; //number of processes in PsiT
2647 int p_num; // number of wave functions (for overlap)
2648
2649 // update overlap table after wave function has changed
2650 LPsiDatA = LevS->LPsi->LocalPsi[l];
2651 m = -1; // to access U matrix element (0..Num-1)
2652 for (j=0; j < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; j++) { // go through all wave functions
2653 OnePsiB = &Psi->AllPsiStatus[j]; // grab OnePsiB
2654 if (OnePsiB->PsiType == state) { // drop all but the ones of current min state
2655 m++; // increase m if it is non-extra wave function
2656 if (OnePsiB->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
2657 LOnePsiB = &Psi->LocalPsiStatus[OnePsiB->MyLocalNo];
2658 else
2659 LOnePsiB = NULL;
2660 if (LOnePsiB == NULL) { // if it's not local ... receive it from respective process into TempPsi
2661 RecvSource = OnePsiB->my_color_comm_ST_Psi;
2662 MPI_Recv( LevS->LPsi->TempPsi, LevS->MaxG*ElementSize, MPI_DOUBLE, RecvSource, OverlapTag, P->Par.comm_ST_PsiT, &status );
2663 LPsiDatB=LevS->LPsi->TempPsi;
2664 } else { // .. otherwise send it to all other processes (Max_me... - 1)
2665 for (p=0;p<P->Par.Max_me_comm_ST_PsiT;p++)
2666 if (p != OnePsiB->my_color_comm_ST_Psi)
2667 MPI_Send( LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo], LevS->MaxG*ElementSize, MPI_DOUBLE, p, OverlapTag, P->Par.comm_ST_PsiT);
2668 LPsiDatB=LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo];
2669 } // LPsiDatB is now set to the coefficients of OnePsi either stored or MPI_Received
2670
2671 tmp = GradSP(P, LevS, LPsiDatA, LPsiDatB) * sqrt(Psi->LocalPsiStatus[l].PsiFactor * OnePsiB->PsiFactor);
2672 MPI_Allreduce ( &tmp, &TMP, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
2673 //fprintf(stderr,"(%i) Setting Overlap [%i][%i] = %lg\n",P->Par.me, ActNum,m,TMP);
2674 Psi->Overlap[ActNum][m] = TMP; //= Psi->Overlap[m][ActNum]
2675 }
2676 }
2677
2678 // exchange newly calculated rows among PsiT
2679 p_num = (m+1) + 1; // number of Psis: one more due to ActNum
2680 sendbuf = (double *) Malloc(p_num * sizeof(double), "CalculateOverlap: sendbuf");
2681 sendbuf[0] = ActNum; // first entry is the global row number
2682 for (i=1;i<p_num;i++)
2683 sendbuf[i] = Psi->Overlap[ActNum][i-1]; // then follow up each entry of overlap row
2684 recvbuf = (double *) Malloc(gsize * p_num * sizeof(double), "CalculateOverlap: recvbuf");
2685 MPI_Allgather(sendbuf, p_num, MPI_DOUBLE, recvbuf, p_num, MPI_DOUBLE, P->Par.comm_ST_PsiT);
2686 Free(sendbuf, "bla");
2687 for (i=0;i<gsize;i++) {// extract results from other processes out of receiving buffer
2688 m = recvbuf[i*p_num]; // m is ActNum of the process whose results we've just received
2689 //fprintf(stderr,"(%i) Received row %i from process %i\n", P->Par.me, m, i);
2690 for (j=1;j<p_num;j++)
2691 Psi->Overlap[m][j-1] = Psi->Overlap[j-1][m] = recvbuf[i*p_num+j]; // put each entry into correspondent Overlap row
2692 }
2693 Free(recvbuf, "bla");
2694}
2695
2696
2697/** Calculates magnetic susceptibility from known current density.
2698 * The bulk susceptibility tensor can be expressed as a function of the current density.
2699 * \f[
2700 * \chi_{ij} = \frac{\mu_0}{2\Omega} \frac{\delta}{\delta B_i^{ext}} \int_\Omega d^3 r \left (r \times j(r) \right )_j
2701 * \f]
2702 * Thus the integral over real space and subsequent MPI_Allreduce() over results from ParallelSimulationData#comm_ST_Psi is
2703 * straightforward. Tensor is diagonalized afterwards and split into its various sub-tensors of lower rank (e.g., isometric
2704 * value is tensor of rank 0) which are printed to screen and the tensorial elements to file '....chi.csv'
2705 * \param *P Problem at hand
2706 */
2707void CalculateMagneticSusceptibility(struct Problem *P)
2708{
2709 struct RunStruct *R = &P->R;
2710 struct Lattice *Lat = &P->Lat;
2711 struct LatticeLevel *Lev0 = R->Lev0;
2712 struct Density *Dens0 = R->Lev0->Dens;
2713 struct Ions *I = &P->Ion;
2714 fftw_real *CurrentDensity[NDIM*NDIM];
2715 int in, dex, i, i0, n0;
2716 int n[NDIM];
2717 const int N0 = Lev0->Plan0.plan->local_nx;
2718 int N[NDIM];
2719 N[0] = Lev0->Plan0.plan->N[0];
2720 N[1] = Lev0->Plan0.plan->N[1];
2721 N[2] = Lev0->Plan0.plan->N[2];
2722 double chi[NDIM*NDIM],Chi[NDIM*NDIM], x[NDIM], fac[NDIM];
2723 const double discrete_factor = Lat->Volume/Lev0->MaxN;
2724 const int myPE = P->Par.me_comm_ST_Psi;
2725 double eta, delta_chi, S, A, iso;
2726 int cross_lookup[4];
2727 char filename[256];
2728 FILE *ChiFile;
2729 time_t seconds;
2730 time(&seconds); // get current time
2731
2732 // set pointers onto current density
2733 CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
2734 CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
2735 CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
2736 CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
2737 CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
2738 CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
2739 CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
2740 CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
2741 CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
2742 //for(i=0;i<NDIM;i++) {
2743// field[i] = Dens0->DensityArray[TempDensity+i];
2744 //LockDensityArray(Dens0,TempDensity+i,real);
2745// SetArrayToDouble0((double *)field[i],Dens0->TotalSize*2);
2746 //}
2747 gsl_matrix_complex *H = gsl_matrix_complex_calloc(NDIM,NDIM);
2748
2749
2750 if (P->Call.out[ValueOut]) fprintf(stderr,"(%i) magnetic susceptibility tensor \\Chi_ij = \n",P->Par.me);
2751 for (in=0; in<NDIM; in++) { // index i of integrand vector component
2752 for(dex=0;dex<4;dex++) // initialise cross lookup
2753 cross_lookup[dex] = cross(in,dex);
2754 for (dex=0; dex<NDIM; dex++) { // index j of derivation wrt B field
2755 chi[in+dex*NDIM] = 0.;
2756 // do the integration over real space
2757 for(n0=0;n0<N0;n0++)
2758 for(n[1]=0;n[1]<N[1];n[1]++)
2759 for(n[2]=0;n[2]<N[2];n[2]++) {
2760 n[0]=n0 + N0*myPE; // global relative coordinate: due to partitoning of x-axis in PEPGamma>1 case
2761 fac[0] = (double)(n[0])/(double)N[0];
2762 fac[1] = (double)(n[1])/(double)N[1];
2763 fac[2] = (double)(n[2])/(double)N[2];
2764 RMat33Vec3(x, Lat->RealBasis, fac);
2765 i0 = n[2]+N[2]*(n[1]+N[1]*(n0)); // the index of current density must match LocalSizeR!
2766 chi[in+dex*NDIM] += MinImageConv(Lat,x[cross_lookup[0]], sqrt(Lat->RealBasisSQ[cross_lookup[0]])/2.,cross_lookup[0]) * CurrentDensity[dex*NDIM+cross_lookup[1]][i0]; // x[cross(in,0)], sqrt(Lat->RealBasisSQ[cross_lookup[0]])/2.
2767 chi[in+dex*NDIM] -= MinImageConv(Lat,x[cross_lookup[2]], sqrt(Lat->RealBasisSQ[cross_lookup[2]])/2.,cross_lookup[2]) * CurrentDensity[dex*NDIM+cross_lookup[3]][i0]; // x[cross(in,2)], sqrt(Lat->RealBasisSQ[cross_lookup[2]])/2.
2768// if (in == dex) field[in][i0] =
2769// truedist(Lat,x[cross_lookup[0]], sqrt(Lat->RealBasisSQ[c[0]])/2.,cross_lookup[0]) * CurrentDensity[dex*NDIM+cross_lookup[1]][i0]
2770// - truedist(Lat,x[cross_lookup[2]], sqrt(Lat->RealBasisSQ[c[2]])/2.,cross_lookup[2]) * CurrentDensity[dex*NDIM+cross_lookup[3]][i0];
2771 //fprintf(stderr,"(%i) temporary susceptiblity \\chi[%i][%i] += %e * %e = r[%i] * CurrDens[%i][%i] = %e\n",P->Par.me,in,dex,(double)n[cross_lookup[0]]/(double)N[cross_lookup[0]]*(sqrt(Lat->RealBasisSQ[cross_lookup[0]])),CurrentDensity[dex*NDIM+cross_lookup[1]][i0],cross_lookup[0],dex*NDIM+cross_lookup[1],i0,chi[in*NDIM+dex]);
2772 }
2773 chi[in+dex*NDIM] *= mu0*discrete_factor/(2.*Lat->Volume); // integral factor
2774 chi[in+dex*NDIM] *= (-1625.); // empirical gauge factor ... sigh
2775 MPI_Allreduce ( &chi[in+dex*NDIM], &Chi[in+dex*NDIM], 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum "LocalSize to TotalSize"
2776 I->I[0].chi[in+dex*NDIM] = Chi[in+dex*NDIM];
2777 Chi[in+dex*NDIM] *= Lat->Volume*loschmidt_constant; // factor for _molar_ susceptibility
2778 if (P->Call.out[ValueOut]) {
2779 fprintf(stderr,"%e\t", Chi[in+dex*NDIM]);
2780 if (dex == NDIM-1) fprintf(stderr,"\n");
2781 }
2782 }
2783 }
2784 // store symmetrized matrix
2785 for (in=0;in<NDIM;in++)
2786 for (dex=0;dex<NDIM;dex++)
2787 gsl_matrix_complex_set(H,in,dex,gsl_complex_rect((Chi[in+dex*NDIM]+Chi[dex+in*NDIM])/2.,0));
2788 // output tensor to file
2789 if (P->Par.me == 0) {
2790 sprintf(filename, ".chi.L%i.csv", Lev0->LevelNo);
2791 OpenFile(P, &ChiFile, filename, "a", P->Call.out[ReadOut]);
2792 fprintf(ChiFile,"# magnetic susceptibility tensor chi[01,02,03,10,11,12,20,21,22], seed %i, config %s, run on %s", R->Seed, P->Files.default_path, ctime(&seconds));
2793 fprintf(ChiFile,"%lg\t", P->Lat.ECut/(Lat->LevelSizes[0]*Lat->LevelSizes[0]));
2794 for (in=0;in<NDIM*NDIM;in++)
2795 fprintf(ChiFile,"%e\t", Chi[in]);
2796 fprintf(ChiFile,"\n");
2797 fclose(ChiFile);
2798 }
2799 // diagonalize chi
2800 gsl_vector *eval = gsl_vector_alloc(NDIM);
2801 gsl_eigen_herm_workspace *w = gsl_eigen_herm_alloc(NDIM);
2802 gsl_eigen_herm(H, eval, w);
2803 gsl_eigen_herm_free(w);
2804 gsl_sort_vector(eval); // sort eigenvalues
2805 // print eigenvalues
2806 iso = 0;
2807 for (i=0;i<NDIM;i++) {
2808 I->I[0].chi_PAS[i] = gsl_vector_get(eval,i);
2809 iso += Chi[i+i*NDIM]/3.;
2810 }
2811 eta = (gsl_vector_get(eval,1)-gsl_vector_get(eval,0))/(gsl_vector_get(eval,2)-iso);
2812 delta_chi = gsl_vector_get(eval,2) - 0.5*(gsl_vector_get(eval,0)+gsl_vector_get(eval,1));
2813 S = (delta_chi*delta_chi)*(1+1./3.*eta*eta);
2814 A = 0.;
2815 for (i=0;i<NDIM;i++) {
2816 in = cross(i,0);
2817 dex = cross(i,1);
2818 A += pow(-1,i)*pow(0.5*(Chi[in+dex*NDIM]-Chi[dex+in*NDIM]),2);
2819 }
2820 if (P->Call.out[ValueOut]) {
2821 fprintf(stderr,"(%i) converted to Principal Axis System\n==================\nDiagonal entries:", P->Par.me);
2822 for (i=0;i<NDIM;i++)
2823 fprintf(stderr,"\t%lg",gsl_vector_get(eval,i));
2824 fprintf(stderr,"\nsusceptib. : %e\n", iso);
2825 fprintf(stderr,"anisotropy : %e\n", delta_chi);
2826 fprintf(stderr,"asymmetry : %e\n", eta);
2827 fprintf(stderr,"S : %e\n", S);
2828 fprintf(stderr,"A : %e\n", A);
2829 fprintf(stderr,"==================\n");
2830 }
2831 //for(i=0;i<NDIM;i++)
2832 //UnLockDensityArray(Dens0,TempDensity+i,real);
2833 gsl_vector_free(eval);
2834 gsl_matrix_complex_free(H);
2835}
2836
2837/** Fouriertransforms all nine current density components and calculates shielding tensor.
2838 * \f[
2839 * \sigma_{ij} = \left ( \frac{G}{|G|^2} \times J_i(G) \right )_j
2840 * \f]
2841 * The CurrentDensity has to be fouriertransformed to reciprocal subspace in order to be useful, and the final
2842 * product \f$\sigma_{ij}(G)\f$ has to be back-transformed to real space. However, the shielding is the only evaluated
2843 * at the grid points and not where the real ion position is. The shieldings there are interpolated between the eight
2844 * adjacent grid points by a simple linear weighting. Afterwards follows the same analaysis and printout of the rank-2-tensor
2845 * as in the case of CalculateMagneticShielding().
2846 * \param *P Problem at hand
2847 * \note Lots of arrays are used temporarily during the routine for the fft'ed Current density tensor.
2848 * \note MagneticSusceptibility is needed for G=0-component and thus has to be computed beforehand
2849 */
2850void CalculateChemicalShieldingByReciprocalCurrentDensity(struct Problem *P)
2851{
2852 struct RunStruct *R = &P->R;
2853 struct Lattice *Lat = &P->Lat;
2854 struct LatticeLevel *Lev0 = R->Lev0;
2855 struct Ions *I = &P->Ion;
2856 struct Density *Dens0 = Lev0->Dens;
2857 struct OneGData *GArray = Lev0->GArray;
2858 struct fft_plan_3d *plan = Lat->plan;
2859 fftw_real *CurrentDensity[NDIM*NDIM];
2860 fftw_complex *CurrentDensityC[NDIM*NDIM];
2861 fftw_complex *work = (fftw_complex *)Dens0->DensityCArray[TempDensity];
2862 //fftw_complex *sigma_imag = (fftw_complex *)Dens0->DensityCArray[Temp2Density];
2863 //fftw_real *sigma_real = (fftw_real *)sigma_imag;
2864 fftw_complex *sigma_imag[NDIM_NDIM];
2865 fftw_real *sigma_real[NDIM_NDIM];
2866 double sigma,Sigma;
2867 int it, ion, in, dex, g, n[2][NDIM], Index, i;
2868 //const double FFTfactor = 1.;///Lev0->MaxN;
2869 double eta, delta_sigma, S, A, iso, tmp;
2870 FILE *SigmaFile;
2871 char suffixsigma[255];
2872 double x[2][NDIM];
2873 const int myPE = P->Par.me_comm_ST_Psi;
2874 int N[NDIM];
2875 int cross_lookup[4]; // cross lookup table
2876 N[0] = Lev0->Plan0.plan->N[0];
2877 N[1] = Lev0->Plan0.plan->N[1];
2878 N[2] = Lev0->Plan0.plan->N[2];
2879 const int N0 = Lev0->Plan0.plan->local_nx;
2880 const double factorDC = R->FactorDensityC;
2881 gsl_matrix_complex *H = gsl_matrix_complex_calloc(NDIM,NDIM);
2882
2883 time_t seconds;
2884 time(&seconds); // get current time
2885
2886 // inverse Fourier transform current densities
2887 CurrentDensityC[0] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity0];
2888 CurrentDensityC[1] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity1];
2889 CurrentDensityC[2] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity2];
2890 CurrentDensityC[3] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity3];
2891 CurrentDensityC[4] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity4];
2892 CurrentDensityC[5] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity5];
2893 CurrentDensityC[6] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity6];
2894 CurrentDensityC[7] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity7];
2895 CurrentDensityC[8] = (fftw_complex *) Dens0->DensityCArray[CurrentDensity8];
2896 // don't put the following stuff into a for loop, they are not continuous! (preprocessor values CurrentDensity.)
2897 CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
2898 CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
2899 CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
2900 CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
2901 CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
2902 CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
2903 CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
2904 CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
2905 CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
2906
2907 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Checking J_{ij} (G=0) = 0 for each i,j ... \n",P->Par.me);
2908 for (in=0;in<NDIM*NDIM;in++) {
2909 CalculateOneDensityC(Lat, R->LevS, Dens0, CurrentDensity[in], CurrentDensityC[in], factorDC);
2910 tmp = sqrt(CurrentDensityC[in][0].re*CurrentDensityC[in][0].re+CurrentDensityC[in][0].im*CurrentDensityC[in][0].im);
2911 if (GArray[0].GSq < MYEPSILON) {
2912 if (in % NDIM == 0) fprintf(stderr,"(%i) ",P->Par.me);
2913 if (tmp > MYEPSILON) {
2914 fprintf(stderr,"J_{%i,%i} = |%e + i%e| < %e ? (%e)\t", in / NDIM, in%NDIM, CurrentDensityC[in][0].re, CurrentDensityC[in][0].im, MYEPSILON, tmp - MYEPSILON);
2915 } else {
2916 fprintf(stderr,"J_{%i,%i} ok\t", in / NDIM, in%NDIM);
2917 }
2918 if (in % NDIM == (NDIM-1)) fprintf(stderr,"\n");
2919 }
2920 }
2921
2922 for (in=0;in<NDIM*NDIM;in++) {
2923 LockDensityArray(Dens0,in,real); // Psi1R
2924 sigma_imag[in] = (fftw_complex *) Dens0->DensityArray[in];
2925 sigma_real[in] = (fftw_real *) sigma_imag[in];
2926 }
2927
2928 LockDensityArray(Dens0,TempDensity,imag); // work
2929 LockDensityArray(Dens0,Temp2Density,imag); // tempdestRC and field
2930 // go through reciprocal nodes and calculate shielding tensor sigma
2931 for (in=0; in<NDIM; in++) {// index i of vector component in integrand
2932 for(dex=0;dex<4;dex++) // initialise cross lookup
2933 cross_lookup[dex] = cross(in,dex);
2934 for (dex=0; dex<NDIM; dex++) { // index j of B component derivation in current density tensor
2935 //if (tempdestRC != (fftw_complex *)Dens0->DensityCArray[Temp2Density]) Error(SomeError,"CalculateChemicalShieldingByReciprocalCurrentDensity: tempdestRC corrupted");
2936 SetArrayToDouble0((double *)sigma_imag[in+dex*NDIM],Dens0->TotalSize*2);
2937 for (g=0; g < Lev0->MaxG; g++)
2938 if (GArray[g].GSq > MYEPSILON) { // skip due to divisor
2939 Index = GArray[g].Index; // re = im, im = -re due to "i" in formula
2940 //if (tempdestRC != (fftw_complex *)Dens0->DensityCArray[Temp2Density] || Index<0 || Index>=Dens0->LocalSizeC) Error(SomeError,"CalculateChemicalShieldingByReciprocalCurrentDensity: tempdestRC corrupted");
2941 sigma_imag[in+dex*NDIM][Index].re = GArray[g].G[cross_lookup[0]] * (-CurrentDensityC[dex*NDIM+cross_lookup[1]][Index].im)/GArray[g].GSq;//*FFTfactor;
2942 sigma_imag[in+dex*NDIM][Index].re -= GArray[g].G[cross_lookup[2]] * (-CurrentDensityC[dex*NDIM+cross_lookup[3]][Index].im)/GArray[g].GSq;//*FFTfactor;
2943 sigma_imag[in+dex*NDIM][Index].im = GArray[g].G[cross_lookup[0]] * ( CurrentDensityC[dex*NDIM+cross_lookup[1]][Index].re)/GArray[g].GSq;//*FFTfactor;
2944 sigma_imag[in+dex*NDIM][Index].im -= GArray[g].G[cross_lookup[2]] * ( CurrentDensityC[dex*NDIM+cross_lookup[3]][Index].re)/GArray[g].GSq;//*FFTfactor;
2945 } else { // G=0-component stems from magnetic susceptibility
2946 sigma_imag[in+dex*NDIM][GArray[g].Index].re = 2./3.*I->I[0].chi[in+dex*NDIM];//-4.*M_PI*(0.5*I->I[0].chi[0+0*NDIM]+0.5*I->I[0].chi[1+1*NDIM]+2./3.*I->I[0].chi[2+2*NDIM]);
2947 }
2948 for (g=0; g<Lev0->MaxDoubleG; g++) { // apply symmetry
2949 //if (tempdestRC != (fftw_complex *)Dens0->DensityCArray[Temp2Density] || Lev0->DoubleG[2*g+1]<0 || Lev0->DoubleG[2*g+1]>=Dens0->LocalSizeC) Error(SomeError,"CalculateChemicalShieldingByReciprocalCurrentDensity: tempdestRC corrupted");
2950 sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g+1]].re = sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g]].re;
2951 sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g+1]].im = -sigma_imag[in+dex*NDIM][Lev0->DoubleG[2*g]].im;
2952 }
2953 // fourier transformation of sigma
2954 //if (tempdestRC != (fftw_complex *)Dens0->DensityCArray[Temp2Density]) Error(SomeError,"CalculateChemicalShieldingByReciprocalCurrentDensity: tempdestRC corrupted");
2955 fft_3d_complex_to_real(plan, Lev0->LevelNo, FFTNF1, sigma_imag[in+dex*NDIM], work);
2956
2957 for (it=0; it < I->Max_Types; it++) { // integration over all types
2958 for (ion=0; ion < I->I[it].Max_IonsOfType; ion++) { // and each ion of type
2959 // read transformed sigma at core position and MPI_Allreduce
2960 for (g=0;g<NDIM;g++) {
2961 n[0][g] = floor(I->I[it].R[NDIM*ion+g]/sqrt(Lat->RealBasisSQ[g])*(double)N[g]);
2962 n[1][g] = ceil(I->I[it].R[NDIM*ion+g]/sqrt(Lat->RealBasisSQ[g])*(double)N[g]);
2963 x[1][g] = I->I[it].R[NDIM*ion+g]/sqrt(Lat->RealBasisSQ[g])*(double)N[g] - (double)n[0][g];
2964 x[0][g] = 1. - x[1][g];
2965 //fprintf(stderr,"(%i) n_floor[%i] = %i\tn_ceil[%i] = %i --- x_floor[%i] = %e\tx_ceil[%i] = %e\n",P->Par.me, g,n[0][g], g,n[1][g], g,x[0][g], g,x[1][g]);
2966 }
2967 sigma = 0.;
2968 for (i=0;i<2;i++) { // interpolate linearly between adjacent grid points per axis
2969 if ((n[i][0] >= N0*myPE) && (n[i][0] < N0*(myPE+1))) {
2970// fprintf(stderr,"(%i) field[%i]: sigma = %e\n", P->Par.me, n[i][2]+N[2]*(n[i][1]+N[1]*(n[i][0]-N0*myPE)), sigma);
2971 sigma += (x[i][0]*x[0][1]*x[0][2])*sigma_real[in+dex*NDIM][n[0][2]+N[2]*(n[0][1]+N[1]*(n[i][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
2972 //fprintf(stderr,"(%i) field[%i]: sigma += %e * %e \n", P->Par.me, n[i][2]+N[2]*(n[i][1]+N[1]*(n[i][0]-N0*myPE)), (x[i][0]*x[0][1]*x[0][2]), field[n[0][2]+N[2]*(n[0][1]+N[1]*(n[i][0]-N0*myPE))]*mu0);
2973 sigma += (x[i][0]*x[0][1]*x[1][2])*sigma_real[in+dex*NDIM][n[1][2]+N[2]*(n[0][1]+N[1]*(n[i][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
2974 //fprintf(stderr,"(%i) field[%i]: sigma += %e * %e \n", P->Par.me, n[i][2]+N[2]*(n[i][1]+N[1]*(n[i][0]-N0*myPE)), (x[i][0]*x[0][1]*x[1][2]), field[n[1][2]+N[2]*(n[0][1]+N[1]*(n[i][0]-N0*myPE))]*mu0);
2975 sigma += (x[i][0]*x[1][1]*x[0][2])*sigma_real[in+dex*NDIM][n[0][2]+N[2]*(n[1][1]+N[1]*(n[i][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
2976 //fprintf(stderr,"(%i) field[%i]: sigma += %e * %e \n", P->Par.me, n[i][2]+N[2]*(n[i][1]+N[1]*(n[i][0]-N0*myPE)), (x[i][0]*x[1][1]*x[0][2]), field[n[0][2]+N[2]*(n[1][1]+N[1]*(n[i][0]-N0*myPE))]*mu0);
2977 sigma += (x[i][0]*x[1][1]*x[1][2])*sigma_real[in+dex*NDIM][n[1][2]+N[2]*(n[1][1]+N[1]*(n[i][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
2978 //fprintf(stderr,"(%i) field[%i]: sigma += %e * %e \n", P->Par.me, n[i][2]+N[2]*(n[i][1]+N[1]*(n[i][0]-N0*myPE)), (x[i][0]*x[1][1]*x[1][2]), field[n[1][2]+N[2]*(n[1][1]+N[1]*(n[i][0]-N0*myPE))]*mu0);
2979 }
2980 }
2981 sigma *= -R->FactorDensityR; // factor from inverse fft? (and its defined as negative proportionaly factor)
2982 MPI_Allreduce ( &sigma, &Sigma, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum local to total
2983 I->I[it].sigma_rezi[ion][in+dex*NDIM] = Sigma;
2984 }
2985 }
2986 // fabs() all sigma values, as we need them as a positive density: OutputVis plots them in logarithmic scale and
2987 // thus cannot deal with negative values!
2988 for (i=0; i< Dens0->LocalSizeR; i++)
2989 sigma_real[in+dex*NDIM][i] = fabs(sigma_real[in+dex*NDIM][i]);
2990 }
2991 }
2992 UnLockDensityArray(Dens0,TempDensity,imag); // work
2993 UnLockDensityArray(Dens0,Temp2Density,imag); // tempdestRC and field
2994
2995 // output tensor to file
2996 if (P->Par.me == 0) {
2997 sprintf(&suffixsigma[0], ".sigma_chi_rezi.L%i.csv", Lev0->LevelNo);
2998 OpenFile(P, &SigmaFile, suffixsigma, "a", P->Call.out[ReadOut]);
2999 fprintf(SigmaFile,"# chemical shielding tensor sigma_rezi[01,02,03,10,11,12,20,21,22], seed %i, config %s, run on %s", R->Seed, P->Files.default_path, ctime(&seconds));
3000 fprintf(SigmaFile,"%lg\t", P->Lat.ECut/(Lat->LevelSizes[0]*Lat->LevelSizes[0]));
3001 for (in=0;in<NDIM;in++)
3002 for (dex=0;dex<NDIM;dex++)
3003 fprintf(SigmaFile,"%e\t", GSL_REAL(gsl_matrix_complex_get(H,in,dex)));
3004 fprintf(SigmaFile,"\n");
3005 fclose(SigmaFile);
3006 }
3007
3008 gsl_vector *eval = gsl_vector_alloc(NDIM);
3009 gsl_eigen_herm_workspace *w = gsl_eigen_herm_alloc(NDIM);
3010
3011 for (it=0; it < I->Max_Types; it++) { // integration over all types
3012 for (ion=0; ion < I->I[it].Max_IonsOfType; ion++) { // and each ion of type
3013 if (P->Call.out[ValueOut]) fprintf(stderr,"(%i) Shielding Tensor for Ion %i of element %s \\sigma_ij = \n",P->Par.me, ion, I->I[it].Name);
3014 for (in=0; in<NDIM; in++) { // index i of vector component in integrand
3015 for (dex=0; dex<NDIM; dex++) {// index j of B component derivation in current density tensor
3016 gsl_matrix_complex_set(H,in,dex,gsl_complex_rect((I->I[it].sigma_rezi[ion][in+dex*NDIM]+I->I[it].sigma_rezi[ion][dex+in*NDIM])/2.,0));
3017 if (P->Call.out[ValueOut]) fprintf(stderr,"%e\t", I->I[it].sigma_rezi[ion][in+dex*NDIM]);
3018 }
3019 if (P->Call.out[ValueOut]) fprintf(stderr,"\n");
3020 }
3021 // output tensor to file
3022 if (P->Par.me == 0) {
3023 sprintf(&suffixsigma[0], ".sigma_i%i_%s_rezi.L%i.csv", ion, I->I[it].Symbol, Lev0->LevelNo);
3024 OpenFile(P, &SigmaFile, suffixsigma, "a", P->Call.out[ReadOut]);
3025 fprintf(SigmaFile,"# chemical shielding tensor sigma_rezi[01,02,03,10,11,12,20,21,22], seed %i, config %s, run on %s", R->Seed, P->Files.default_path, ctime(&seconds));
3026 fprintf(SigmaFile,"%lg\t", P->Lat.ECut/(Lat->LevelSizes[0]*Lat->LevelSizes[0]));
3027 for (in=0;in<NDIM;in++)
3028 for (dex=0;dex<NDIM;dex++)
3029 fprintf(SigmaFile,"%e\t", I->I[it].sigma_rezi[ion][in+dex*NDIM]);
3030 fprintf(SigmaFile,"\n");
3031 fclose(SigmaFile);
3032 }
3033 // diagonalize sigma
3034 gsl_eigen_herm(H, eval, w);
3035 gsl_sort_vector(eval); // sort eigenvalues
3036// print eigenvalues
3037// if (P->Call.out[ValueOut]) {
3038// fprintf(stderr,"(%i) diagonal shielding for Ion %i of element %s:", P->Par.me, ion, I->I[it].Name);
3039// for (in=0;in<NDIM;in++)
3040// fprintf(stderr,"\t%lg",gsl_vector_get(eval,in));
3041// fprintf(stderr,"\n\n");
3042// }
3043 iso = 0.;
3044 for (i=0;i<NDIM;i++) {
3045 I->I[it].sigma_rezi_PAS[ion][i] = gsl_vector_get(eval,i);
3046 iso += I->I[it].sigma_rezi[ion][i+i*NDIM]/3.;
3047 }
3048 eta = (gsl_vector_get(eval,1)-gsl_vector_get(eval,0))/(gsl_vector_get(eval,2)-iso);
3049 delta_sigma = gsl_vector_get(eval,2) - 0.5*(gsl_vector_get(eval,0)+gsl_vector_get(eval,1));
3050 S = (delta_sigma*delta_sigma)*(1+1./3.*eta*eta);
3051 A = 0.;
3052 for (i=0;i<NDIM;i++) {
3053 in = cross(i,0);
3054 dex = cross(i,1);
3055 A += pow(-1,i)*pow(0.5*(I->I[it].sigma_rezi[ion][in+dex*NDIM]-I->I[it].sigma_rezi[ion][dex+in*NDIM]),2);
3056 }
3057 if (P->Call.out[ValueOut]) {
3058 fprintf(stderr,"(%i) converted to Principal Axis System\n==================\nDiagonal entries:", P->Par.me);
3059 for (i=0;i<NDIM;i++)
3060 fprintf(stderr,"\t%lg",gsl_vector_get(eval,i));
3061 fprintf(stderr,"\nshielding : %e\n", iso);
3062 fprintf(stderr,"anisotropy : %e\n", delta_sigma);
3063 fprintf(stderr,"asymmetry : %e\n", eta);
3064 fprintf(stderr,"S : %e\n", S);
3065 fprintf(stderr,"A : %e\n", A);
3066 fprintf(stderr,"==================\n");
3067
3068 }
3069 }
3070 }
3071
3072 // Output of magnetic field densities for each direction
3073 for (i=0;i<NDIM*NDIM;i++)
3074 OutputVis(P, sigma_real[i]);
3075 // Diagonalizing the tensor "field" B_ij [r]
3076 fprintf(stderr,"(%i) Diagonalizing B_ij [r] ... \n", P->Par.me);
3077 for (i=0; i< Dens0->LocalSizeR; i++) {
3078 for (in=0; in<NDIM; in++) // index i of vector component in integrand
3079 for (dex=0; dex<NDIM; dex++) { // index j of B component derivation in current density tensor
3080 //fprintf(stderr,"(%i) Setting B_(%i,%i)[%i] ... \n", P->Par.me, in,dex,i);
3081 gsl_matrix_complex_set(H,in,dex,gsl_complex_rect((sigma_real[in+dex*NDIM][i]+sigma_real[dex+in*NDIM][i])/2.,0));
3082 }
3083 gsl_eigen_herm(H, eval, w);
3084 gsl_sort_vector(eval); // sort eigenvalues
3085 for (in=0;in<NDIM;in++)
3086 sigma_real[in][i] = gsl_vector_get(eval,in);
3087 }
3088 // Output of diagonalized magnetic field densities for each direction
3089 for (i=0;i<NDIM;i++)
3090 OutputVis(P, sigma_real[i]);
3091 for (i=0;i<NDIM*NDIM;i++)
3092 UnLockDensityArray(Dens0,i,real); // sigma_imag/real free
3093
3094 gsl_eigen_herm_free(w);
3095 gsl_vector_free(eval);
3096 gsl_matrix_complex_free(H);
3097}
3098
3099
3100/** Calculates the chemical shielding tensor at the positions of the nuclei.
3101 * The chemical shielding tensor at position R is defined as the proportionality factor between the induced and
3102 * the externally applied field.
3103 * \f[
3104 * \sigma_{ij} (R) = \frac{\delta B_j^{ind} (R)}{\delta B_i^{ext}}
3105 * = \frac{\mu_0}{4 \pi} \int d^3 r' \left ( \frac{r'-r}{| r' - r |^3} \times J_i (r') \right )_j
3106 * \f]
3107 * One after another for each nuclear position is the tensor evaluated and the result printed
3108 * to screen. Tensor is diagonalized afterwards.
3109 * \param *P Problem at hand
3110 * \sa CalculateMagneticSusceptibility() - similar calculation, yet without translation to ion centers.
3111 * \warning This routine is out-dated due to being numerically unstable because of the singularity which is not
3112 * considered carefully, recommendend replacement is CalculateChemicalShieldingByReciprocalCurrentDensity().
3113 */
3114void CalculateChemicalShielding(struct Problem *P)
3115{
3116 struct RunStruct *R = &P->R;
3117 struct Lattice *Lat = &P->Lat;
3118 struct LatticeLevel *Lev0 = R->Lev0;
3119 struct Density *Dens0 = R->Lev0->Dens;
3120 struct Ions *I = &P->Ion;
3121 double sigma[NDIM*NDIM],Sigma[NDIM*NDIM];
3122 fftw_real *CurrentDensity[NDIM*NDIM];
3123 int it, ion, in, dex, i0, n[NDIM], n0, i;//, *NUp;
3124 double x,y,z;
3125 double dist;
3126 double r[NDIM], fac[NDIM];
3127 const double discrete_factor = Lat->Volume/Lev0->MaxN;
3128 double eta, delta_sigma, S, A, iso;
3129 const int myPE = P->Par.me_comm_ST_Psi;
3130 int N[NDIM];
3131 N[0] = Lev0->Plan0.plan->N[0];
3132 N[1] = Lev0->Plan0.plan->N[1];
3133 N[2] = Lev0->Plan0.plan->N[2];
3134 const int N0 = Lev0->Plan0.plan->local_nx;
3135 FILE *SigmaFile;
3136 char suffixsigma[255];
3137 time_t seconds;
3138 time(&seconds); // get current time
3139
3140 // set pointers onto current density
3141 CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
3142 CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
3143 CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
3144 CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
3145 CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
3146 CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
3147 CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
3148 CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
3149 CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
3150 gsl_matrix_complex *H = gsl_matrix_complex_calloc(NDIM,NDIM);
3151
3152 for (it=0; it < I->Max_Types; it++) { // integration over all types
3153 for (ion=0; ion < I->I[it].Max_IonsOfType; ion++) { // and each ion of type
3154 if (P->Call.out[ValueOut]) fprintf(stderr,"(%i) Shielding Tensor for Ion %i of element %s \\sigma_ij = \n",P->Par.me, ion, I->I[it].Name);
3155 for (in=0; in<NDIM; in++) {// index i of vector component in integrand
3156 for (dex=0; dex<NDIM; dex++) { // index j of B component derivation in current density tensor
3157 sigma[in+dex*NDIM] = 0.;
3158
3159 for(n0=0;n0<N0;n0++) // do the integration over real space
3160 for(n[1]=0;n[1]<N[1];n[1]++)
3161 for(n[2]=0;n[2]<N[2];n[2]++) {
3162 n[0]=n0 + N0*myPE; // global relative coordinate: due to partitoning of x-axis in PEPGamma>1 case
3163 fac[0] = (double)n[0]/(double)N[0];
3164 fac[1] = (double)n[1]/(double)N[1];
3165 fac[2] = (double)n[2]/(double)N[2];
3166 RMat33Vec3(r, Lat->RealBasis, fac);
3167 i0 = n[2]+N[2]*(n[1]+N[1]*(n0)); // the index of current density must match LocalSizeR!
3168 x = MinImageConv(Lat,r[cross(in,0)], I->I[it].R[NDIM*ion+cross(in,0)],cross(in,0));
3169 y = MinImageConv(Lat,r[cross(in,2)], I->I[it].R[NDIM*ion+cross(in,2)],cross(in,2));
3170 z = MinImageConv(Lat,r[in], I->I[it].R[NDIM*ion+in],in); // "in" always is missing third component in cross product
3171 dist = pow(x*x + y*y + z*z, 3./2.);
3172 if ((dist < pow(2.,3.)) && (dist > MYEPSILON)) sigma[in+dex*NDIM] += (x * CurrentDensity[dex*NDIM+cross(in,1)][i0] - y * CurrentDensity[dex*NDIM+cross(in,3)][i0])/dist;
3173 //if (it == 0 && ion == 0) fprintf(stderr,"(%i) sigma[%i][%i] += (%e * %e - %e * %e)/%e = %e\n", P->Par.me, in, dex, x,CurrentDensity[dex*NDIM+cross(in,1)][i0],y,CurrentDensity[dex*NDIM+cross(in,3)][i0],dist,sigma[in+dex*NDIM]);
3174 }
3175 sigma[in+dex*NDIM] *= -mu0*discrete_factor/(4.*PI); // due to summation instead of integration
3176 MPI_Allreduce ( &sigma[in+dex*NDIM], &Sigma[in+dex*NDIM], 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum "LocalSize to TotalSize"
3177 I->I[it].sigma[ion][in+dex*NDIM] = Sigma[in+dex*NDIM];
3178 if (P->Call.out[ValueOut]) fprintf(stderr," %e", Sigma[in+dex*NDIM]);
3179 }
3180 if (P->Call.out[ValueOut]) fprintf(stderr,"\n");
3181 }
3182 // store symmetrized matrix
3183 for (in=0;in<NDIM;in++)
3184 for (dex=0;dex<NDIM;dex++)
3185 gsl_matrix_complex_set(H,in,dex,gsl_complex_rect((Sigma[in+dex*NDIM]+Sigma[dex+in*NDIM])/2.,0));
3186 // output tensor to file
3187 if (P->Par.me == 0) {
3188 sprintf(&suffixsigma[0], ".sigma_i%i_%s.L%i.csv", ion, I->I[it].Symbol, Lev0->LevelNo);
3189 OpenFile(P, &SigmaFile, suffixsigma, "a", P->Call.out[ReadOut]);
3190 fprintf(SigmaFile,"# chemical shielding tensor sigma[01,02,03,10,11,12,20,21,22], seed %i, config %s, run on %s", R->Seed, P->Files.default_path, ctime(&seconds));
3191 fprintf(SigmaFile,"%lg\t", P->Lat.ECut/(Lat->LevelSizes[0]*Lat->LevelSizes[0]));
3192 for (in=0;in<NDIM*NDIM;in++)
3193 fprintf(SigmaFile,"%e\t", Sigma[in]);
3194 fprintf(SigmaFile,"\n");
3195 fclose(SigmaFile);
3196 }
3197 // diagonalize sigma
3198 gsl_vector *eval = gsl_vector_alloc(NDIM);
3199 gsl_eigen_herm_workspace *w = gsl_eigen_herm_alloc(NDIM);
3200 gsl_eigen_herm(H, eval, w);
3201 gsl_eigen_herm_free(w);
3202 gsl_sort_vector(eval); // sort eigenvalues
3203 // print eigenvalues
3204// if (P->Call.out[ValueOut]) {
3205// fprintf(stderr,"(%i) diagonal shielding for Ion %i of element %s:", P->Par.me, ion, I->I[it].Name);
3206// for (in=0;in<NDIM;in++)
3207// fprintf(stderr,"\t%lg",gsl_vector_get(eval,in));
3208// fprintf(stderr,"\n\n");
3209// }
3210 // print eigenvalues
3211 iso = 0;
3212 for (i=0;i<NDIM;i++) {
3213 I->I[it].sigma[ion][i] = gsl_vector_get(eval,i);
3214 iso += Sigma[i+i*NDIM]/3.;
3215 }
3216 eta = (gsl_vector_get(eval,1)-gsl_vector_get(eval,0))/(gsl_vector_get(eval,2)-iso);
3217 delta_sigma = gsl_vector_get(eval,2) - 0.5*(gsl_vector_get(eval,0)+gsl_vector_get(eval,1));
3218 S = (delta_sigma*delta_sigma)*(1+1./3.*eta*eta);
3219 A = 0.;
3220 for (i=0;i<NDIM;i++) {
3221 in = cross(i,0);
3222 dex = cross(i,1);
3223 A += pow(-1,i)*pow(0.5*(Sigma[in+dex*NDIM]-Sigma[dex+in*NDIM]),2);
3224 }
3225 if (P->Call.out[ValueOut]) {
3226 fprintf(stderr,"(%i) converted to Principal Axis System\n==================\nDiagonal entries:", P->Par.me);
3227 for (i=0;i<NDIM;i++)
3228 fprintf(stderr,"\t%lg",gsl_vector_get(eval,i));
3229 fprintf(stderr,"\nshielding : %e\n", iso);
3230 fprintf(stderr,"anisotropy : %e\n", delta_sigma);
3231 fprintf(stderr,"asymmetry : %e\n", eta);
3232 fprintf(stderr,"S : %e\n", S);
3233 fprintf(stderr,"A : %e\n", A);
3234 fprintf(stderr,"==================\n");
3235
3236 }
3237 gsl_vector_free(eval);
3238 }
3239 }
3240
3241 gsl_matrix_complex_free(H);
3242}
3243
3244/** Test if integrated current over cell is 0.
3245 * In most cases we do not reach a numerical sensible zero as in MYEPSILON and remain satisfied as long
3246 * as the integrated current density is very small (e.g. compared to single entries in the current density array)
3247 * \param *P Problem at hand
3248 * \param index index of current component
3249 * \sa CalculateNativeIntDens() for integration of one current tensor component
3250 */
3251 void TestCurrent(struct Problem *P, const int index)
3252{
3253 struct RunStruct *R = &P->R;
3254 struct LatticeLevel *Lev0 = R->Lev0;
3255 struct Density *Dens0 = Lev0->Dens;
3256 fftw_real *CurrentDensity[NDIM*NDIM];
3257 int in;
3258 double result[NDIM*NDIM], res = 0.;
3259
3260 // set pointers onto current density array and get number of grid points in each direction
3261 CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
3262 CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
3263 CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
3264 CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
3265 CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
3266 CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
3267 CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
3268 CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
3269 CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
3270 for(in=0;in<NDIM;in++) {
3271 result[in] = CalculateNativeIntDens(P,Lev0,CurrentDensity[in + NDIM*index],R->FactorDensityR);
3272 res += pow(result[in],2.);
3273 }
3274 res = sqrt(res);
3275 // if greater than 0, complain about it
3276 if ((res > MYEPSILON) && (P->Call.out[LeaderOut]))
3277 fprintf(stderr, "(%i) \\int_\\Omega d^3 r j_%i(r) = (%e,%e,%e), %e > %e!\n",P->Par.me, index, result[0], result[1], result[2], res, MYEPSILON);
3278}
3279
3280/** Testing whether re<->im switches (due to symmetry) confuses fft.
3281 * \param *P Problem at hand
3282 * \param l local wave function number
3283 */
3284void test_fft_symmetry(struct Problem *P, const int l)
3285{
3286 struct Lattice *Lat = &P->Lat;
3287 struct RunStruct *R = &P->R;
3288 struct LatticeLevel *LevS = R->LevS;
3289 struct LatticeLevel *Lev0 = R->Lev0;
3290 struct Density *Dens0 = Lev0->Dens;
3291 struct fft_plan_3d *plan = Lat->plan;
3292 fftw_complex *tempdestRC = (fftw_complex *)Dens0->DensityCArray[Temp2Density];
3293 fftw_complex *work = Dens0->DensityCArray[TempDensity];
3294 fftw_complex *workC = (fftw_complex *)Dens0->DensityArray[TempDensity];
3295 fftw_complex *posfac, *destpos, *destRCS, *destRCD;
3296 fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
3297 fftw_real *PsiCR = (fftw_real *) PsiC;
3298 fftw_complex *Psi0 = LevS->LPsi->LocalPsi[l];
3299 fftw_complex *dest = LevS->LPsi->TempPsi;
3300 fftw_real *Psi0R = (fftw_real *)Dens0->DensityArray[Temp2Density];
3301 int i,Index, pos, i0, iS,g; //, NoOfPsis = Psi->TypeStartIndex[UnOccupied] - Psi->TypeStartIndex[Occupied];
3302 int n[NDIM], n0;
3303 const int N0 = LevS->Plan0.plan->local_nx; // we don't want to build global density, but local
3304 int N[NDIM], NUp[NDIM];
3305 N[0] = LevS->Plan0.plan->N[0];
3306 N[1] = LevS->Plan0.plan->N[1];
3307 N[2] = LevS->Plan0.plan->N[2];
3308 NUp[0] = LevS->NUp[0];
3309 NUp[1] = LevS->NUp[1];
3310 NUp[2] = LevS->NUp[2];
3311 //const int k_normal = Lat->Psi.TypeStartIndex[Occupied] + (l - Lat->Psi.TypeStartIndex[R->CurrentMin]);
3312 //const double *Wcentre = Lat->Psi.AddData[k_normal].WannierCentre;
3313 //double x[NDIM], fac[NDIM];
3314 double result1=0., result2=0., result3=0., result4=0.;
3315 double Result1=0., Result2=0., Result3=0., Result4=0.;
3316 const double HGcRCFactor = 1./LevS->MaxN; // factor for inverse fft
3317
3318
3319 // fft to real space
3320 SetArrayToDouble0((double *)tempdestRC, Dens0->TotalSize*2);
3321 SetArrayToDouble0((double *)PsiC, Dens0->TotalSize*2);
3322 for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is positive
3323 Index = LevS->GArray[i].Index;
3324 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
3325 destpos = &tempdestRC[LevS->MaxNUp*Index];
3326 for (pos=0; pos < LevS->MaxNUp; pos++) {
3327 destpos[pos].re = (Psi0[i].re)*posfac[pos].re-(Psi0[i].im)*posfac[pos].im;
3328 destpos[pos].im = (Psi0[i].re)*posfac[pos].im+(Psi0[i].im)*posfac[pos].re;
3329 //destpos[pos].re = (Psi0[i].im)*posfac[pos].re-(-Psi0[i].re)*posfac[pos].im;
3330 //destpos[pos].im = (Psi0[i].im)*posfac[pos].im+(-Psi0[i].re)*posfac[pos].re;
3331 }
3332 }
3333 for (i=0; i<LevS->MaxDoubleG; i++) {
3334 destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
3335 destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
3336 for (pos=0; pos < LevS->MaxNUp; pos++) {
3337 destRCD[pos].re = destRCS[pos].re;
3338 destRCD[pos].im = -destRCS[pos].im;
3339 }
3340 }
3341 fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
3342 DensityRTransformPos(LevS,(fftw_real*)tempdestRC, Psi0R);
3343
3344 // apply position operator and do first result
3345 for (n0=0;n0<N0;n0++) // only local points on x axis
3346 for (n[1]=0;n[1]<N[1];n[1]++)
3347 for (n[2]=0;n[2]<N[2];n[2]++) {
3348 n[0]=n0 + LevS->Plan0.plan->start_nx; // global relative coordinate: due to partitoning of x-axis in PEPGamma>1 case
3349 i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
3350 iS = n[2]+N[2]*(n[1]+N[1]*n0);
3351 //x[0] += 1; // shifting expectation value of x coordinate from 0 to 1
3352 PsiCR[iS] = Psi0R[i0]; // truedist(Lat, x[0], Wcentre[0],0) *
3353 result1 += PsiCR[iS] * Psi0R[i0];
3354 }
3355 result1 /= LevS->MaxN; // factor due to discrete integration
3356 MPI_Allreduce ( &result1, &Result1, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum "LocalSize to TotalSize"
3357 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 1st result: %e\n",P->Par.me, Result1);
3358
3359 // fft to reciprocal space and do second result
3360 fft_3d_real_to_complex(plan, LevS->LevelNo, FFTNF1, PsiC, workC);
3361 SetArrayToDouble0((double *)dest, 2*R->InitLevS->MaxG);
3362 for (g=0; g < LevS->MaxG; g++) {
3363 Index = LevS->GArray[g].Index;
3364 dest[g].re = (Psi0[Index].re)*HGcRCFactor;
3365 dest[g].im = (Psi0[Index].im)*HGcRCFactor;
3366 }
3367 result2 = GradSP(P,LevS,Psi0,dest);
3368 MPI_Allreduce ( &result2, &Result2, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum "LocalSize to TotalSize"
3369 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 2nd result: %e\n",P->Par.me, Result2);
3370
3371 // fft again to real space, this time change symmetry
3372 SetArrayToDouble0((double *)tempdestRC, Dens0->TotalSize*2);
3373 SetArrayToDouble0((double *)PsiC, Dens0->TotalSize*2);
3374 for (i=0;i<LevS->MaxG;i++) { // incoming is positive, outgoing is positive
3375 Index = LevS->GArray[i].Index;
3376 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
3377 destpos = &tempdestRC[LevS->MaxNUp*Index];
3378 for (pos=0; pos < LevS->MaxNUp; pos++) {
3379 destpos[pos].re = (Psi0[i].im)*posfac[pos].re-(-Psi0[i].re)*posfac[pos].im;
3380 destpos[pos].im = (Psi0[i].im)*posfac[pos].im+(-Psi0[i].re)*posfac[pos].re;
3381 }
3382 }
3383 for (i=0; i<LevS->MaxDoubleG; i++) {
3384 destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
3385 destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
3386 for (pos=0; pos < LevS->MaxNUp; pos++) {
3387 destRCD[pos].re = destRCS[pos].re;
3388 destRCD[pos].im = -destRCS[pos].im;
3389 }
3390 }
3391 fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
3392 DensityRTransformPos(LevS,(fftw_real*)tempdestRC, Psi0R);
3393
3394 // bring down from Lev0 to LevS
3395 for (n0=0;n0<N0;n0++) // only local points on x axis
3396 for (n[1]=0;n[1]<N[1];n[1]++)
3397 for (n[2]=0;n[2]<N[2];n[2]++) {
3398 i0 = n[2]*NUp[2]+N[2]*NUp[2]*(n[1]*NUp[1]+N[1]*NUp[1]*n0*NUp[0]);
3399 iS = n[2]+N[2]*(n[1]+N[1]*n0);
3400 PsiCR[iS] = Psi0R[i0]; // truedist(Lat, x[0], Wcentre[0],0) *
3401 result3 += PsiCR[iS] * Psi0R[i0];
3402 }
3403 result3 /= LevS->MaxN; // factor due to discrete integration
3404 MPI_Allreduce ( &result3, &Result3, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum "LocalSize to TotalSize"
3405 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 3rd result: %e\n",P->Par.me, Result3);
3406
3407 // fft back to reciprocal space, change symmetry back and do third result
3408 fft_3d_real_to_complex(plan, LevS->LevelNo, FFTNF1, PsiC, workC);
3409 SetArrayToDouble0((double *)dest, 2*R->InitLevS->MaxG);
3410 for (g=0; g < LevS->MaxG; g++) {
3411 Index = LevS->GArray[g].Index;
3412 dest[g].re = (-PsiC[Index].im)*HGcRCFactor;
3413 dest[g].im = ( PsiC[Index].re)*HGcRCFactor;
3414 }
3415 result4 = GradSP(P,LevS,Psi0,dest);
3416 MPI_Allreduce ( &result4, &Result4, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); // sum "LocalSize to TotalSize"
3417 if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) 4th result: %e\n",P->Par.me, Result4);
3418}
3419
3420
3421/** Test function to check RxP application.
3422 * Checks applied solution to an analytic for a specific and simple wave function -
3423 * where just one coefficient is unequal to zero.
3424 * \param *P Problem at hand
3425 exp(I b G) - I exp(I b G) b G - exp(I a G) + I exp(I a G) a G
3426 -------------------------------------------------------------
3427 2
3428 G
3429 */
3430void test_rxp(struct Problem *P)
3431{
3432 struct RunStruct *R = &P->R;
3433 struct Lattice *Lat = &P->Lat;
3434 //struct LatticeLevel *Lev0 = R->Lev0;
3435 struct LatticeLevel *LevS = R->LevS;
3436 struct OneGData *GA = LevS->GArray;
3437 //struct Density *Dens0 = Lev0->Dens;
3438 fftw_complex *Psi0 = LevS->LPsi->TempPsi;
3439 fftw_complex *Psi2 = P->Grad.GradientArray[GraSchGradient];
3440 fftw_complex *Psi3 = LevS->LPsi->TempPsi2;
3441 int g, g_bar, i, j, k, k_normal = 0;
3442 double tmp, a,b, G;
3443 //const double *Wcentre = Lat->Psi.AddData[k_normal].WannierCentre;
3444 const double discrete_factor = 1.;//Lat->Volume/LevS->MaxN;
3445 fftw_complex integral;
3446
3447 // reset coefficients
3448 debug (P,"Creating RxP test function.");
3449 SetArrayToDouble0((double *)Psi0,2*R->InitLevS->MaxG);
3450 SetArrayToDouble0((double *)Psi2,2*R->InitLevS->MaxG);
3451
3452 // pick one which becomes non-zero
3453 g = 3;
3454
3455 //for (g=0;g<LevS->MaxG;g++) {
3456 Psi0[g].re = 1.;
3457 Psi0[g].im = 0.;
3458 //}
3459 fprintf(stderr,"(%i) G[%i] = (%e,%e,%e) \n",P->Par.me, g, GA[g].G[0], GA[g].G[1], GA[g].G[2]);
3460 i = 0;
3461
3462 // calculate analytic result
3463 debug (P,"Calculating analytic solution.");
3464 for (g_bar=0;g_bar<LevS->MaxG;g_bar++) {
3465 for (g=0;g<LevS->MaxG;g++) {
3466 if (GA[g].G[i] == GA[g_bar].G[i]) {
3467 j = cross(i,0);
3468 k = cross(i,1);
3469 if (GA[g].G[k] == GA[g_bar].G[k]) {
3470 //b = truedist(Lat, sqrt(Lat->RealBasisSQ[j]), Wcentre[j], j);
3471 b = sqrt(Lat->RealBasisSQ[j]);
3472 //a = truedist(Lat, 0., Wcentre[j], j);
3473 a = 0.;
3474 G = 1; //GA[g].G[k];
3475 if (GA[g].G[j] == GA[g_bar].G[j]) {
3476 Psi2[g_bar].re += G*Psi0[g].re * (.5 * b * b - .5 * a * a) * discrete_factor;
3477 Psi2[g_bar].im += G*Psi0[g].im * (.5 * b * b - .5 * a * a) * discrete_factor;
3478 //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON)))
3479 //fprintf(stderr,"(%i) Psi[%i].re += %e +i %e\n",P->Par.me, g_bar, G*Psi0[g].re * (.5 * b * b - .5 * a * a) * discrete_factor, G*Psi0[g].im * (.5 * b * b - .5 * a * a) * discrete_factor);
3480 } else {
3481 tmp = GA[g].G[j]-GA[g_bar].G[j];
3482 integral.re = (cos(tmp*b)+sin(tmp*b)*b*tmp - cos(tmp*a)-sin(tmp*a)*a*tmp) / (tmp * tmp);
3483 integral.im = (sin(tmp*b)-cos(tmp*b)*b*tmp - sin(tmp*a)+cos(tmp*a)*a*tmp) / (tmp * tmp);
3484 Psi2[g_bar].re += G*(Psi0[g].re*integral.re - Psi0[g].im*integral.im) * discrete_factor;
3485 Psi2[g_bar].im += G*(Psi0[g].re*integral.im + Psi0[g].im*integral.re) * discrete_factor;
3486 //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON)))
3487 //fprintf(stderr,"(%i) Psi[%i].re += %e\tPsi[%i].im += %e \n",P->Par.me, g_bar, G*(Psi0[g].re*integral.re - Psi0[g].im*integral.im) * discrete_factor, g_bar, G*(Psi0[g].re*integral.im + Psi0[g].im*integral.re) * discrete_factor);
3488 }
3489 }
3490 j = cross(i,2);
3491 k = cross(i,3);
3492 if (GA[g].G[k] == GA[g_bar].G[k]) {
3493 //b = truedist(Lat, sqrt(Lat->RealBasisSQ[j]), Wcentre[j], j);
3494 b = sqrt(Lat->RealBasisSQ[j]);
3495 //a = truedist(Lat, 0., Wcentre[j], j);
3496 a = 0.;
3497 G = 1; //GA[g].G[k];
3498 if (GA[g].G[j] == GA[g_bar].G[j]) {
3499 Psi2[g_bar].re += G*Psi0[g].re * (.5 * b * b - .5 * a * a) * discrete_factor;
3500 Psi2[g_bar].im += G*Psi0[g].im * (.5 * b * b - .5 * a * a) * discrete_factor;
3501 //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON)))
3502 //fprintf(stderr,"(%i) Psi[%i].re += %e +i %e\n",P->Par.me, g_bar, G*Psi0[g].re * (.5 * b * b - .5 * a * a) * discrete_factor, G*Psi0[g].im * (.5 * b * b - .5 * a * a) * discrete_factor);
3503 } else {
3504 tmp = GA[g].G[j]-GA[g_bar].G[j];
3505 integral.re = (cos(tmp*b)+sin(tmp*b)*b*tmp - cos(tmp*a)-sin(tmp*a)*a*tmp) / (tmp * tmp);
3506 integral.im = (sin(tmp*b)-cos(tmp*b)*b*tmp - sin(tmp*a)+cos(tmp*a)*a*tmp) / (tmp * tmp);
3507 Psi2[g_bar].re += G*(Psi0[g].re*integral.re - Psi0[g].im*integral.im) * discrete_factor;
3508 Psi2[g_bar].im += G*(Psi0[g].re*integral.im + Psi0[g].im*integral.re) * discrete_factor;
3509 //if ((G != 0) && ((fabs(Psi0[g].re) > MYEPSILON) || (fabs(Psi0[g].im) > MYEPSILON)))
3510 //fprintf(stderr,"(%i) Psi[%i].re += %e\tPsi[%i].im += %e \n",P->Par.me, g_bar, G*(Psi0[g].re*integral.re - Psi0[g].im*integral.im) * discrete_factor, g_bar, G*(Psi0[g].re*integral.im + Psi0[g].im*integral.re) * discrete_factor);
3511 }
3512 }
3513 }
3514 }
3515 }
3516
3517 // apply rxp
3518 debug (P,"Applying RxP to test function.");
3519 CalculatePerturbationOperator_RxP(P,Psi0,Psi3,k_normal,i);
3520
3521 // compare both coefficient arrays
3522 debug(P,"Beginning comparison of analytic and Rxp applied solution.");
3523 for (g=0;g<LevS->MaxG;g++) {
3524 if ((fabs(Psi3[g].re-Psi2[g].re) >= MYEPSILON) || (fabs(Psi3[g].im-Psi2[g].im) >= MYEPSILON))
3525 fprintf(stderr,"(%i) Psi3[%i] = %e +i %e != Psi2[%i] = %e +i %e\n",P->Par.me, g, Psi3[g].re, Psi3[g].im, g, Psi2[g].re, Psi2[g].im);
3526 //else
3527 //fprintf(stderr,"(%i) Psi1[%i] == Psi2[%i] = %e +i %e\n",P->Par.me, g, g, Psi1[g].re, Psi1[g].im);
3528 }
3529 fprintf(stderr,"(%i) <0|1> = <0|r|0> == %e +i %e\n",P->Par.me, GradSP(P,LevS,Psi0,Psi3), GradImSP(P,LevS,Psi0,Psi3));
3530 fprintf(stderr,"(%i) <1|1> = |r|ᅵ == %e +i %e\n",P->Par.me, GradSP(P,LevS,Psi3,Psi3), GradImSP(P,LevS,Psi3,Psi3));
3531 fprintf(stderr,"(%i) <0|0> = %e +i %e\n",P->Par.me, GradSP(P,LevS,Psi0,Psi0), GradImSP(P,LevS,Psi0,Psi0));
3532 fprintf(stderr,"(%i) <0|2> = %e +i %e\n",P->Par.me, GradSP(P,LevS,Psi0,Psi2), GradImSP(P,LevS,Psi0,Psi2));
3533}
3534
3535
3536/** Output of a (X,Y,DX,DY) 2d-vector plot.
3537 * For a printable representation of the induced current two-dimensional vector plots are useful, as three-dimensional
3538 * isospheres are sometimes mis-leading or do not represent the desired flow direction. The routine simply extracts a
3539 * two-dimensional cut orthogonal to one of the lattice axis at a certain node.
3540 * \param *P Problem at hand
3541 * \param B_index direction of B field
3542 * \param n_orth grid node in B_index direction of the plane (the order in which the remaining two coordinate axis
3543 * appear is the same as in a cross product, which is used to determine orthogonality)
3544 */
3545void PlotVectorPlane(struct Problem *P, int B_index, int n_orth)
3546{
3547 struct RunStruct *R = &P->R;
3548 struct LatticeLevel *Lev0 = R->Lev0;
3549 struct Density *Dens0 = Lev0->Dens;
3550 char filename[255];
3551 char *suchpointer;
3552 FILE *PlotFile = NULL;
3553 const int myPE = P->Par.me_comm_ST;
3554 time_t seconds;
3555 fftw_real *CurrentDensity[NDIM*NDIM];
3556 CurrentDensity[0] = (fftw_real *) Dens0->DensityArray[CurrentDensity0];
3557 CurrentDensity[1] = (fftw_real *) Dens0->DensityArray[CurrentDensity1];
3558 CurrentDensity[2] = (fftw_real *) Dens0->DensityArray[CurrentDensity2];
3559 CurrentDensity[3] = (fftw_real *) Dens0->DensityArray[CurrentDensity3];
3560 CurrentDensity[4] = (fftw_real *) Dens0->DensityArray[CurrentDensity4];
3561 CurrentDensity[5] = (fftw_real *) Dens0->DensityArray[CurrentDensity5];
3562 CurrentDensity[6] = (fftw_real *) Dens0->DensityArray[CurrentDensity6];
3563 CurrentDensity[7] = (fftw_real *) Dens0->DensityArray[CurrentDensity7];
3564 CurrentDensity[8] = (fftw_real *) Dens0->DensityArray[CurrentDensity8];
3565 time(&seconds); // get current time
3566
3567 if (!myPE) { // only process 0 writes to file
3568 // open file
3569 sprintf(&filename[0], ".current.L%i.csv", Lev0->LevelNo);
3570 OpenFile(P, &PlotFile, filename, "w", P->Call.out[ReadOut]);
3571 strcpy(filename, ctime(&seconds));
3572 suchpointer = strchr(filename, '\n');
3573 if (suchpointer != NULL)
3574 *suchpointer = '\0';
3575 if (PlotFile != NULL) {
3576 fprintf(PlotFile,"# current vector plot of plane perpendicular to direction e_%i at node %i, seed %i, config %s, run on %s, #cpus %i", B_index, n_orth, R->Seed, P->Files.default_path, filename, P->Par.Max_me_comm_ST_Psi);
3577 fprintf(PlotFile,"\n");
3578 } else { Error(SomeError, "PlotVectorPlane: Opening Plot File"); }
3579 }
3580
3581 // plot density
3582 if (!P->Par.me_comm_ST_PsiT) // only first wave function group as current density of all psis was gathered
3583 PlotRealDensity(P, Lev0, PlotFile, B_index, n_orth, CurrentDensity[B_index*NDIM+cross(B_index,0)], CurrentDensity[B_index*NDIM+cross(B_index,1)]);
3584
3585 if (PlotFile != NULL) {
3586 // close file
3587 fclose(PlotFile);
3588 }
3589}
3590
3591
3592/** Reads psi coefficients of \a type from file and transforms to new level.
3593 * \param *P Problem at hand
3594 * \param type PsiTypeTag of which minimisation group to load from file
3595 * \sa ReadSrcPsiDensity() - reading the coefficients, ChangePsiAndDensToLevUp() - transformation to upper level
3596 */
3597void ReadSrcPerturbedPsis(struct Problem *P, enum PsiTypeTag type)
3598{
3599 struct RunStruct *R = &P->R;
3600 struct Lattice *Lat = &P->Lat;
3601 struct LatticeLevel *Lev0 = &P->Lat.Lev[R->Lev0No+1]; // one level higher than current (ChangeLevUp already occurred)
3602 struct LatticeLevel *LevS = &P->Lat.Lev[R->LevSNo+1];
3603 struct Density *Dens = Lev0->Dens;
3604 struct Psis *Psi = &Lat->Psi;
3605 struct fft_plan_3d *plan = Lat->plan;
3606 fftw_complex *work = (fftw_complex *)Dens->DensityCArray[TempDensity];
3607 fftw_complex *tempdestRC = (fftw_complex *)Dens->DensityArray[TempDensity];
3608 fftw_complex *posfac, *destpos, *destRCS, *destRCD;
3609 fftw_complex *source, *source0;
3610 int Index,i,pos;
3611 double factorC = 1./Lev0->MaxN;
3612 int p,g;
3613
3614 // ================= read coefficients from file to LocalPsi ============
3615 ReadSrcPsiDensity(P, type, 0, R->LevSNo+1);
3616
3617 // ================= transform to upper level ===========================
3618 // for all local Psis do the usual transformation (completing coefficients for all grid vectors, fft, permutation)
3619 LockDensityArray(Dens, TempDensity, real);
3620 LockDensityArray(Dens, TempDensity, imag);
3621 for (p=Psi->LocalNo-1; p >= 0; p--)
3622 if (Psi->LocalPsiStatus[p].PsiType == type) { // only for the desired type
3623 source = LevS->LPsi->LocalPsi[p];
3624 source0 = Lev0->LPsi->LocalPsi[p];
3625 //fprintf(stderr,"(%i) ReadSrcPerturbedPsis: LevSNo %i\t Lev0No %i\tp %i\t source %p\t source0 %p\n", P->Par.me, LevS->LevelNo, Lev0->LevelNo, p, source, source0);
3626 SetArrayToDouble0((double *)tempdestRC, Dens->TotalSize*2);
3627 for (i=0;i<LevS->MaxG;i++) {
3628 Index = LevS->GArray[i].Index;
3629 posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
3630 destpos = &tempdestRC[LevS->MaxNUp*Index];
3631 //if (isnan(source[i].re)) { fprintf(stderr,"(%i) WARNING in ReadSrcPerturbedPsis(): source_%i[%i] = NaN!\n", P->Par.me, p, i); Error(SomeError, "NaN-Fehler!"); }
3632 for (pos=0; pos < LevS->MaxNUp; pos++) {
3633 destpos[pos].re = source[i].re*posfac[pos].re-source[i].im*posfac[pos].im;
3634 destpos[pos].im = source[i].re*posfac[pos].im+source[i].im*posfac[pos].re;
3635 }
3636 }
3637 for (i=0; i<LevS->MaxDoubleG; i++) {
3638 destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
3639 destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
3640 for (pos=0; pos < LevS->MaxNUp; pos++) {
3641 destRCD[pos].re = destRCS[pos].re;
3642 destRCD[pos].im = -destRCS[pos].im;
3643 }
3644 }
3645 fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
3646 DensityRTransformPos(LevS,(fftw_real*)tempdestRC,(fftw_real *)Dens->DensityCArray[ActualPsiDensity]);
3647 // now we have density in the upper level, fft back to complex and store it as wave function coefficients
3648 fft_3d_real_to_complex(plan, Lev0->LevelNo, FFTNF1, Dens->DensityCArray[ActualPsiDensity], work);
3649 for (g=0; g < Lev0->MaxG; g++) {
3650 Index = Lev0->GArray[g].Index;
3651 source0[g].re = Dens->DensityCArray[ActualPsiDensity][Index].re*factorC;
3652 source0[g].im = Dens->DensityCArray[ActualPsiDensity][Index].im*factorC;
3653 //if (isnan(source0[g].re)) { fprintf(stderr,"(%i) WARNING in ReadSrcPerturbedPsis(): source0_%i[%i] = NaN!\n", P->Par.me, p, g); Error(SomeError, "NaN-Fehler!"); }
3654 }
3655 if (Lev0->GArray[0].GSq == 0.0)
3656 source0[g].im = 0.0;
3657 }
3658 UnLockDensityArray(Dens, TempDensity, real);
3659 UnLockDensityArray(Dens, TempDensity, imag);
3660 // finished.
3661}
3662
3663/** evaluates perturbed energy functional
3664 * \param norm norm of current Psi in functional
3665 * \param *params void-pointer to parameter array
3666 * \return evaluated functional at f(x) with \a norm
3667 */
3668double perturbed_function (double norm, void *params) {
3669 struct Problem *P = (struct Problem *)params;
3670 int i, n = P->R.LevS->MaxG;
3671 double old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);
3672 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
3673 fprintf(stderr,"(%i) perturbed_function: setting norm to %lg ...", P->Par.me, norm);
3674 // set desired norm for current Psi
3675 for (i=0; i< n; i++) {
3676 currentPsi[i].re *= norm/old_norm; // real part
3677 currentPsi[i].im *= norm/old_norm; // imaginary part
3678 }
3679 P->R.PsiStep = 0; // make it not advance to next Psi
3680
3681 //debug(P,"UpdateActualPsiNo");
3682 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
3683 //debug(P,"UpdateEnergyArray");
3684 UpdateEnergyArray(P); // shift energy values in their array by one
3685 //debug(P,"UpdatePerturbedEnergyCalculation");
3686 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)
3687 EnergyAllReduce(P); // gather from all processes and sum up to total energy
3688/*
3689 for (i=0; i< n; i++) {
3690 currentPsi[i].re /= norm/old_norm; // real part
3691 currentPsi[i].im /= norm/old_norm; // imaginary part
3692 }*/
3693
3694 fprintf(stderr,"%lg\n", P->Lat.E->TotalEnergy[0]);
3695 return P->Lat.E->TotalEnergy[0]; // and return evaluated functional
3696}
3697
3698/** evaluates perturbed energy functional.
3699 * \param *x current position in functional
3700 * \param *params void-pointer to parameter array
3701 * \return evaluated functional at f(x)
3702 */
3703double perturbed_f (const gsl_vector *x, void *params) {
3704 struct Problem *P = (struct Problem *)params;
3705 int i, n = P->R.LevS->MaxG*2;
3706 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
3707 //int diff = 0;
3708 //debug(P,"f");
3709 // put x into current Psi
3710 for (i=0; i< n; i+=2) {
3711 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;
3712 currentPsi[i/2].re = gsl_vector_get (x, i); // real part
3713 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part
3714 }
3715 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);
3716 P->R.PsiStep = 0; // make it not advance to next Psi
3717
3718 //debug(P,"UpdateActualPsiNo");
3719 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
3720 //debug(P,"UpdateEnergyArray");
3721 UpdateEnergyArray(P); // shift energy values in their array by one
3722 //debug(P,"UpdatePerturbedEnergyCalculation");
3723 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)
3724 EnergyAllReduce(P); // gather from all processes and sum up to total energy
3725
3726 return P->Lat.E->TotalEnergy[0]; // and return evaluated functional
3727}
3728
3729/** evaluates perturbed energy gradient.
3730 * \param *x current position in functional
3731 * \param *params void-pointer to parameter array
3732 * \param *g array for gradient vector on return
3733 */
3734void perturbed_df (const gsl_vector *x, void *params, gsl_vector *g) {
3735 struct Problem *P = (struct Problem *)params;
3736 int i, n = P->R.LevS->MaxG*2;
3737 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
3738 fftw_complex *gradient = P->Grad.GradientArray[ActualGradient];
3739 //int diff = 0;
3740 //debug(P,"df");
3741 // put x into current Psi
3742 for (i=0; i< n; i+=2) {
3743 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;
3744 currentPsi[i/2].re = gsl_vector_get (x, i); // real part
3745 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part
3746 }
3747 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);
3748 P->R.PsiStep = 0; // make it not advance to next Psi
3749
3750 //debug(P,"UpdateActualPsiNo");
3751 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
3752 //debug(P,"UpdateEnergyArray");
3753 UpdateEnergyArray(P); // shift energy values in their array by one
3754 //debug(P,"UpdatePerturbedEnergyCalculation");
3755 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)
3756 EnergyAllReduce(P); // gather from all processes and sum up to total energy
3757
3758 // checkout gradient
3759 //diff = 0;
3760 for (i=0; i< n; i+=2) {
3761 //if ((-gradient[i/2].re != gsl_vector_get (g, i)) || (-gradient[i/2].im != gsl_vector_get (g, i+1))) diff++;
3762 gsl_vector_set (g, i, -gradient[i/2].re); // real part
3763 gsl_vector_set (g, i+1, -gradient[i/2].im); // imaginary part
3764 }
3765 //if (diff) fprintf(stderr,"(%i) %i differences between old and new gradient.\n", P->Par.me, diff);
3766}
3767
3768/** evaluates perturbed energy functional and gradient.
3769 * \param *x current position in functional
3770 * \param *params void-pointer to parameter array
3771 * \param *f pointer to energy function value on return
3772 * \param *g array for gradient vector on return
3773 */
3774void perturbed_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *g) {
3775 struct Problem *P = (struct Problem *)params;
3776 int i, n = P->R.LevS->MaxG*2;
3777 fftw_complex *currentPsi = P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo];
3778 fftw_complex *gradient = P->Grad.GradientArray[ActualGradient];
3779 //int diff = 0;
3780 //debug(P,"fdf");
3781 // put x into current Psi
3782 for (i=0; i< n; i+=2) {
3783 //if ((currentPsi[i/2].re != gsl_vector_get (x, i)) || (currentPsi[i/2].im != gsl_vector_get (x, i+1))) diff++;
3784 currentPsi[i/2].re = gsl_vector_get (x, i); // real part
3785 currentPsi[i/2].im = gsl_vector_get (x, i+1); // imaginary part
3786 }
3787 //if (diff) fprintf(stderr,"(%i) %i differences between old and new currentPsi.\n", P->Par.me, diff);
3788 P->R.PsiStep = 0; // make it not advance to next Psi
3789
3790 //debug(P,"UpdateActualPsiNo");
3791 UpdateActualPsiNo(P, P->R.CurrentMin); // orthogonalize
3792 //debug(P,"UpdateEnergyArray");
3793 UpdateEnergyArray(P); // shift energy values in their array by one
3794 //debug(P,"UpdatePerturbedEnergyCalculation");
3795 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)
3796 EnergyAllReduce(P); // gather from all processes and sum up to total energy
3797
3798 // checkout gradient
3799 //diff = 0;
3800 for (i=0; i< n; i+=2) {
3801 //if ((-gradient[i/2].re != gsl_vector_get (g, i)) || (-gradient[i/2].im != gsl_vector_get (g, i+1))) diff++;
3802 gsl_vector_set (g, i, -gradient[i/2].re); // real part
3803 gsl_vector_set (g, i+1, -gradient[i/2].im); // imaginary part
3804 }
3805 //if (diff) fprintf(stderr,"(%i) %i differences between old and new gradient.\n", P->Par.me, diff);
3806
3807 *f = P->Lat.E->TotalEnergy[0]; // and return evaluated functional
3808}
3809
3810/* MinimisePerturbed with all the brent minimisation approach
3811void MinimisePerturbed (struct Problem *P, int *Stop, int *SuperStop) {
3812 struct RunStruct *R = &P->R;
3813 struct Lattice *Lat = &P->Lat;
3814 struct Psis *Psi = &Lat->Psi;
3815 int type;
3816 //int i;
3817
3818 // stuff for GSL minimization
3819 //size_t iter;
3820 //int status, Status
3821 int n = R->LevS->MaxG*2;
3822 const gsl_multimin_fdfminimizer_type *T_multi;
3823 const gsl_min_fminimizer_type *T;
3824 gsl_multimin_fdfminimizer *s_multi;
3825 gsl_min_fminimizer *s;
3826 gsl_vector *x;//, *ss;
3827 gsl_multimin_function_fdf my_func;
3828 gsl_function F;
3829 //fftw_complex *currentPsi;
3830 //double a,b,m, f_m, f_a, f_b;
3831 //double old_norm;
3832
3833 my_func.f = &perturbed_f;
3834 my_func.df = &perturbed_df;
3835 my_func.fdf = &perturbed_fdf;
3836 my_func.n = n;
3837 my_func.params = P;
3838 F.function = &perturbed_function;
3839 F.params = P;
3840
3841 x = gsl_vector_alloc (n);
3842 //ss = gsl_vector_alloc (Psi->NoOfPsis);
3843 T_multi = gsl_multimin_fdfminimizer_vector_bfgs;
3844 s_multi = gsl_multimin_fdfminimizer_alloc (T_multi, n);
3845 T = gsl_min_fminimizer_brent;
3846 s = gsl_min_fminimizer_alloc (T);
3847
3848 for (type=Perturbed_P0;type<=Perturbed_RxP2;type++) { // go through each perturbation group separately //
3849 *Stop=0; // reset stop flag
3850 fprintf(stderr,"(%i)Beginning perturbed minimisation of type %s ...\n", P->Par.me, R->MinimisationName[type]);
3851 //OutputOrbitalPositions(P, Occupied);
3852 R->PsiStep = R->MaxPsiStep; // reset in-Psi-minimisation-counter, so that we really advance to the next wave function
3853 UpdateActualPsiNo(P, type); // step on to next perturbed one
3854 fprintf(stderr, "(%i) Re-initializing perturbed psi array for type %s ", P->Par.me, R->MinimisationName[type]);
3855 if (P->Call.ReadSrcFiles && ReadSrcPsiDensity(P,type,1, R->LevSNo)) {
3856 SpeedMeasure(P, InitSimTime, StartTimeDo);
3857 fprintf(stderr,"from source file of recent calculation\n");
3858 ReadSrcPsiDensity(P,type, 0, R->LevSNo);
3859 ResetGramSchTagType(P, Psi, type, IsOrthogonal); // loaded values are orthonormal
3860 SpeedMeasure(P, DensityTime, StartTimeDo);
3861 //InitDensityCalculation(P);
3862 SpeedMeasure(P, DensityTime, StopTimeDo);
3863 R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // needed otherwise called routines in function below crash
3864 UpdateGramSchOldActualPsiNo(P,Psi);
3865 InitPerturbedEnergyCalculation(P, 1); // go through all orbitals calculate each H^{(0)}-eigenvalue, recalc HGDensity, cause InitDensityCalc zero'd it
3866 UpdatePerturbedEnergyCalculation(P); // H1cGradient and Gradient must be current ones
3867 EnergyAllReduce(P); // gather energies for minimum search
3868 SpeedMeasure(P, InitSimTime, StopTimeDo);
3869 }
3870 if (P->Call.ReadSrcFiles != 1) {
3871 SpeedMeasure(P, InitSimTime, StartTimeDo);
3872 ResetGramSchTagType(P, Psi, type, NotOrthogonal); // perturbed now shall be orthonormalized
3873 if (P->Call.ReadSrcFiles != 2) {
3874 if (R->LevSNo == Lat->MaxLevel-1) { // is it the starting level? (see InitRunLevel())
3875 fprintf(stderr, "randomly.\n");
3876 InitPsisValue(P, Psi->TypeStartIndex[type], Psi->TypeStartIndex[type+1]); // initialize perturbed array for this run
3877 } else {
3878 fprintf(stderr, "from source file of last level.\n");
3879 ReadSrcPerturbedPsis(P, type);
3880 }
3881 }
3882 SpeedMeasure(P, InitGramSchTime, StartTimeDo);
3883 GramSch(P, R->LevS, Psi, Orthogonalize);
3884 SpeedMeasure(P, InitGramSchTime, StopTimeDo);
3885 SpeedMeasure(P, InitDensityTime, StartTimeDo);
3886 //InitDensityCalculation(P);
3887 SpeedMeasure(P, InitDensityTime, StopTimeDo);
3888 InitPerturbedEnergyCalculation(P, 1); // go through all orbitals calculate each H^{(0)}-eigenvalue, recalc HGDensity, cause InitDensityCalc zero'd it
3889 R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // needed otherwise called routines in function below crash
3890 UpdateGramSchOldActualPsiNo(P,Psi);
3891 UpdatePerturbedEnergyCalculation(P); // H1cGradient and Gradient must be current ones
3892 EnergyAllReduce(P); // gather energies for minimum search
3893 SpeedMeasure(P, InitSimTime, StopTimeDo);
3894 R->LevS->Step++;
3895 EnergyOutput(P,0);
3896 while (*Stop != 1) {
3897 // copy current Psi into starting vector
3898 currentPsi = R->LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];
3899 for (i=0; i< n; i+=2) {
3900 gsl_vector_set (x, i, currentPsi[i/2].re); // real part
3901 gsl_vector_set (x, i+1, currentPsi[i/2].im); // imaginary part
3902 }
3903 gsl_multimin_fdfminimizer_set (s_multi, &my_func, x, 0.01, 1e-2);
3904 iter = 0;
3905 status = 0;
3906 do { // look for minimum along current local psi
3907 iter++;
3908 status = gsl_multimin_fdfminimizer_iterate (s_multi);
3909 MPI_Allreduce(&status, &Status, 1, MPI_INT, MPI_MAX, P->Par.comm_ST_Psi);
3910 if (Status)
3911 break;
3912 status = gsl_multimin_test_gradient (s_multi->gradient, 1e-2);
3913 MPI_Allreduce(&status, &Status, 1, MPI_INT, MPI_MAX, P->Par.comm_ST_Psi);
3914 //if (Status == GSL_SUCCESS)
3915 //printf ("Minimum found at:\n");
3916 if (P->Par.me == 0) fprintf (stderr,"(%i,%i,%i)S(%i,%i,%i):\t %5d %10.5f\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, (int)iter, s_multi->f);
3917 //TestGramSch(P,R->LevS,Psi, type); // functions are orthonormal?
3918 } while (Status == GSL_CONTINUE && iter < 3);
3919 // now minimize norm of currentPsi (one-dim)
3920 if (0) {
3921 iter = 0;
3922 status = 0;
3923 m = 1.;
3924 a = MYEPSILON;
3925 b = 100.;
3926 f_a = perturbed_function (a, P);
3927 f_b = perturbed_function (b, P);
3928 f_m = perturbed_function (m, P);
3929 //if ((f_m < f_a) && (f_m < f_b)) {
3930 gsl_min_fminimizer_set (s, &F, m, a, b);
3931 do { // look for minimum along current local psi
3932 iter++;
3933 status = gsl_min_fminimizer_iterate (s);
3934 m = gsl_min_fminimizer_x_minimum (s);
3935 a = gsl_min_fminimizer_x_lower (s);
3936 b = gsl_min_fminimizer_x_upper (s);
3937 status = gsl_min_test_interval (a, b, 0.001, 0.0);
3938 if (status == GSL_SUCCESS)
3939 printf ("Minimum found at:\n");
3940 printf ("%5d [%.7f, %.7f] %.7f %.7f\n",
3941 (int) iter, a, b,
3942 m, b - a);
3943 } while (status == GSL_CONTINUE && iter < 100);
3944 old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);
3945 for (i=0; i< n; i++) {
3946 currentPsi[i].re *= m/old_norm; // real part
3947 currentPsi[i].im *= m/old_norm; // imaginary part
3948 }
3949 } else debug(P,"Norm not minimizable!");
3950 //P->R.PsiStep = P->R.MaxPsiStep; // make it advance to next Psi
3951 FindPerturbedMinimum(P);
3952 //debug(P,"UpdateActualPsiNo");
3953 UpdateActualPsiNo(P, type); // step on to next perturbed Psi
3954 //debug(P,"UpdateEnergyArray");
3955 UpdateEnergyArray(P); // shift energy values in their array by one
3956 //debug(P,"UpdatePerturbedEnergyCalculation");
3957 UpdatePerturbedEnergyCalculation(P); // re-calc energies (which is hopefully lower)
3958 EnergyAllReduce(P); // gather from all processes and sum up to total energy
3959 //ControlNativeDensity(P); // check total density (summed up PertMixed must be zero!)
3960 //printf ("(%i,%i,%i)S(%i,%i,%i):\t %5d %10.5f\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, (int)iter, s_multi->f);
3961 if (*SuperStop != 1)
3962 *SuperStop = CheckCPULIM(P);
3963 *Stop = CalculateMinimumStop(P, *SuperStop);
3964 P->Speed.Steps++; // step on
3965 R->LevS->Step++;
3966 }
3967 // now release normalization condition and minimize wrt to norm
3968 *Stop = 0;
3969 while (*Stop != 1) {
3970 currentPsi = R->LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];
3971 iter = 0;
3972 status = 0;
3973 m = 1.;
3974 a = 0.001;
3975 b = 10.;
3976 f_a = perturbed_function (a, P);
3977 f_b = perturbed_function (b, P);
3978 f_m = perturbed_function (m, P);
3979 if ((f_m < f_a) && (f_m < f_b)) {
3980 gsl_min_fminimizer_set (s, &F, m, a, b);
3981 do { // look for minimum along current local psi
3982 iter++;
3983 status = gsl_min_fminimizer_iterate (s);
3984 m = gsl_min_fminimizer_x_minimum (s);
3985 a = gsl_min_fminimizer_x_lower (s);
3986 b = gsl_min_fminimizer_x_upper (s);
3987 status = gsl_min_test_interval (a, b, 0.001, 0.0);
3988 if (status == GSL_SUCCESS)
3989 printf ("Minimum found at:\n");
3990 printf ("%5d [%.7f, %.7f] %.7f %.7f\n",
3991 (int) iter, a, b,
3992 m, b - a);
3993 } while (status == GSL_CONTINUE && iter < 100);
3994 old_norm = GramSchGetNorm2(P,P->R.LevS,P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo]);
3995 for (i=0; i< n; i++) {
3996 currentPsi[i].re *= m/old_norm; // real part
3997 currentPsi[i].im *= m/old_norm; // imaginary part
3998 }
3999 }
4000 P->R.PsiStep = P->R.MaxPsiStep; // make it advance to next Psi
4001 //debug(P,"UpdateActualPsiNo");
4002 UpdateActualPsiNo(P, type); // step on to next perturbed Psi
4003 if (*SuperStop != 1)
4004 *SuperStop = CheckCPULIM(P);
4005 *Stop = CalculateMinimumStop(P, *SuperStop);
4006 P->Speed.Steps++; // step on
4007 R->LevS->Step++;
4008 }
4009 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) Write %s srcpsi to disk\n", P->Par.me, R->MinimisationName[type]);
4010 OutputSrcPsiDensity(P, type);
4011// if (!TestReadnWriteSrcDensity(P,type))
4012// Error(SomeError,"TestReadnWriteSrcDensity failed!");
4013 }
4014
4015 TestGramSch(P,R->LevS,Psi, type); // functions are orthonormal?
4016 // calculate current density summands
4017 //if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Filling current density grid ...\n",P->Par.me);
4018 SpeedMeasure(P, CurrDensTime, StartTimeDo);
4019 if (*SuperStop != 1) {
4020 if ((R->DoFullCurrent == 1) || ((R->DoFullCurrent == 2) && (CheckOrbitalOverlap(P) == 1))) { //test to check whether orbitals have mutual overlap and thus \\DeltaJ_{xc} must not be dropped
4021 R->DoFullCurrent = 1; // set to 1 if it was 2 but Check...() yielded necessity
4022 //debug(P,"Filling with Delta j ...");
4023 //FillDeltaCurrentDensity(P);
4024 }// else
4025 //debug(P,"There is no overlap between orbitals.");
4026 //debug(P,"Filling with j ...");
4027 FillCurrentDensity(P);
4028 }
4029 SpeedMeasure(P, CurrDensTime, StopTimeDo);
4030
4031 SetGramSchExtraPsi(P,Psi,NotUsedToOrtho); // remove extra Psis from orthogonality check
4032 ResetGramSchTagType(P, Psi, type, NotUsedToOrtho); // remove this group from the check for the next minimisation group as well!
4033 }
4034 UpdateActualPsiNo(P, Occupied); // step on back to an occupied one
4035
4036 gsl_multimin_fdfminimizer_free (s_multi);
4037 gsl_min_fminimizer_free (s);
4038 gsl_vector_free (x);
4039 //gsl_vector_free (ss);
4040}
4041*/
Note: See TracBrowser for help on using the repository browser.