source: pcp/src/perturbed.c@ 4f9fe2

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

changed all small, already inlined, functions to using HAVE_INLINE (and if not they won't be inline)

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