source: pcp/src/perturbed.c@ 5a78f5

Last change on this file since 5a78f5 was 375dcf, checked in by Frederik Heber <heber@…>, 17 years ago

introduced shieldings to analyzer and joiner

both now handle pcp.sigma_all...csv files just as pcp.forces.all. Therefore the data format in pcp/perturbed.c was adapted a bit, as we need a header.
periodentafel.hpp got periodentafel and element class from molecules.hpp

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