| [a0bcf1] | 1 | /** \file ions.c
 | 
|---|
 | 2 |  * Ionic Force, speed, coordinate and energy calculation.
 | 
|---|
 | 3 |  * Herein are all the routines for the molecular dynamics calculations such as
 | 
|---|
 | 4 |  * reading of configuration files IonsInitRead() and
 | 
|---|
 | 5 |  * free'ing RemoveIonsRead(),
 | 
|---|
 | 6 |  * summing up forces CalculateIonForce(),
 | 
|---|
 | 7 |  * correcting for temperature CorrectVelocities(),
 | 
|---|
 | 8 |  * or for fixation center of balance CorrectForces(),
 | 
|---|
 | 9 |  * outputting them to file OutputIonForce(),
 | 
|---|
 | 10 |  * calculating kinetic CalculateEnergyIonsU(), ewald CalculateEwald() energies,
 | 
|---|
 | 11 |  * moving ion UpdateIonsR() (position) UpdateIonsU() (speed),
 | 
|---|
 | 12 |  * scaling to match some temperature ScaleTemp()
 | 
|---|
 | 13 |  * are gathered.
 | 
|---|
 | 14 |  * Finally, needed for structure optimization GetOuterStop() evaluates the stop
 | 
|---|
 | 15 |  * condition of a minimal mean force acting on each ion.
 | 
|---|
 | 16 |  * 
 | 
|---|
 | 17 |   Project: ParallelCarParrinello
 | 
|---|
 | 18 |  \author Jan Hamaekers
 | 
|---|
 | 19 |  \date 2000
 | 
|---|
 | 20 | 
 | 
|---|
 | 21 |   File: ions.c
 | 
|---|
 | 22 |   $Id: ions.c,v 1.34 2007/02/05 16:15:27 foo Exp $
 | 
|---|
 | 23 | */
 | 
|---|
 | 24 | 
 | 
|---|
 | 25 | #include <stdlib.h>
 | 
|---|
 | 26 | #include <stdio.h>
 | 
|---|
 | 27 | #include <stddef.h>
 | 
|---|
 | 28 | #include <math.h>
 | 
|---|
 | 29 | #include <string.h>
 | 
|---|
 | 30 | #include <unistd.h>
 | 
|---|
| [961b75] | 31 | #include <gsl/gsl_randist.h>
 | 
|---|
| [a0bcf1] | 32 | #include "mymath.h"
 | 
|---|
 | 33 | 
 | 
|---|
 | 34 | 
 | 
|---|
 | 35 | // use double precision fft when we have it
 | 
|---|
 | 36 | #ifdef HAVE_CONFIG_H
 | 
|---|
 | 37 | #include <config.h>
 | 
|---|
 | 38 | #endif
 | 
|---|
 | 39 | 
 | 
|---|
 | 40 | #ifdef HAVE_DFFTW_H
 | 
|---|
 | 41 | #include "dfftw.h"
 | 
|---|
 | 42 | #else
 | 
|---|
 | 43 | #include "fftw.h"
 | 
|---|
 | 44 | #endif
 | 
|---|
 | 45 | 
 | 
|---|
 | 46 | #include "data.h"
 | 
|---|
 | 47 | #include "errors.h"
 | 
|---|
 | 48 | #include "helpers.h"
 | 
|---|
 | 49 | #include "mymath.h"
 | 
|---|
 | 50 | #include "ions.h"
 | 
|---|
 | 51 | #include "init.h"
 | 
|---|
 | 52 | 
 | 
|---|
| [b74e5e] | 53 | /** Readin of Thermostat related values from parameter file.
 | 
|---|
 | 54 |  * \param *P Problem at hand
 | 
|---|
 | 55 |  * \param *source parameter file
 | 
|---|
 | 56 |  */
 | 
|---|
 | 57 | void InitThermostats(struct Problem *P, FILE *source)
 | 
|---|
 | 58 | {
 | 
|---|
 | 59 |   struct FileData *F = &P->Files;
 | 
|---|
 | 60 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 61 |   char *thermo = MallocString(12, "IonsInitRead: thermo");
 | 
|---|
 | 62 |   int j;
 | 
|---|
 | 63 | 
 | 
|---|
 | 64 |   // initialize the naming stuff and all
 | 
|---|
 | 65 |   I->ThermostatImplemented = (int *) Malloc((MaxThermostats)*(sizeof(int)), "IonsInitRead: *ThermostatImplemented");
 | 
|---|
 | 66 |   I->ThermostatNames = (char **) Malloc((MaxThermostats)*(sizeof(char *)), "IonsInitRead: *ThermostatNames");
 | 
|---|
 | 67 |   for (j=0;j<MaxThermostats;j++)
 | 
|---|
 | 68 |     I->ThermostatNames[j] = (char *) MallocString(12*(sizeof(char)), "IonsInitRead: ThermostatNames[]");
 | 
|---|
 | 69 |   strcpy(I->ThermostatNames[0],"None");
 | 
|---|
 | 70 |   I->ThermostatImplemented[0] = 1;
 | 
|---|
 | 71 |   strcpy(I->ThermostatNames[1],"Woodcock"); 
 | 
|---|
 | 72 |   I->ThermostatImplemented[1] = 1;
 | 
|---|
 | 73 |   strcpy(I->ThermostatNames[2],"Gaussian"); 
 | 
|---|
 | 74 |   I->ThermostatImplemented[2] = 1;
 | 
|---|
 | 75 |   strcpy(I->ThermostatNames[3],"Langevin"); 
 | 
|---|
 | 76 |   I->ThermostatImplemented[3] = 1;
 | 
|---|
 | 77 |   strcpy(I->ThermostatNames[4],"Berendsen"); 
 | 
|---|
 | 78 |   I->ThermostatImplemented[4] = 1;
 | 
|---|
 | 79 |   strcpy(I->ThermostatNames[5],"NoseHoover"); 
 | 
|---|
 | 80 |   I->ThermostatImplemented[5] = 1;
 | 
|---|
 | 81 |   I->Thermostat = -1;
 | 
|---|
 | 82 |   if (F->MeOutMes) fprintf(F->TemperatureFile, "# %s\t%s\t%s --- ","Step", "ActualTemp(1)", "ActualTemp(2)");
 | 
|---|
 | 83 | 
 | 
|---|
 | 84 |   // read desired Thermostat from file along with needed additional parameters
 | 
|---|
 | 85 |   if (ParseForParameter(P->Call.out[ReadOut],source,"Thermostat", 0, 1, 1, string_type, thermo, 1, optional)) {
 | 
|---|
 | 86 |     if (strcmp(thermo, I->ThermostatNames[0]) == 0) { // None
 | 
|---|
 | 87 |       if (I->ThermostatImplemented[0] == 1) {
 | 
|---|
 | 88 |         I->Thermostat = None;
 | 
|---|
 | 89 |       } else {
 | 
|---|
 | 90 |         if (P->Par.me == 0)
 | 
|---|
 | 91 |           fprintf(stderr, "(%i) Warning: %s thermostat not implemented, falling back to None.", P->Par.me, I->ThermostatNames[0]);
 | 
|---|
 | 92 |         I->Thermostat = None;
 | 
|---|
 | 93 |       }
 | 
|---|
 | 94 |     } else if (strcmp(thermo, I->ThermostatNames[1]) == 0) { // Woodcock
 | 
|---|
 | 95 |       if (I->ThermostatImplemented[1] == 1) {
 | 
|---|
 | 96 |         I->Thermostat = Woodcock;
 | 
|---|
 | 97 |         ParseForParameter(P->Call.out[ReadOut],source,"Thermostat", 0, 2, 1, int_type, &P->R.ScaleTempStep, 1, critical); // read scaling frequency
 | 
|---|
 | 98 |       } else {
 | 
|---|
 | 99 |         if (P->Par.me == 0)
 | 
|---|
 | 100 |           fprintf(stderr, "(%i) Warning: %s thermostat not implemented, falling back to None.", P->Par.me, I->ThermostatNames[1]);
 | 
|---|
 | 101 |         I->Thermostat = None;
 | 
|---|
 | 102 |       }
 | 
|---|
 | 103 |     } else if (strcmp(thermo, I->ThermostatNames[2]) == 0) { // Gaussian
 | 
|---|
 | 104 |       if (I->ThermostatImplemented[2] == 1) {
 | 
|---|
 | 105 |         I->Thermostat = Gaussian;
 | 
|---|
 | 106 |         ParseForParameter(P->Call.out[ReadOut],source,"Thermostat", 0, 2, 1, int_type, &P->R.ScaleTempStep, 1, critical); // read collision rate
 | 
|---|
 | 107 |       } else {
 | 
|---|
 | 108 |         if (P->Par.me == 0)
 | 
|---|
 | 109 |           fprintf(stderr, "(%i) Warning: %s thermostat not implemented, falling back to None.", P->Par.me, I->ThermostatNames[2]);
 | 
|---|
 | 110 |         I->Thermostat = None;
 | 
|---|
 | 111 |       }
 | 
|---|
 | 112 |     } else if (strcmp(thermo, I->ThermostatNames[3]) == 0) { // Langevin
 | 
|---|
 | 113 |       if (I->ThermostatImplemented[3] == 1) {
 | 
|---|
 | 114 |         I->Thermostat = Langevin;
 | 
|---|
 | 115 |         ParseForParameter(P->Call.out[ReadOut],source,"Thermostat", 0, 2, 1, double_type, &P->R.TempFrequency, 1, critical); // read gamma
 | 
|---|
 | 116 |         if (ParseForParameter(P->Call.out[ReadOut],source,"Thermostat", 0, 3, 1, double_type, &P->R.alpha, 1, optional)) {
 | 
|---|
 | 117 |           if (P->Par.me == 0) 
 | 
|---|
 | 118 |             fprintf(stderr,"(%i) Extended Stochastic Thermostat detected with interpolation coefficient %lg\n", P->Par.me, P->R.alpha);
 | 
|---|
 | 119 |         } else {
 | 
|---|
 | 120 |           P->R.alpha = 1.;
 | 
|---|
 | 121 |         }
 | 
|---|
 | 122 |       } else {
 | 
|---|
 | 123 |         if (P->Par.me == 0)
 | 
|---|
 | 124 |           fprintf(stderr, "(%i) Warning: %s thermostat not implemented, falling back to None.", P->Par.me, I->ThermostatNames[3]);
 | 
|---|
 | 125 |         I->Thermostat = None;
 | 
|---|
 | 126 |       }
 | 
|---|
 | 127 |     } else if (strcmp(thermo, I->ThermostatNames[4]) == 0) { // Berendsen
 | 
|---|
 | 128 |       if (I->ThermostatImplemented[4] == 1) {
 | 
|---|
 | 129 |         I->Thermostat = Berendsen;
 | 
|---|
 | 130 |         ParseForParameter(P->Call.out[ReadOut],source,"Thermostat", 0, 2, 1, double_type, &P->R.TempFrequency, 1, critical); // read \tau_T
 | 
|---|
 | 131 |       } else {
 | 
|---|
 | 132 |         if (P->Par.me == 0)
 | 
|---|
 | 133 |           fprintf(stderr, "(%i) Warning: %s thermostat not implemented, falling back to None.", P->Par.me, I->ThermostatNames[4]);
 | 
|---|
 | 134 |         I->Thermostat = None;
 | 
|---|
 | 135 |       }
 | 
|---|
 | 136 |     } else if (strcmp(thermo, I->ThermostatNames[5]) == 0) { // Nose-Hoover
 | 
|---|
 | 137 |       if (I->ThermostatImplemented[5] == 1) {
 | 
|---|
 | 138 |         I->Thermostat = NoseHoover;
 | 
|---|
 | 139 |         ParseForParameter(P->Call.out[ReadOut],source,"Thermostat", 0, 2, 1, double_type, &P->R.HooverMass, 1, critical); // read Hoovermass
 | 
|---|
 | 140 |         P->R.alpha = 0.;
 | 
|---|
 | 141 |       } else {
 | 
|---|
 | 142 |         if (P->Par.me == 0)
 | 
|---|
 | 143 |           fprintf(stderr, "(%i) Warning: %s thermostat not implemented, falling back to None.", P->Par.me, I->ThermostatNames[5]);
 | 
|---|
 | 144 |         I->Thermostat = None;
 | 
|---|
 | 145 |       }
 | 
|---|
 | 146 |     }
 | 
|---|
 | 147 |     if (I->Thermostat == -1) {
 | 
|---|
 | 148 |       if (P->Par.me == 0) 
 | 
|---|
 | 149 |         fprintf(stderr,"(%i) Warning: thermostat name was not understood!\n", P->Par.me);
 | 
|---|
 | 150 |       I->Thermostat = None;
 | 
|---|
 | 151 |     }
 | 
|---|
 | 152 |   } else {
 | 
|---|
 | 153 |     if ((P->R.MaxOuterStep > 0) && (P->R.TargetTemp != 0)) 
 | 
|---|
 | 154 |       debug(P, "No thermostat chosen despite finite temperature MD, falling back to None.");
 | 
|---|
 | 155 |     I->Thermostat = None;
 | 
|---|
 | 156 |   }
 | 
|---|
 | 157 |   if (F->MeOutMes) fprintf(F->TemperatureFile, "%s Thermostat\n",I->ThermostatNames[(int)I->Thermostat]); 
 | 
|---|
 | 158 |   Free(thermo, "InitThermostats: thermo");
 | 
|---|
 | 159 | }
 | 
|---|
 | 160 | 
 | 
|---|
| [961b75] | 161 | /** Parses for a given keyword the ion coordinates and velocites.
 | 
|---|
 | 162 |  * \param *P Problem at hand, contains pointer to Ion and IonType structure
 | 
|---|
 | 163 |  * \param *source
 | 
|---|
 | 164 |  * \param *keyword keyword string
 | 
|---|
 | 165 |  * \param repetition which repeated version of the keyword shall be read by ReadParameters()
 | 
|---|
 | 166 |  * \param relative whether atom coordinates are relative to unit cell size or absolute
 | 
|---|
 | 167 |  * \param Bohr conversion factor to atomiclength (e.g. 1.0 if coordinates in bohr radius, 0.529... if given in Angstrom)
 | 
|---|
 | 168 |  * \param sigma variance of maxwell-boltzmann distribution
 | 
|---|
 | 169 |  * \param *R where to put the read coordinates
 | 
|---|
 | 170 |  * \param *U where to put the read velocities
 | 
|---|
 | 171 |  * \param *IMT whether its MoveType#FixedIon or not
 | 
|---|
 | 172 |  * \return if 1 - success, 0 - failure
 | 
|---|
 | 173 |  */
 | 
|---|
 | 174 | int ParseIonsCoordinatesAndVelocities(struct Problem *P, FILE *source, char *keyword, int repetition, int relative, double sigma, double *R, double *U, int *IMT) 
 | 
|---|
 | 175 | {
 | 
|---|
 | 176 |   //struct RunStruct *Run = &P->R;
 | 
|---|
 | 177 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 178 |   struct Lattice *L = &P->Lat;
 | 
|---|
 | 179 |   int k;
 | 
|---|
 | 180 |   double R_trafo[3];
 | 
|---|
 | 181 |   gsl_rng * r;
 | 
|---|
 | 182 |   const gsl_rng_type * T;
 | 
|---|
 | 183 |   double Bohr = (I->IsAngstroem) ? ANGSTROEMINBOHRRADIUS : 1.;
 | 
|---|
 | 184 |   
 | 
|---|
 | 185 |   gsl_rng_env_setup();
 | 
|---|
 | 186 |   T = gsl_rng_default;
 | 
|---|
 | 187 |   r = gsl_rng_alloc (T);
 | 
|---|
 | 188 |   if (ParseForParameter(P->Call.out[ReadOut],source, keyword, 0, 1, 1, double_type, &R_trafo[0], repetition, optional) &&
 | 
|---|
 | 189 |     ParseForParameter(P->Call.out[ReadOut],source, keyword, 0, 2, 1, double_type, &R_trafo[1], repetition, optional) &&
 | 
|---|
 | 190 |     ParseForParameter(P->Call.out[ReadOut],source, keyword, 0, 3, 1, double_type, &R_trafo[2], repetition, optional) &&
 | 
|---|
 | 191 |     ParseForParameter(P->Call.out[ReadOut],source, keyword, 0, 4, 1, int_type, IMT, repetition, optional)) {
 | 
|---|
 | 192 |     // if read successful, then try also parsing velocities
 | 
|---|
 | 193 |     if ((ParseForParameter(P->Call.out[ReadOut],source, keyword, 0, 5, 1, double_type, &U[0], repetition, optional)) &&
 | 
|---|
 | 194 |       (ParseForParameter(P->Call.out[ReadOut],source, keyword, 0, 6, 1, double_type, &U[1], repetition, optional)) && 
 | 
|---|
 | 195 |       (ParseForParameter(P->Call.out[ReadOut],source, keyword, 0, 7, 1, double_type, &U[2], repetition, optional))) {
 | 
|---|
 | 196 |       //nothing
 | 
|---|
 | 197 |     } else {  // if no velocities specified, set to maxwell-boltzmann distributed
 | 
|---|
 | 198 |       if ((I->Thermostat != None)) {
 | 
|---|
 | 199 |         if (P->Par.me == 0) fprintf(stderr, "(%i) Missing velocities of ion %s: Maxwell-Boltzmann with %lg\n", P->Par.me, keyword, sigma);
 | 
|---|
 | 200 |         for (k=0;k<NDIM;k++)
 | 
|---|
 | 201 |           U[k] = gsl_ran_gaussian (r, sigma);
 | 
|---|
 | 202 |       } else {
 | 
|---|
 | 203 |         for (k=0;k<NDIM;k++)
 | 
|---|
 | 204 |           U[k] = 0.;
 | 
|---|
 | 205 |       }
 | 
|---|
 | 206 |     }
 | 
|---|
 | 207 |     // change if coordinates were relative
 | 
|---|
 | 208 |     if (relative) {
 | 
|---|
 | 209 |       //fprintf(stderr,"(%i)Ion coordinates are relative %i ... \n",P->Par.me, relative);
 | 
|---|
 | 210 |       RMat33Vec3(R, L->RealBasis, R_trafo); // multiply with real basis
 | 
|---|
 | 211 |     } else {
 | 
|---|
 | 212 |       for (k=0;k<NDIM;k++) // otherweise just copy to vector
 | 
|---|
 | 213 |         R[k] = R_trafo[k];
 | 
|---|
 | 214 |     }
 | 
|---|
 | 215 |     // check if given MoveType is valid
 | 
|---|
 | 216 |     if (*IMT < 0 || *IMT >= MaxIonMoveType) {
 | 
|---|
 | 217 |       fprintf(stderr,"Bad Ion MoveType set to MoveIon for %s\n", keyword);
 | 
|---|
 | 218 |       *IMT = 0;
 | 
|---|
 | 219 |     }
 | 
|---|
 | 220 |     if (!relative) {
 | 
|---|
 | 221 |       //fprintf(stderr,"converting with %lg\n", Bohr);
 | 
|---|
 | 222 |       SM(R, Bohr, NDIM); // convert angstroem to bohrradius
 | 
|---|
 | 223 |       SM(U, Bohr, NDIM); // convert angstroem to bohrradius
 | 
|---|
 | 224 |     }
 | 
|---|
 | 225 |     // finally periodicly correct coordinates to remain in unit cell
 | 
|---|
 | 226 |     RMat33Vec3(R_trafo, L->InvBasis, R);
 | 
|---|
 | 227 |     for (k=0; k <NDIM; k++) { // periodic correction until within unit cell
 | 
|---|
 | 228 |       while (R_trafo[k] < 0) 
 | 
|---|
 | 229 |         R_trafo[k] += 1.0;
 | 
|---|
 | 230 |       while (R_trafo[k] >= 1.0) 
 | 
|---|
 | 231 |         R_trafo[k] -= 1.0;
 | 
|---|
 | 232 |     }
 | 
|---|
 | 233 |     RMat33Vec3(R, L->RealBasis, R_trafo);
 | 
|---|
 | 234 |     // print coordinates if desired
 | 
|---|
 | 235 |     if ((P->Call.out[ReadOut])) {
 | 
|---|
 | 236 |       fprintf(stderr,"(%i) coordinates of Ion %s: (x,y,z) = (",P->Par.me, keyword);
 | 
|---|
 | 237 |       for(k=0;k<NDIM;k++) {
 | 
|---|
 | 238 |         fprintf(stderr,"%lg ",R[k]);
 | 
|---|
 | 239 |         if (k != NDIM-1) fprintf(stderr,", ");
 | 
|---|
 | 240 |         else fprintf(stderr,")\n");
 | 
|---|
 | 241 |       }
 | 
|---|
 | 242 |     }
 | 
|---|
 | 243 |     gsl_rng_free (r);
 | 
|---|
 | 244 |     return 1;
 | 
|---|
 | 245 |   } else {
 | 
|---|
 | 246 |     for (k=0;k<NDIM;k++) {
 | 
|---|
 | 247 |       U[k] = R[k] = 0.;
 | 
|---|
 | 248 |     }
 | 
|---|
 | 249 |     *IMT = 0; 
 | 
|---|
 | 250 |     gsl_rng_free (r);
 | 
|---|
 | 251 |     return 0;
 | 
|---|
 | 252 |   }
 | 
|---|
 | 253 | }
 | 
|---|
 | 254 | 
 | 
|---|
| [a0bcf1] | 255 | /** Readin of the ion section of parameter file.
 | 
|---|
 | 256 |  * Among others the following paramaters are read from file:
 | 
|---|
 | 257 |  * Ions::MaxTypes, IonType::Max_IonsOfType, IonType::Z, IonType::R,
 | 
|---|
 | 258 |  * IonType:IMT, ...
 | 
|---|
 | 259 |  * \param P Problem at hand (containing Ions and Lattice structures)
 | 
|---|
 | 260 |  * \param *source file pointer
 | 
|---|
 | 261 |  */
 | 
|---|
 | 262 | void IonsInitRead(struct Problem *P, FILE *source) {
 | 
|---|
 | 263 |         struct Ions *I = &P->Ion;
 | 
|---|
 | 264 |   //struct RunStruct *Run = &P->R;
 | 
|---|
| [961b75] | 265 |   int i,it,j,IMT,d,me, count;
 | 
|---|
| [a0bcf1] | 266 |   int relative; // whether read-in coordinate are relative (1) or absolute  
 | 
|---|
| [460e95] | 267 |   double Bohr = ANGSTROEMINBOHRRADIUS; /* Angstroem */
 | 
|---|
 | 268 |   double sigma, R[3], U[3];
 | 
|---|
| [961b75] | 269 |   struct IonConstrained *ptr = NULL;
 | 
|---|
 | 270 |      
 | 
|---|
| [a0bcf1] | 271 |   I->Max_TotalIons = 0;
 | 
|---|
 | 272 |   I->TotalZval = 0;
 | 
|---|
 | 273 |   MPI_Comm_rank(MPI_COMM_WORLD, &me);
 | 
|---|
| [961b75] | 274 |   ParseForParameter(P->Call.out[ReadOut],source,"RCut", 0, 1, 1, double_type, &I->R_cut, 1, critical);
 | 
|---|
 | 275 |   ParseForParameter(P->Call.out[ReadOut],source,"IsAngstroem", 0, 1, 1, int_type, &I->IsAngstroem, 1, critical);
 | 
|---|
| [460e95] | 276 |   if (!I->IsAngstroem) {
 | 
|---|
| [961b75] | 277 |     Bohr = 1.0;
 | 
|---|
 | 278 |   } else {  // adapt RealBasis (is in Angstroem as well)
 | 
|---|
| [460e95] | 279 |     SM(P->Lat.RealBasis, Bohr, NDIM_NDIM); 
 | 
|---|
 | 280 |     RMatReci3(P->Lat.InvBasis,  P->Lat.RealBasis);
 | 
|---|
 | 281 |   }
 | 
|---|
| [961b75] | 282 |   ParseForParameter(P->Call.out[ReadOut],source,"MaxTypes", 0, 1, 1, int_type, &I->Max_Types, 1, critical);
 | 
|---|
| [a0bcf1] | 283 |   I->I = (struct IonType *) Malloc(sizeof(struct IonType)*I->Max_Types, "IonsInitRead: IonType");
 | 
|---|
| [961b75] | 284 |   if (!ParseForParameter(P->Call.out[ReadOut],source,"RelativeCoord", 0, 1, 1, int_type, &relative, 1, optional))
 | 
|---|
| [a0bcf1] | 285 |     relative = 0;
 | 
|---|
| [961b75] | 286 |   if (!ParseForParameter(P->Call.out[ReadOut],source,"StructOpt", 0, 1, 1, int_type, &I->StructOpt, 1, optional))
 | 
|---|
| [a0bcf1] | 287 |     I->StructOpt = 0;
 | 
|---|
| [961b75] | 288 |   
 | 
|---|
| [b74e5e] | 289 |   InitThermostats(P, source);
 | 
|---|
| [961b75] | 290 |   
 | 
|---|
| [a0bcf1] | 291 |   /* Ions Data */
 | 
|---|
 | 292 |   I->RLatticeVec = NULL;
 | 
|---|
 | 293 |   I->TotalMass = 0;
 | 
|---|
 | 294 |   char *free_name, *name;
 | 
|---|
| [c510a7] | 295 |   name = free_name = Malloc(MAXSTRINGSIZE*sizeof(char),"IonsInitRead: Name");
 | 
|---|
| [a0bcf1] | 296 |   for (i=0; i < I->Max_Types; i++) {
 | 
|---|
 | 297 |         sprintf(name,"Ion_Type%i",i+1);
 | 
|---|
 | 298 |     I->I[i].corecorr = NotCoreCorrected;
 | 
|---|
| [c510a7] | 299 |     I->I[i].Name = MallocString(MAXSTRINGSIZE, "IonsInitRead: Name");
 | 
|---|
 | 300 |     I->I[i].Symbol = MallocString(MAXSTRINGSIZE, "IonsInitRead: Symbol");
 | 
|---|
| [961b75] | 301 |                 ParseForParameter(P->Call.out[ReadOut],source, name, 0, 1, 1, int_type, &I->I[i].Max_IonsOfType, 1, critical);
 | 
|---|
 | 302 |                 ParseForParameter(P->Call.out[ReadOut],source, name, 0, 2, 1, int_type, &I->I[i].Z, 1, critical);
 | 
|---|
 | 303 |                 ParseForParameter(P->Call.out[ReadOut],source, name, 0, 3, 1, double_type, &I->I[i].rgauss, 1, critical);
 | 
|---|
 | 304 |                 ParseForParameter(P->Call.out[ReadOut],source, name, 0, 4, 1, int_type, &I->I[i].l_max, 1, critical);
 | 
|---|
 | 305 |                 ParseForParameter(P->Call.out[ReadOut],source, name, 0, 5, 1, int_type, &I->I[i].l_loc, 1, critical);
 | 
|---|
 | 306 |                 ParseForParameter(P->Call.out[ReadOut],source, name, 0, 6, 1, double_type, &I->I[i].IonMass, 1, critical);
 | 
|---|
 | 307 |     if(!ParseForParameter(P->Call.out[ReadOut],source, name, 0, 7, 1, string_type, &I->I[i].Name[0], 1, optional))
 | 
|---|
| [a0bcf1] | 308 |       sprintf(&I->I[i].Name[0],"type%i",i);
 | 
|---|
| [961b75] | 309 |     if(!ParseForParameter(P->Call.out[ReadOut],source, name, 0, 8, 1, string_type, &I->I[i].Symbol[0], 1, optional))
 | 
|---|
| [a0bcf1] | 310 |       sprintf(&I->I[i].Symbol[0],"t%i",i);
 | 
|---|
 | 311 |     if (P->Call.out[ReadOut]) fprintf(stderr,"(%i) Element name: %s, symbol: %s\n",P->Par.me, I->I[i].Name, I->I[i].Symbol);
 | 
|---|
| [961b75] | 312 |     I->I[i].moment = (double **) Malloc(sizeof(double *) * I->I[i].Max_IonsOfType, "IonsInitRead: moment");
 | 
|---|
| [a0bcf1] | 313 |     I->I[i].sigma = (double **) Malloc(sizeof(double *) * I->I[i].Max_IonsOfType, "IonsInitRead: sigma");
 | 
|---|
 | 314 |     I->I[i].sigma_rezi = (double **) Malloc(sizeof(double *) * I->I[i].Max_IonsOfType, "IonsInitRead: sigma_rezi");
 | 
|---|
 | 315 |     I->I[i].sigma_PAS = (double **) Malloc(sizeof(double *) * I->I[i].Max_IonsOfType, "IonsInitRead: sigma_PAS");
 | 
|---|
 | 316 |     I->I[i].sigma_rezi_PAS = (double **) Malloc(sizeof(double *) * I->I[i].Max_IonsOfType, "IonsInitRead: sigma_rezi_PAS");
 | 
|---|
 | 317 |     for (it=0;it<I->I[i].Max_IonsOfType;it++) {
 | 
|---|
| [961b75] | 318 |       I->I[i].moment[it] = (double *) Malloc(sizeof(double) * NDIM*NDIM, "IonsInitRead: moment");
 | 
|---|
| [a0bcf1] | 319 |       I->I[i].sigma[it] = (double *) Malloc(sizeof(double) * NDIM*NDIM, "IonsInitRead: sigma");
 | 
|---|
 | 320 |       I->I[i].sigma_rezi[it] = (double *) Malloc(sizeof(double) * NDIM*NDIM, "IonsInitRead: sigma_rezi");
 | 
|---|
 | 321 |       I->I[i].sigma_PAS[it] = (double *) Malloc(sizeof(double) * NDIM, "IonsInitRead: sigma_PAS");
 | 
|---|
 | 322 |       I->I[i].sigma_rezi_PAS[it] = (double *) Malloc(sizeof(double) * NDIM, "IonsInitRead: sigma_rezi_PAS");
 | 
|---|
 | 323 |     }
 | 
|---|
 | 324 |     //I->I[i].IonFac = I->I[i].IonMass;
 | 
|---|
| [961b75] | 325 |     I->I[i].IonMass *= Units2Electronmass;  // in config given in amu not in "atomic units" (electron mass, m_e = 1)
 | 
|---|
 | 326 |                                             // proportional factor between electron and proton mass
 | 
|---|
 | 327 |     I->I[i].IonFac = Units2Electronmass/I->I[i].IonMass;
 | 
|---|
| [a0bcf1] | 328 |     I->TotalMass += I->I[i].Max_IonsOfType*I->I[i].IonMass;
 | 
|---|
| [961b75] | 329 |     sigma = sqrt(P->R.TargetTemp/I->I[i].IonMass);
 | 
|---|
| [a0bcf1] | 330 |     I->I[i].ZFactor = -I->I[i].Z*4.*PI;
 | 
|---|
 | 331 |     I->I[i].alpha = (double *) Malloc(sizeof(double) * I->I[i].Max_IonsOfType, "IonsInitRead: alpha");
 | 
|---|
 | 332 |     I->I[i].R = (double *) Malloc(sizeof(double) * NDIM * I->I[i].Max_IonsOfType, "IonsInitRead: R");
 | 
|---|
 | 333 |     I->I[i].R_old = (double *) Malloc(sizeof(double) *NDIM* I->I[i].Max_IonsOfType, "IonsInitRead: R_old");
 | 
|---|
 | 334 |     I->I[i].R_old_old = (double *) Malloc(sizeof(double) *NDIM* I->I[i].Max_IonsOfType, "IonsInitRead: R_old_old");
 | 
|---|
| [961b75] | 335 |     I->I[i].Constraints = (struct IonConstrained **) Malloc(sizeof(struct IonConstrained *)*I->I[i].Max_IonsOfType, "IonsInitRead: **Constraints");
 | 
|---|
 | 336 |     for (it=0;it<I->I[i].Max_IonsOfType;it++)
 | 
|---|
 | 337 |       I->I[i].Constraints[it] = NULL;
 | 
|---|
| [a0bcf1] | 338 |     I->I[i].FIon = (double *) Malloc(sizeof(double) * NDIM * I->I[i].Max_IonsOfType, "IonsInitRead: FIon");
 | 
|---|
 | 339 |     I->I[i].FIon_old = (double *) Malloc(sizeof(double) * NDIM * I->I[i].Max_IonsOfType, "IonsInitRead: FIon_old");
 | 
|---|
 | 340 |     SetArrayToDouble0(I->I[i].FIon_old, NDIM*I->I[i].Max_IonsOfType);
 | 
|---|
 | 341 |     I->I[i].SearchDir = Malloc(sizeof(double) * NDIM * I->I[i].Max_IonsOfType, "IonsInitRead: SearchDir");
 | 
|---|
 | 342 |     I->I[i].GammaA = Malloc(sizeof(double) * I->I[i].Max_IonsOfType, "IonsInitRead: GammaA");
 | 
|---|
 | 343 |     SetArrayToDouble0(I->I[i].GammaA, I->I[i].Max_IonsOfType);
 | 
|---|
 | 344 |     I->I[i].U = (double *) Malloc(sizeof(double) *NDIM* I->I[i].Max_IonsOfType, "IonsInitRead: U");
 | 
|---|
 | 345 |     SetArrayToDouble0(I->I[i].U, NDIM*I->I[i].Max_IonsOfType);
 | 
|---|
 | 346 |     I->I[i].SFactor = NULL;
 | 
|---|
 | 347 |     I->I[i].IMT = (enum IonMoveType *) Malloc(sizeof(enum IonMoveType) * I->I[i].Max_IonsOfType, "IonsInitRead: IMT");
 | 
|---|
 | 348 |     I->I[i].FIonL = (double *) Malloc(sizeof(double) * NDIM * I->I[i].Max_IonsOfType, "IonsInitRead: FIonL");
 | 
|---|
 | 349 |     I->I[i].FIonNL = (double *) Malloc(sizeof(double) * NDIM * I->I[i].Max_IonsOfType, "IonsInitRead: FIonNL");
 | 
|---|
| [961b75] | 350 |     I->I[i].FMagnetic = (double *) Malloc(sizeof(double) * NDIM * I->I[i].Max_IonsOfType, "IonsInitRead: FMagnetic");
 | 
|---|
 | 351 |     I->I[i].FConstraint = (double *) Malloc(sizeof(double) * NDIM * I->I[i].Max_IonsOfType, "IonsInitRead: FConstraint");
 | 
|---|
| [a0bcf1] | 352 |     I->I[i].FEwald = (double *) Malloc(sizeof(double) * NDIM * I->I[i].Max_IonsOfType, "IonsInitRead: FEwald");
 | 
|---|
 | 353 |     I->I[i].alpha = (double *) Malloc(sizeof(double) * I->I[i].Max_IonsOfType, "IonsInitRead: alpha");
 | 
|---|
| [961b75] | 354 |     // now parse ion coordination
 | 
|---|
| [a0bcf1] | 355 |     for (j=0; j < I->I[i].Max_IonsOfType; j++) {
 | 
|---|
 | 356 |       I->I[i].alpha[j] = 2.;
 | 
|---|
 | 357 |         sprintf(name,"Ion_Type%i_%i",i+1,j+1);
 | 
|---|
| [961b75] | 358 |       for (d=0; d <NDIM; d++) // transfor to old and old_old coordinates as well
 | 
|---|
 | 359 |         I->I[i].FMagnetic[d+j*NDIM] = 0.;
 | 
|---|
 | 360 |       // first ones are starting positions
 | 
|---|
 | 361 |       if ((count = ParseIonsCoordinatesAndVelocities(P, source, name, 1, relative, sigma, &I->I[i].R[NDIM*j], &I->I[i].U[NDIM*j], &IMT))) {
 | 
|---|
 | 362 |         for (d=0; d <NDIM; d++) // transfor to old and old_old coordinates as well
 | 
|---|
 | 363 |           I->I[i].R_old_old[d+NDIM*j] = I->I[i].R_old[d+NDIM*j] = I->I[i].R[d+NDIM*j];
 | 
|---|
 | 364 |         I->I[i].IMT[j] = IMT;
 | 
|---|
 | 365 |         if (P->Call.out[ReadOut]) fprintf(stderr, "(%i) R[%d,%d] = (%lg, %lg, %lg)\n", P->Par.me, i,j,I->I[i].R[0+NDIM*j],I->I[i].R[1+NDIM*j],I->I[i].R[2+NDIM*j]);
 | 
|---|
 | 366 |         if (P->Call.out[ReadOut]) fprintf(stderr, "(%i) U[%d,%d] = (%lg, %lg, %lg)\n", P->Par.me, i,j,I->I[i].U[0+NDIM*j],I->I[i].U[1+NDIM*j],I->I[i].U[2+NDIM*j]);
 | 
|---|
 | 367 |         if (P->Call.out[ReadOut]) fprintf(stderr, "(%i) IMT[%d,%d] = %i\n", P->Par.me, i,j,I->I[i].IMT[j]);
 | 
|---|
| [a0bcf1] | 368 |       } else {
 | 
|---|
| [961b75] | 369 |         Error(SomeError, "Could not find or parse coordinates of an ion");
 | 
|---|
| [a0bcf1] | 370 |       }
 | 
|---|
| [961b75] | 371 |       // following ones are constrained motions
 | 
|---|
 | 372 |       while (ParseIonsCoordinatesAndVelocities(P, source, name, ++count, relative, sigma, R, U, &IMT)) {
 | 
|---|
 | 373 |         if (P->Call.out[ReadOut]) fprintf(stderr, "(%i) Constrained read %d ...\n", P->Par.me, count-1);
 | 
|---|
 | 374 |         ptr = AddConstraintItem(&I->I[i], j);  // allocate memory
 | 
|---|
 | 375 |         for (d=0; d< NDIM; d++) { // fill the constraint item
 | 
|---|
 | 376 |           ptr->R[d] = R[d];
 | 
|---|
 | 377 |           ptr->U[d] = U[d];
 | 
|---|
| [a0bcf1] | 378 |         }
 | 
|---|
| [961b75] | 379 |         ptr->IMT = IMT;
 | 
|---|
 | 380 |         ptr->step = count-1;
 | 
|---|
 | 381 |         if (P->Call.out[ReadOut]) fprintf(stderr, "(%i) R[%d,%d] = (%lg, %lg, %lg)\n", P->Par.me, i,j,ptr->R[0],ptr->R[1],ptr->R[2]);
 | 
|---|
 | 382 |         if (P->Call.out[ReadOut]) fprintf(stderr, "(%i) U[%d,%d] = (%lg, %lg, %lg)\n", P->Par.me, i,j,ptr->U[0],ptr->U[1],ptr->U[2]);
 | 
|---|
 | 383 |         if (P->Call.out[ReadOut]) fprintf(stderr, "(%i) IMT[%d,%d] = %i\n", P->Par.me, i,j,ptr->IMT);
 | 
|---|
| [a0bcf1] | 384 |       }
 | 
|---|
| [961b75] | 385 |       //if (P->Call.out[ReadOut]) 
 | 
|---|
 | 386 |       fprintf(stderr,"(%i) A total of %d additional constrained moves for ion (%d,%d) was parsed.\n", P->Par.me, count-2, i,j);
 | 
|---|
| [a0bcf1] | 387 | 
 | 
|---|
 | 388 |       I->Max_TotalIons++;
 | 
|---|
 | 389 |     }
 | 
|---|
 | 390 |   }
 | 
|---|
| [32de28] | 391 |   Free(free_name, "IonsInitRead: free_name");
 | 
|---|
| [a0bcf1] | 392 |   I->Max_Max_IonsOfType = 0;
 | 
|---|
 | 393 |   for (i=0; i < I->Max_Types; i++) 
 | 
|---|
 | 394 |     I->Max_Max_IonsOfType = MAX(I->Max_Max_IonsOfType, I->I[i].Max_IonsOfType);
 | 
|---|
 | 395 |   I->FTemp = (double *) Malloc(sizeof(double) * NDIM * I->Max_Max_IonsOfType, "IonsInitRead:");
 | 
|---|
 | 396 | }
 | 
|---|
 | 397 | 
 | 
|---|
| [32de28] | 398 | /** Allocates memory for a IonConstrained item and adds to end of list.
 | 
|---|
 | 399 |  * \param *I IonType structure
 | 
|---|
 | 400 |  * \param ion which ion of the type
 | 
|---|
 | 401 |  * \return pointer to created item
 | 
|---|
 | 402 |  */
 | 
|---|
 | 403 | struct IonConstrained * AddConstraintItem(struct IonType *I, int ion)
 | 
|---|
 | 404 | {
 | 
|---|
 | 405 |   struct IonConstrained **ptr = &(I->Constraints[ion]);
 | 
|---|
 | 406 |   while (*ptr != NULL) { // advance to end of list
 | 
|---|
 | 407 |     ptr = &((*ptr)->next);
 | 
|---|
 | 408 |   }
 | 
|---|
 | 409 |   // allocated memory for structure and items within
 | 
|---|
 | 410 |   *ptr = (struct IonConstrained *) Malloc(sizeof(struct IonConstrained), "CreateConstraintItem: IonConstrained");
 | 
|---|
 | 411 |   (*ptr)->R = (double *) Malloc(sizeof(double)*NDIM, "AddConstraintItem: *R");
 | 
|---|
 | 412 |   (*ptr)->U = (double *) Malloc(sizeof(double)*NDIM, "AddConstraintItem: *U");
 | 
|---|
 | 413 |   (*ptr)->next = NULL;
 | 
|---|
 | 414 |   return *ptr;
 | 
|---|
 | 415 | }
 | 
|---|
 | 416 | 
 | 
|---|
 | 417 | /** Removes first of item of IonConstrained list for given \a ion.
 | 
|---|
 | 418 |  * Frees memory of items within and then
 | 
|---|
 | 419 |  * \param *I IonType structure
 | 
|---|
 | 420 |  * \param ion which ion of the type
 | 
|---|
 | 421 |  * \return 1 - success, 0 - failure (list is already empty, start pointer was NULL)
 | 
|---|
 | 422 |  */ 
 | 
|---|
 | 423 | int RemoveConstraintItem(struct IonType *I, int ion)
 | 
|---|
 | 424 | {
 | 
|---|
 | 425 |   struct IonConstrained **ptr = &(I->Constraints[ion]); 
 | 
|---|
 | 426 |   struct IonConstrained *next_ptr;
 | 
|---|
 | 427 |   if (*ptr != NULL) {
 | 
|---|
 | 428 |     next_ptr = (*ptr)->next;
 | 
|---|
 | 429 |     Free((*ptr)->R, "RemoveConstraintItem: R");
 | 
|---|
 | 430 |     Free((*ptr)->U, "RemoveConstraintItem: U");
 | 
|---|
 | 431 |     Free((*ptr), "RemoveConstraintItem: IonConstrained structure");
 | 
|---|
 | 432 |     *ptr = next_ptr; // set start of list to next item (automatically is null if ptr was last item)
 | 
|---|
 | 433 |     return 1;
 | 
|---|
 | 434 |   } else {
 | 
|---|
 | 435 |     return 0;
 | 
|---|
 | 436 |   }
 | 
|---|
 | 437 | }
 | 
|---|
 | 438 | 
 | 
|---|
| [a0bcf1] | 439 | /** Calculated Ewald force.
 | 
|---|
| [c5bdb23] | 440 |  * The basic idea of the ewald method is to add a countercharge - here of gaussian form -
 | 
|---|
 | 441 |  * which shields the long-range charges making them effectively short-ranged, while the
 | 
|---|
 | 442 |  * countercharges themselves can be analytically (here by (hidden) Fouriertransform: it's
 | 
|---|
 | 443 |  * added to the electron density) integrated and withdrawn. 
 | 
|---|
| [a0bcf1] | 444 |  * \f[
 | 
|---|
 | 445 |  *  E_{K-K} = \frac{1}{2} \sum_L \sum_{K=\{(I_s,I_a,J_s,J_a)|R_{I_s,I_a} - R_{J_s,J_a} - L\neq 0\}} \frac{Z_{I_s} Z_{J_s}} {|R_{I_s,I_a} - R_{J_s,J_a} - L|} 
 | 
|---|
 | 446 |  *    \textnormal{erfc} \Bigl ( \frac{|R_{I_s,I_a} - R_{J_s,J_a} - L|} {\sqrt{r_{I_s}^{Gauss}+r_{J_s}^{Gauss}}}\Bigr )
 | 
|---|
 | 447 |  *    \qquad (4.10)
 | 
|---|
 | 448 |  * \f]
 | 
|---|
 | 449 |  * Calculates the core-to-core force between the ions of all super cells.
 | 
|---|
 | 450 |  * In order for this series to converge there must be a certain summation
 | 
|---|
 | 451 |  * applied, which is the ewald summation and which is nothing else but to move
 | 
|---|
 | 452 |  * in a circular motion from the current cell to the outside up to Ions::R_cut.
 | 
|---|
 | 453 |  * \param *P Problem at hand
 | 
|---|
| [c5bdb23] | 454 |  * \param first if != 0 table mirror cells to take into (local!) account of ewald summation 
 | 
|---|
| [a0bcf1] | 455 |  */
 | 
|---|
 | 456 | void CalculateEwald(struct Problem *P, int first) 
 | 
|---|
 | 457 | {
 | 
|---|
| [c5bdb23] | 458 |   int r,is1,is2,ia1,ia2,ir,ir2,i,j,k,ActualVec,MaxVec,MaxCell,Is_Neighb_Cell,LocalActualVec; //,is
 | 
|---|
| [a0bcf1] | 459 |   int MaxPar=P->Par.procs, ParMe=P->Par.me, MaxLocalVec, StartVec;
 | 
|---|
 | 460 |   double rcut2,r2,erre2,addesr,addpre,arg,fac,gkl,esr,fxx,repand;
 | 
|---|
 | 461 |   double R1[3];
 | 
|---|
 | 462 |   double R2[3];
 | 
|---|
 | 463 |   double R3[3];
 | 
|---|
 | 464 |   double t[3];
 | 
|---|
 | 465 |   struct Lattice *L = &P->Lat;
 | 
|---|
 | 466 |   struct PseudoPot *PP = &P->PP;
 | 
|---|
 | 467 |   struct Ions *I = &P->Ion;
 | 
|---|
| [c5bdb23] | 468 |   if (first) {
 | 
|---|
 | 469 |     SpeedMeasure(P, InitSimTime, StopTimeDo);
 | 
|---|
 | 470 |     rcut2 = I->R_cut*I->R_cut;
 | 
|---|
 | 471 |     ActualVec = 0;  // counts number of cells taken into account
 | 
|---|
 | 472 |     MaxCell = (int)(5.*I->R_cut/pow(L->Volume,1./3.));    // the number of cells in each direction is prop. to axis length over cutoff
 | 
|---|
 | 473 |     if (MaxCell < 2) MaxCell = 2;     // take at least 2
 | 
|---|
 | 474 |     for (i = -MaxCell; i <= MaxCell; i++) {
 | 
|---|
 | 475 |       for (j = -MaxCell; j <= MaxCell; j++) {
 | 
|---|
 | 476 |                                 for (k = -MaxCell; k <= MaxCell; k++) {
 | 
|---|
 | 477 |                                   r2 = 0.;
 | 
|---|
 | 478 |                                   for (ir=0; ir <NDIM; ir++) {  // t is the offset vector pointing to distant cell (only diagonal entries)
 | 
|---|
 | 479 |                                     t[ir] = i*L->RealBasis[0*NDIM+ir]+j*L->RealBasis[1*NDIM+ir]+k*L->RealBasis[2*NDIM+ir];
 | 
|---|
 | 480 |                                     r2 = t[ir]*t[ir];   // is squared distance to other cell 
 | 
|---|
 | 481 |                                   }
 | 
|---|
 | 482 |                                   Is_Neighb_Cell = ((abs(i)<=1) && (abs(j)<=1) && (abs(k)<=1));   // whether it's directly adjacent
 | 
|---|
 | 483 |                                   if ((r2 <= rcut2) || Is_Neighb_Cell) {    // if it's either adjacent or within cutoff, count it in
 | 
|---|
 | 484 |                                     ActualVec++;
 | 
|---|
 | 485 |                                   }
 | 
|---|
 | 486 |                                 }
 | 
|---|
| [a0bcf1] | 487 |       }
 | 
|---|
| [c5bdb23] | 488 |     }
 | 
|---|
 | 489 |     MaxVec = ActualVec;   // store number of cells
 | 
|---|
 | 490 |     I->MaxVec = ActualVec;
 | 
|---|
 | 491 |     MaxLocalVec = MaxVec / MaxPar;  // share among processes
 | 
|---|
 | 492 |     StartVec = ParMe*MaxLocalVec; // for this process start at its patch
 | 
|---|
 | 493 |     r = MaxVec % MaxPar;  // rest not fitting...
 | 
|---|
 | 494 |     if (ParMe >= r) {   // ones who don't get extra cells have to shift their start vector
 | 
|---|
 | 495 |       StartVec += r;
 | 
|---|
 | 496 |     } else {    // others get extra cell and have to shift also by a bit
 | 
|---|
 | 497 |       StartVec += ParMe;
 | 
|---|
 | 498 |       MaxLocalVec++;
 | 
|---|
 | 499 |     }
 | 
|---|
 | 500 |     I->MaxLocalVec = MaxLocalVec;
 | 
|---|
 | 501 |     LocalActualVec = ActualVec = 0;
 | 
|---|
 | 502 |     // now go through the same loop again and note down every offset vector for cells in this process' patch
 | 
|---|
 | 503 |     if (MaxLocalVec != 0) {
 | 
|---|
| [a0bcf1] | 504 |       I->RLatticeVec = (double *)
 | 
|---|
| [c5bdb23] | 505 |         Realloc(I->RLatticeVec, sizeof(double)*NDIM*MaxLocalVec, "CalculateEwald: I->RLatticeVec");
 | 
|---|
 | 506 |     } else {
 | 
|---|
 | 507 |       fprintf(stderr,"(%i) Warning in Ewald summation: Got MaxLocalVec == 0\n", P->Par.me);
 | 
|---|
 | 508 |     }
 | 
|---|
 | 509 |     for (i = -MaxCell; i <= MaxCell; i++) {
 | 
|---|
 | 510 |       for (j = -MaxCell; j <= MaxCell; j++) {
 | 
|---|
 | 511 |                                 for (k = -MaxCell; k <= MaxCell; k++) {
 | 
|---|
 | 512 |                                   r2 = 0.;
 | 
|---|
 | 513 |                                   for (ir=0; ir <NDIM; ir++) {  // create offset vector from diagonal entries
 | 
|---|
 | 514 |                                     t[ir] = i*L->RealBasis[0*NDIM+ir]+j*L->RealBasis[1*NDIM+ir]+k*L->RealBasis[2*NDIM+ir];
 | 
|---|
 | 515 |                                     r2 = t[ir]*t[ir];
 | 
|---|
 | 516 |                                   }
 | 
|---|
 | 517 |                                   Is_Neighb_Cell = ((abs(i)<=1) && (abs(j)<=1) && (abs(k)<=1));
 | 
|---|
 | 518 |                                   if ((r2 <= rcut2) || Is_Neighb_Cell) {  // if adjacent or within cutoff ...
 | 
|---|
 | 519 |                                     if (ActualVec >= StartVec && ActualVec < StartVec+MaxLocalVec) { // ... and belongs to patch, store 'em
 | 
|---|
 | 520 |                                       I->RLatticeVec[0+NDIM*LocalActualVec] = t[0];
 | 
|---|
 | 521 |                                       I->RLatticeVec[1+NDIM*LocalActualVec] = t[1];
 | 
|---|
 | 522 |                                       I->RLatticeVec[2+NDIM*LocalActualVec] = t[2];
 | 
|---|
 | 523 |                                       LocalActualVec++;
 | 
|---|
 | 524 |                                     }
 | 
|---|
 | 525 |                                     ActualVec++;
 | 
|---|
 | 526 |                                   }
 | 
|---|
 | 527 |                                 }
 | 
|---|
| [a0bcf1] | 528 |       }
 | 
|---|
 | 529 |     }
 | 
|---|
| [c5bdb23] | 530 |     SpeedMeasure(P, InitSimTime, StartTimeDo);
 | 
|---|
 | 531 |   }
 | 
|---|
 | 532 |   SpeedMeasure(P, EwaldTime, StartTimeDo);
 | 
|---|
 | 533 | 
 | 
|---|
 | 534 |   // first set everything to zero
 | 
|---|
 | 535 |   esr = 0.0;
 | 
|---|
 | 536 |   //for (is1=0;is1 < I->Max_Types; is1++) 
 | 
|---|
 | 537 |   // then take each ion of each type once 
 | 
|---|
 | 538 |   for (is1=0;is1 < I->Max_Types; is1++) {
 | 
|---|
 | 539 |     // reset FTemp for IonType
 | 
|---|
 | 540 |     for (ia1=0;ia1 < I->I[is1].Max_IonsOfType; ia1++)
 | 
|---|
 | 541 |       for (i=0; i< NDIM; i++)
 | 
|---|
 | 542 |         I->FTemp[i+NDIM*(ia1)] = 0.;
 | 
|---|
 | 543 |     // then sum for each on of the IonType
 | 
|---|
 | 544 |     for (ia1=0;ia1 < I->I[is1].Max_IonsOfType; ia1++) {
 | 
|---|
 | 545 |       for (i=0;i<NDIM;i++) {
 | 
|---|
 | 546 |                                 R1[i]=I->I[is1].R[i+NDIM*ia1];    // R1 is local coordinate of current first ion
 | 
|---|
 | 547 |       }
 | 
|---|
 | 548 |       for (ir2=0;ir2<I->MaxLocalVec;ir2++) {  // for every cell of local patch (each with the same atoms)
 | 
|---|
 | 549 |                                 for (is2=0;is2 < I->Max_Types; is2++) { // and for each ion of each type a second time
 | 
|---|
 | 550 |           // gkl = 1./(sqrt(r_is1,gauss^2 + r_is2,gauss^2))
 | 
|---|
 | 551 |                                   gkl=1./sqrt(I->I[is1].rgauss*I->I[is1].rgauss + I->I[is2].rgauss*I->I[is2].rgauss);
 | 
|---|
 | 552 |                                   for (ia2=0;ia2<I->I[is2].Max_IonsOfType; ia2++) {
 | 
|---|
 | 553 |                                     for (i=0;i<3;i++) {
 | 
|---|
 | 554 |                                       R2[i]=I->RLatticeVec[i+NDIM*ir2]+I->I[is2].R[i+NDIM*ia2]; // R2 is coordinate of current second ion in the distant cell!
 | 
|---|
 | 555 |                                     }
 | 
|---|
 | 556 | 
 | 
|---|
 | 557 |                                     erre2=0.0;
 | 
|---|
 | 558 |                                     for (i=0;i<NDIM;i++) {
 | 
|---|
 | 559 |                                       R3[i] = R1[i]-R2[i];    // R3 = R_is1,ia1 - R_is2,ia2 - L
 | 
|---|
 | 560 |                                       erre2+=R3[i]*R3[i];     // erre2 = |R_is1,ia1 - R_is2,ia2 - L|^2
 | 
|---|
 | 561 |                                     }
 | 
|---|
 | 562 |                                     if (erre2 > MYEPSILON) {  // appears as one over ... in fac, thus check if zero
 | 
|---|
 | 563 |               arg = sqrt(erre2); // arg = |R_is1,ia1 - R_is2,ia2 - L|
 | 
|---|
 | 564 |                                       fac=PP->zval[is1]*PP->zval[is2]/arg*0.5;    // fac = -1/2 * Z_is1 * Z_is2 / arg
 | 
|---|
 | 565 |                                       
 | 
|---|
 | 566 |                                       arg *= gkl;             // arg = |R_is1,ia1 - R_is2,ia2 - L|/(sqrt(r_is1,gauss^2 + r_is2,gauss^2))
 | 
|---|
 | 567 |                                       addesr = derf(arg);  
 | 
|---|
 | 568 |               addesr = (1.-addesr)*fac; // complementary error function: addesr = 1/2*erfc(arg)/|R_is1,ia1 - R_is2,ia2 - L|
 | 
|---|
 | 569 |                                       esr += addesr;
 | 
|---|
 | 570 |               addpre=exp(-arg*arg)*gkl;
 | 
|---|
 | 571 |               addpre = PP->fac1sqrtPI*PP->zval[is1]*PP->zval[is2]*addpre;  // addpre = exp(-|R_is1,ia1 - R_is2,ia2 - L|^2/(r_is1,gauss^2 + r_is2,gauss^2))/(sqrt(pi)*sqrt(r_is1,gauss^2 + r_is2,gauss^2))
 | 
|---|
 | 572 |               repand = (addesr+addpre)/erre2;
 | 
|---|
 | 573 | //              if ((fabs(repand) > MYEPSILON)) {
 | 
|---|
 | 574 | //                fprintf(stderr,"(%i) Ewald[is%d,ia%d/is%d,ia%d,(%d)]: Z1 %lg, Z2 %lg\tpre %lg\t esr %lg\t fac %lg\t arg %lg\tR3 (%lg,%lg,%lg)\n", P->Par.me,  is1, ia1, is2, ia2, ir2, PP->zval[is1], PP->zval[is2],addpre,addesr, fac, arg, R3[0], R3[1], R3[2]);
 | 
|---|
 | 575 | //              }
 | 
|---|
 | 576 |                                       for (i=0;i<NDIM;i++) {
 | 
|---|
 | 577 |                                                                 fxx=repand*R3[i];
 | 
|---|
 | 578 | //                if ((fabs(repand) > MYEPSILON)) {
 | 
|---|
 | 579 | //                                                                fprintf(stderr,"%i %i %i %i %i %g\n",is1+1,ia1+1,is2+1,ia2+1,i+1,fxx);
 | 
|---|
 | 580 | //                }
 | 
|---|
 | 581 |                                                                 I->FTemp[i+NDIM*(ia1)] += fxx*2.0;      // actio = reactio?
 | 
|---|
 | 582 |                                                                 //I->FTemp[i+NDIM*(ia2)] -= fxx;
 | 
|---|
 | 583 |                                       }
 | 
|---|
 | 584 |                                     }
 | 
|---|
 | 585 |                                   }
 | 
|---|
 | 586 |                                 }
 | 
|---|
| [a0bcf1] | 587 |       }
 | 
|---|
 | 588 |     }
 | 
|---|
| [c5bdb23] | 589 |     MPI_Allreduce (I->FTemp , I->I[is1].FEwald, NDIM*I->I[is1].Max_IonsOfType, MPI_DOUBLE, MPI_SUM, P->Par.comm);  
 | 
|---|
| [a0bcf1] | 590 |   }
 | 
|---|
 | 591 |   SpeedMeasure(P, EwaldTime, StopTimeDo);
 | 
|---|
| [c5bdb23] | 592 |   //for (is=0;is < I->Max_Types; is++) {
 | 
|---|
 | 593 |   //}
 | 
|---|
| [a0bcf1] | 594 |   MPI_Allreduce ( &esr, &L->E->AllTotalIonsEnergy[EwaldEnergy], 1, MPI_DOUBLE, MPI_SUM, P->Par.comm);
 | 
|---|
| [c5bdb23] | 595 | //  fprintf(stderr,"\n");
 | 
|---|
| [a0bcf1] | 596 | }
 | 
|---|
 | 597 | 
 | 
|---|
 | 598 | /** Sum up all forces acting on Ions.
 | 
|---|
| [69eca8] | 599 |  * IonType::FIon = IonType::FEwald  + IonType::FIonL + IonType::FIonNL + IonType::FMagnetic for all
 | 
|---|
| [a0bcf1] | 600 |  * dimensions #NDIM and each Ion of IonType
 | 
|---|
 | 601 |  * \param *P Problem at hand
 | 
|---|
 | 602 |  */
 | 
|---|
 | 603 | void CalculateIonForce(struct Problem *P)
 | 
|---|
 | 604 | {
 | 
|---|
 | 605 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 606 |   int i,j,d;
 | 
|---|
 | 607 |   for (i=0; i < I->Max_Types; i++) 
 | 
|---|
 | 608 |     for (j=0; j < I->I[i].Max_IonsOfType; j++)
 | 
|---|
 | 609 |       for (d=0; d<NDIM;d++)
 | 
|---|
| [69eca8] | 610 |                                 I->I[i].FIon[d+j*NDIM] = (I->I[i].FEwald[d+j*NDIM] + I->I[i].FIonL[d+j*NDIM] + I->I[i].FIonNL[d+j*NDIM] + I->I[i].FMagnetic[d+j*NDIM]);
 | 
|---|
| [a0bcf1] | 611 | }
 | 
|---|
 | 612 | 
 | 
|---|
 | 613 | /** Write Forces to FileData::ForcesFile.
 | 
|---|
 | 614 |  * goes through all Ions per IonType and each dimension of #NDIM and prints in one line:
 | 
|---|
 | 615 |  * Position IonType::R, total force Ion IonType::FIon, local force IonType::FIonL, 
 | 
|---|
 | 616 |  * non-local IonType::FIonNL, ewald force IonType::FEwald
 | 
|---|
 | 617 |  * \param *P Problem at hand
 | 
|---|
 | 618 |  */
 | 
|---|
 | 619 | void OutputIonForce(struct Problem *P)
 | 
|---|
 | 620 | {
 | 
|---|
 | 621 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 622 |   struct FileData *F = &P->Files;
 | 
|---|
 | 623 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 624 |   FILE *fout = NULL;
 | 
|---|
 | 625 |   int i,j;
 | 
|---|
 | 626 |   if (F->MeOutMes != 1) return;
 | 
|---|
 | 627 |   fout = F->ForcesFile;
 | 
|---|
 | 628 |   for (i=0; i < I->Max_Types; i++) 
 | 
|---|
 | 629 |     for (j=0; j < I->I[i].Max_IonsOfType; j++) 
 | 
|---|
| [8dd187] | 630 |       fprintf(fout, "%i\t%i\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\n", i,j, 
 | 
|---|
| [a0bcf1] | 631 |               I->I[i].R[0+j*NDIM], I->I[i].R[1+j*NDIM], I->I[i].R[2+j*NDIM],
 | 
|---|
 | 632 |               I->I[i].FIon[0+j*NDIM], I->I[i].FIon[1+j*NDIM], I->I[i].FIon[2+j*NDIM],
 | 
|---|
 | 633 |               I->I[i].FIonL[0+j*NDIM], I->I[i].FIonL[1+j*NDIM], I->I[i].FIonL[2+j*NDIM],
 | 
|---|
 | 634 |               I->I[i].FIonNL[0+j*NDIM], I->I[i].FIonNL[1+j*NDIM], I->I[i].FIonNL[2+j*NDIM],
 | 
|---|
| [8dd187] | 635 |         I->I[i].FMagnetic[0+j*NDIM], I->I[i].FMagnetic[1+j*NDIM], I->I[i].FMagnetic[2+j*NDIM],
 | 
|---|
| [a0bcf1] | 636 |               I->I[i].FEwald[0+j*NDIM], I->I[i].FEwald[1+j*NDIM], I->I[i].FEwald[2+j*NDIM]);
 | 
|---|
 | 637 |   fflush(fout);
 | 
|---|
 | 638 |   fprintf(fout, "MeanForce:\t%e\n", R->MeanForce[0]);
 | 
|---|
 | 639 | } 
 | 
|---|
 | 640 | 
 | 
|---|
| [b74e5e] | 641 | /** Reads Forces from CallOptions::ForcesFile.
 | 
|---|
 | 642 |  * goes through all Ions per IonType and each dimension of #NDIM and parses in one line:
 | 
|---|
 | 643 |  * Position IonType::R, total force Ion IonType::FIon, local force IonType::FIonL, 
 | 
|---|
 | 644 |  * non-local IonType::FIonNL, ewald force IonType::FEwald
 | 
|---|
 | 645 |  * \param *P Problem at hand
 | 
|---|
 | 646 |  */
 | 
|---|
 | 647 | void ParseIonForce(struct Problem *P)
 | 
|---|
 | 648 | {
 | 
|---|
 | 649 |         //struct RunStruct *Run = &P->R;
 | 
|---|
 | 650 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 651 |   FILE *finput = NULL;
 | 
|---|
 | 652 |         char line[1024];
 | 
|---|
 | 653 |   int i,j;
 | 
|---|
 | 654 |   double i1, j1;
 | 
|---|
 | 655 |   double R[NDIM];
 | 
|---|
 | 656 |   
 | 
|---|
 | 657 |   if (P->Call.ForcesFile == NULL) return;
 | 
|---|
 | 658 |   finput = fopen(P->Call.ForcesFile, "r");
 | 
|---|
 | 659 |         //fprintf(stderr, "File pointer says %p\n", finput);
 | 
|---|
 | 660 |         if (finput == NULL)
 | 
|---|
 | 661 |                 Error(InitReading, "ForcesFile does not exist.");
 | 
|---|
 | 662 |         fscanf(finput, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n", line,line,line,line,line,line,line,line,line,line,line,line,line,line,line,line,line,line,line,line);        // skip header line
 | 
|---|
 | 663 |   for (i=0; i < I->Max_Types; i++) 
 | 
|---|
 | 664 |     for (j=0; j < I->I[i].Max_IonsOfType; j++)
 | 
|---|
 | 665 |                         if (feof(finput)) {
 | 
|---|
 | 666 |                                 Error(InitReading, "ForcesFile does not contain enough lines.");
 | 
|---|
 | 667 |                         } else {
 | 
|---|
 | 668 |                                 //fscanf(finput, "%s\n", line);
 | 
|---|
 | 669 |                                 //if (strlen(line) < 100) {
 | 
|---|
 | 670 |                                         //fprintf(stderr, "i %d, j %d, length of line %ld, line %s.\n", i,j, strlen(line), line);
 | 
|---|
 | 671 |                                         //Error(InitReading, "ForcesFile does not contain enough lines or line is faulty.");
 | 
|---|
 | 672 |                                 //} else
 | 
|---|
 | 673 |                                         //fprintf(stderr, "Parsed line: '%s'\n", line);
 | 
|---|
 | 674 |                 fscanf(finput, "%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\t%le\n", &i1,&j1, 
 | 
|---|
 | 675 |                       &R[0], &R[1], &R[2],
 | 
|---|
 | 676 |                       &I->I[i].FIon[0+j*NDIM], &I->I[i].FIon[1+j*NDIM], &I->I[i].FIon[2+j*NDIM],
 | 
|---|
 | 677 |                     &I->I[i].FIonL[0+j*NDIM], &I->I[i].FIonL[1+j*NDIM], &I->I[i].FIonL[2+j*NDIM],
 | 
|---|
 | 678 |                   &I->I[i].FIonNL[0+j*NDIM], &I->I[i].FIonNL[1+j*NDIM], &I->I[i].FIonNL[2+j*NDIM],
 | 
|---|
 | 679 |                 &I->I[i].FMagnetic[0+j*NDIM], &I->I[i].FMagnetic[1+j*NDIM], &I->I[i].FMagnetic[2+j*NDIM],
 | 
|---|
 | 680 |                       &I->I[i].FEwald[0+j*NDIM], &I->I[i].FEwald[1+j*NDIM], &I->I[i].FEwald[2+j*NDIM]);
 | 
|---|
 | 681 |                                 if ((i != (int)i1) || (j != (int)j1))
 | 
|---|
 | 682 |                                         Error(InitReading, "Line does not match to desired ion.");
 | 
|---|
 | 683 |                 }
 | 
|---|
 | 684 |         fclose(finput);
 | 
|---|
 | 685 |   //fprintf(stderr, "MeanForce:\t%e\n", Run->MeanForce[0]);
 | 
|---|
 | 686 | };
 | 
|---|
 | 687 | 
 | 
|---|
| [a0bcf1] | 688 | /** Frees memory IonType.
 | 
|---|
 | 689 |  * All pointers from IonType and the pointer on it are free'd
 | 
|---|
 | 690 |  * \param *I Ions structure to be free'd
 | 
|---|
 | 691 |  * \sa IonsInitRead where memory is allocated
 | 
|---|
 | 692 |  */
 | 
|---|
 | 693 | void RemoveIonsRead(struct Ions *I)
 | 
|---|
 | 694 | {
 | 
|---|
 | 695 |   int i, it;
 | 
|---|
 | 696 |   for (i=0; i < I->Max_Types; i++) {
 | 
|---|
| [32de28] | 697 |     Free(I->I[i].Name, "RemoveIonsRead: I->I[i].Name");
 | 
|---|
 | 698 |     Free(I->I[i].Symbol, "RemoveIonsRead: I->I[i].Symbol"); 
 | 
|---|
| [a0bcf1] | 699 |     for (it=0;it<I->I[i].Max_IonsOfType;it++) {
 | 
|---|
| [32de28] | 700 |       Free(I->I[i].moment[it], "RemoveIonsRead: I->I[i].moment[it]");
 | 
|---|
 | 701 |       Free(I->I[i].sigma[it], "RemoveIonsRead: I->I[i].sigma[it]");
 | 
|---|
 | 702 |       Free(I->I[i].sigma_rezi[it], "RemoveIonsRead: I->I[i].sigma_rezi[it]");
 | 
|---|
 | 703 |       Free(I->I[i].sigma_PAS[it], "RemoveIonsRead: I->I[i].sigma_PAS[it]");
 | 
|---|
 | 704 |       Free(I->I[i].sigma_rezi_PAS[it], "RemoveIonsRead: I->I[i].sigma_rezi_PAS[it]");
 | 
|---|
 | 705 |       while (RemoveConstraintItem(&I->I[i], it)); // empty the constrained item list
 | 
|---|
| [a0bcf1] | 706 |     }
 | 
|---|
| [32de28] | 707 |     Free(I->I[i].sigma, "RemoveIonsRead: I->I[i].sigma");
 | 
|---|
 | 708 |     Free(I->I[i].sigma_rezi, "RemoveIonsRead: I->I[i].sigma_rezi");
 | 
|---|
 | 709 |     Free(I->I[i].sigma_PAS, "RemoveIonsRead: I->I[i].sigma_PAS");
 | 
|---|
 | 710 |     Free(I->I[i].sigma_rezi_PAS, "RemoveIonsRead: I->I[i].sigma_rezi_PAS");
 | 
|---|
 | 711 |     Free(I->I[i].R, "RemoveIonsRead: I->I[i].R");
 | 
|---|
 | 712 |     Free(I->I[i].R_old, "RemoveIonsRead: I->I[i].R_old");
 | 
|---|
 | 713 |     Free(I->I[i].R_old_old, "RemoveIonsRead: I->I[i].R_old_old");
 | 
|---|
 | 714 |     Free(I->I[i].Constraints, "RemoveIonsRead: I->I[i].Constraints");
 | 
|---|
 | 715 |     Free(I->I[i].FIon, "RemoveIonsRead: I->I[i].FIon");
 | 
|---|
 | 716 |     Free(I->I[i].FIon_old, "RemoveIonsRead: I->I[i].FIon_old");
 | 
|---|
 | 717 |     Free(I->I[i].SearchDir, "RemoveIonsRead: I->I[i].SearchDir");
 | 
|---|
 | 718 |     Free(I->I[i].GammaA, "RemoveIonsRead: I->I[i].GammaA");
 | 
|---|
 | 719 |     Free(I->I[i].FIonL, "RemoveIonsRead: I->I[i].FIonL");
 | 
|---|
 | 720 |     Free(I->I[i].FIonNL, "RemoveIonsRead: I->I[i].FIonNL");
 | 
|---|
 | 721 |     Free(I->I[i].FMagnetic, "RemoveIonsRead: I->I[i].FMagnetic");
 | 
|---|
 | 722 |     Free(I->I[i].U, "RemoveIonsRead: I->I[i].U");
 | 
|---|
 | 723 |     Free(I->I[i].SFactor, "RemoveIonsRead: I->I[i].SFactor");
 | 
|---|
 | 724 |     Free(I->I[i].IMT, "RemoveIonsRead: I->I[i].IMT");
 | 
|---|
 | 725 |     Free(I->I[i].FEwald, "RemoveIonsRead: I->I[i].FEwald");
 | 
|---|
 | 726 |     Free(I->I[i].alpha, "RemoveIonsRead: I->I[i].alpha");
 | 
|---|
| [a0bcf1] | 727 |   }
 | 
|---|
 | 728 |   if (I->R_cut == 0.0)
 | 
|---|
| [32de28] | 729 |     Free(I->RLatticeVec, "RemoveIonsRead: I->RLatticeVec");
 | 
|---|
 | 730 |   Free(I->FTemp, "RemoveIonsRead: I->FTemp");
 | 
|---|
 | 731 |   Free(I->I, "RemoveIonsRead: I->I");
 | 
|---|
| [a0bcf1] | 732 | }
 | 
|---|
 | 733 | 
 | 
|---|
 | 734 | /** Shifts center of gravity of ion forces IonType::FIon.
 | 
|---|
| [9a2c8c] | 735 |  * First sums up all forces of movable ions for net center of gravity force,
 | 
|---|
 | 736 |  * then reduces each force by this temp over Ions#Max_TotalIons, so that all in all
 | 
|---|
| [a0bcf1] | 737 |  * the net force is 0.
 | 
|---|
 | 738 |  * \param *P Problem at hand
 | 
|---|
| [9a2c8c] | 739 |  * \sa CorrectVelocity()
 | 
|---|
| [a0bcf1] | 740 |  */
 | 
|---|
 | 741 | void CorrectForces(struct Problem *P)
 | 
|---|
 | 742 | {
 | 
|---|
 | 743 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 744 |   double *FIon;
 | 
|---|
 | 745 |   double FTemp[NDIM];
 | 
|---|
| [9a2c8c] | 746 |   int is, ia, d, NumIons = 0;
 | 
|---|
| [a0bcf1] | 747 |   for (d=0; d<NDIM; d++)
 | 
|---|
| [9a2c8c] | 748 |     FTemp[d] = 0.;
 | 
|---|
| [a0bcf1] | 749 |   for (is=0; is < I->Max_Types; is++) {         // calculate force temperature for each type ...
 | 
|---|
 | 750 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {    // .. and each ion of this type ...
 | 
|---|
 | 751 |       FIon = &I->I[is].FIon[NDIM*ia];
 | 
|---|
| [9a2c8c] | 752 |       if (I->I[is].IMT[ia] == MoveIon) {                // .. if it's influenced
 | 
|---|
 | 753 |         NumIons++;
 | 
|---|
| [a0bcf1] | 754 |                                 for (d=0; d<NDIM; d++) 
 | 
|---|
 | 755 |                                   FTemp[d] += FIon[d];
 | 
|---|
 | 756 |       }
 | 
|---|
 | 757 |     }
 | 
|---|
 | 758 |   }
 | 
|---|
| [9a2c8c] | 759 |   //if (P->Files.MeOutMes != 1) return;
 | 
|---|
 | 760 |   //  fprintf(stderr, "TotalForce before: %e\t %e\t %e\n", FTemp[0], FTemp[1], FTemp[2]);
 | 
|---|
| [a0bcf1] | 761 |   for (is=0; is < I->Max_Types; is++) {         // and then reduce each by this value
 | 
|---|
 | 762 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
 | 763 |       FIon = &I->I[is].FIon[NDIM*ia];
 | 
|---|
 | 764 |       if (I->I[is].IMT[ia] == MoveIon) {
 | 
|---|
 | 765 |                                 for (d=0; d<NDIM; d++) 
 | 
|---|
| [9a2c8c] | 766 |                                  FIon[d] -= FTemp[d]/NumIons;
 | 
|---|
| [a0bcf1] | 767 |       }
 | 
|---|
 | 768 |     }
 | 
|---|
 | 769 |   }
 | 
|---|
| [9a2c8c] | 770 | /*  for (d=0; d<NDIM; d++)
 | 
|---|
 | 771 |     FTemp[d] = 0.;
 | 
|---|
 | 772 |   for (is=0; is < I->Max_Types; is++) {         // calculate force temperature for each type ...
 | 
|---|
 | 773 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {    // .. and each ion of this type ...
 | 
|---|
 | 774 |       FIon = &I->I[is].FIon[NDIM*ia];
 | 
|---|
 | 775 |       if (I->I[is].IMT[ia] == MoveIon) {                // .. if it's influenced
 | 
|---|
 | 776 |                                 for (d=0; d<NDIM; d++) 
 | 
|---|
 | 777 |                                   FTemp[d] += FIon[d];
 | 
|---|
 | 778 |       }
 | 
|---|
 | 779 |     }
 | 
|---|
 | 780 |   }
 | 
|---|
 | 781 |   if (P->Files.MeOutMes != 1) return;
 | 
|---|
 | 782 |     fprintf(stderr, "TotalForce after: %e\t %e\t %e\n", FTemp[0], FTemp[1], FTemp[2]);
 | 
|---|
 | 783 |     */
 | 
|---|
| [a0bcf1] | 784 | }
 | 
|---|
 | 785 | 
 | 
|---|
 | 786 | 
 | 
|---|
 | 787 | /** Shifts center of gravity of ion velocities (rather momentums).
 | 
|---|
 | 788 |  * First sums up ion speed U times their IonMass (summed up for each
 | 
|---|
| [4782e78] | 789 |  * dimension) in temp, then reduces the velocity by temp per Ions::TotalMass (so here
 | 
|---|
| [a0bcf1] | 790 |  * total number of Ions is included)
 | 
|---|
 | 791 |  * \param *P Problem at hand
 | 
|---|
| [4782e78] | 792 |  * \sa CorrectForces()
 | 
|---|
| [a0bcf1] | 793 |  */
 | 
|---|
 | 794 | void CorrectVelocity(struct Problem *P)
 | 
|---|
 | 795 | {
 | 
|---|
 | 796 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 797 |   double *U;
 | 
|---|
 | 798 |   double UTemp[NDIM];
 | 
|---|
 | 799 |   int is, ia, d;
 | 
|---|
 | 800 |   for (d=0; d<NDIM; d++)
 | 
|---|
 | 801 |     UTemp[d] = 0;
 | 
|---|
 | 802 |   for (is=0; is < I->Max_Types; is++) {         // all types ...
 | 
|---|
 | 803 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {    // ... all ions per type ...
 | 
|---|
 | 804 |       U = &I->I[is].U[NDIM*ia];
 | 
|---|
| [4782e78] | 805 |       //if (I->I[is].IMT[ia] == MoveIon) {      // ... even FixedIon moves, only not by other's forces
 | 
|---|
| [a0bcf1] | 806 |                                 for (d=0; d<NDIM; d++) 
 | 
|---|
 | 807 |                                   UTemp[d] += I->I[is].IonMass*U[d];
 | 
|---|
| [4782e78] | 808 |       //}
 | 
|---|
| [a0bcf1] | 809 |     }
 | 
|---|
 | 810 |   }
 | 
|---|
 | 811 |   for (is=0; is < I->Max_Types; is++) {
 | 
|---|
 | 812 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
 | 813 |       U = &I->I[is].U[NDIM*ia];
 | 
|---|
| [4782e78] | 814 |       //if (I->I[is].IMT[ia] == MoveIon) {
 | 
|---|
| [a0bcf1] | 815 |                                 for (d=0; d<NDIM; d++) 
 | 
|---|
 | 816 |                                   U[d] -= UTemp[d]/I->TotalMass;                // shift by mean velocity over mass and number of ions
 | 
|---|
| [4782e78] | 817 |       //}
 | 
|---|
| [a0bcf1] | 818 |     }
 | 
|---|
 | 819 |   }
 | 
|---|
 | 820 | }
 | 
|---|
 | 821 | 
 | 
|---|
 | 822 | /** Moves ions according to calculated force.
 | 
|---|
 | 823 |  * Goes through each type of IonType and each ion therein, takes mass and
 | 
|---|
 | 824 |  * Newton to move each ion to new coordinates IonType::R, while remembering the last
 | 
|---|
 | 825 |  * two coordinates and the last force of the ion. Coordinates R are being
 | 
|---|
 | 826 |  * transformed to inverted base, shifted by +-1.0 and back-transformed to
 | 
|---|
 | 827 |  * real base.
 | 
|---|
 | 828 |  * \param *P Problem at hand
 | 
|---|
 | 829 |  * \sa CalculateIonForce
 | 
|---|
 | 830 |  * \sa UpdateIonsU
 | 
|---|
 | 831 |  * \warning U is not changed here, only used to move the ion.
 | 
|---|
 | 832 |  */
 | 
|---|
 | 833 | void UpdateIonsR(struct Problem *P)
 | 
|---|
 | 834 | {
 | 
|---|
 | 835 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 836 |   int is, ia, d;
 | 
|---|
 | 837 |   double *R, *R_old, *R_old_old, *FIon, *FIon_old, *U, *FIonL, *FIonNL, *FEwald;
 | 
|---|
 | 838 |   double IonMass, a;
 | 
|---|
 | 839 |   double sR[NDIM], sRold[NDIM], sRoldold[NDIM];
 | 
|---|
 | 840 |   const int delta_t = P->R.delta_t;
 | 
|---|
 | 841 |   for (is=0; is < I->Max_Types; is++) { // go through all types ...
 | 
|---|
 | 842 |     IonMass = I->I[is].IonMass;
 | 
|---|
 | 843 |     if (IonMass < MYEPSILON) fprintf(stderr,"UpdateIonsR: IonMass = %lg",IonMass);
 | 
|---|
 | 844 |     a = delta_t*0.5/IonMass;            // F/m = a and thus: s = 0.5 * F/m * t^2 + v * t =: t * (F * a + v)
 | 
|---|
 | 845 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) { // .. and each ion of the type
 | 
|---|
 | 846 |       FIon = &I->I[is].FIon[NDIM*ia];
 | 
|---|
 | 847 |       FIonL = &I->I[is].FIonL[NDIM*ia];
 | 
|---|
 | 848 |       FIonNL = &I->I[is].FIonNL[NDIM*ia];
 | 
|---|
 | 849 |       FEwald = &I->I[is].FEwald[NDIM*ia];
 | 
|---|
 | 850 |       FIon_old = &I->I[is].FIon_old[NDIM*ia];
 | 
|---|
 | 851 |       U = &I->I[is].U[NDIM*ia];
 | 
|---|
 | 852 |       R = &I->I[is].R[NDIM*ia];
 | 
|---|
 | 853 |       R_old = &I->I[is].R_old[NDIM*ia];
 | 
|---|
 | 854 |       R_old_old = &I->I[is].R_old_old[NDIM*ia];
 | 
|---|
| [6590194] | 855 |       //if (I->I[is].IMT[ia] == MoveIon) { // even FixedIon moves, only not by other's forces
 | 
|---|
| [a0bcf1] | 856 |                                 for (d=0; d<NDIM; d++) {
 | 
|---|
 | 857 |                                   R_old_old[d] = R_old[d];                              // shift old values
 | 
|---|
 | 858 |                                   R_old[d] = R[d];
 | 
|---|
| [6590194] | 859 |                             R[d] += delta_t*(U[d]+a*FIon[d]);                   // F = m * a and s = 0.5 * a * t^2
 | 
|---|
| [a0bcf1] | 860 |                                   FIon_old[d] = FIon[d];                                        // store old force
 | 
|---|
| [6590194] | 861 | //                                FIon[d] = 0.;                                                                         // zero all as a sign that's been moved
 | 
|---|
 | 862 | //                                FIonL[d] = 0.;
 | 
|---|
 | 863 | //                                FIonNL[d] = 0.;
 | 
|---|
 | 864 | //                                FEwald[d] = 0.;
 | 
|---|
 | 865 | // don't reset forces here anymore, as we OutputVis() after this and before next CalculateForce() (rendering them null in the cute graphs)
 | 
|---|
| [a0bcf1] | 866 |                                 }
 | 
|---|
| [6590194] | 867 |         if (I->I[is].Constraints[ia] != NULL) { // override current resulting R if constrained is given
 | 
|---|
 | 868 |           fprintf(stderr, "(%i) Using constrained coordinates R of step %d on ion (%i,%i)\n", P->Par.me, I->I[is].Constraints[ia]->step, is, ia);
 | 
|---|
 | 869 |           if ((I->I[is].Constraints[ia]->step != P->R.OuterStep) && (P->Par.me == 0))
 | 
|---|
 | 870 |             fprintf(stderr, "(%i) WARNING: constraint step %d does not match Outerstep %d for ion (%d,%d)\n", P->Par.me, I->I[is].Constraints[ia]->step, P->R.OuterStep, is, ia);
 | 
|---|
 | 871 |           for (d=0; d<NDIM; d++)
 | 
|---|
 | 872 |             R[d] = I->I[is].Constraints[ia]->R[d];
 | 
|---|
 | 873 |           I->I[is].IMT[ia] = I->I[is].Constraints[ia]->IMT;
 | 
|---|
 | 874 |           //RemoveConstraintItem(&I->I[is],ia); // and remove this first item from the list: // is done now  at UpdateIonsU()
 | 
|---|
 | 875 |         }
 | 
|---|
| [a0bcf1] | 876 |                                 RMat33Vec3(sR, P->Lat.InvBasis, R);
 | 
|---|
 | 877 |                                 RMat33Vec3(sRold, P->Lat.InvBasis, R_old);
 | 
|---|
 | 878 |                                 RMat33Vec3(sRoldold, P->Lat.InvBasis, R_old_old);
 | 
|---|
 | 879 |                                 for (d=0; d <NDIM; d++) {
 | 
|---|
 | 880 |                                   while (sR[d] < 0) {
 | 
|---|
 | 881 |                                     sR[d] += 1.0;
 | 
|---|
 | 882 |                                     sRold[d] += 1.0;
 | 
|---|
 | 883 |                                     sRoldold[d] += 1.0;
 | 
|---|
 | 884 |                                   }
 | 
|---|
 | 885 |                                   while (sR[d] >= 1.0) {
 | 
|---|
 | 886 |                                     sR[d] -= 1.0;
 | 
|---|
 | 887 |                                     sRold[d] -= 1.0;
 | 
|---|
 | 888 |                                     sRoldold[d] -= 1.0;
 | 
|---|
 | 889 |                                   }
 | 
|---|
 | 890 |                                 }
 | 
|---|
 | 891 |                                 RMat33Vec3(R, P->Lat.RealBasis, sR);
 | 
|---|
 | 892 |                                 RMat33Vec3(R_old, P->Lat.RealBasis, sRold);
 | 
|---|
 | 893 |                                 RMat33Vec3(R_old_old, P->Lat.RealBasis, sRoldold);
 | 
|---|
| [6590194] | 894 |       //}
 | 
|---|
| [a0bcf1] | 895 |     }
 | 
|---|
 | 896 |   }
 | 
|---|
 | 897 | }
 | 
|---|
 | 898 | 
 | 
|---|
| [13d7f6] | 899 | /** Resets the forces array.
 | 
|---|
 | 900 |  * \param *P Problem at hand
 | 
|---|
 | 901 |  */
 | 
|---|
 | 902 | void ResetForces(struct Problem *P)
 | 
|---|
 | 903 | {
 | 
|---|
 | 904 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 905 |   double *FIon, *FIonL, *FIonNL, *FEwald;
 | 
|---|
 | 906 |   int is, ia, d;
 | 
|---|
 | 907 |   for (is=0; is < I->Max_Types; is++) { // go through all types ...
 | 
|---|
 | 908 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) { // .. and each ion of the type
 | 
|---|
 | 909 |       FIon = &I->I[is].FIon[NDIM*ia];
 | 
|---|
 | 910 |       FIonL = &I->I[is].FIonL[NDIM*ia];
 | 
|---|
 | 911 |       FIonNL = &I->I[is].FIonNL[NDIM*ia];
 | 
|---|
 | 912 |       FEwald = &I->I[is].FEwald[NDIM*ia];
 | 
|---|
 | 913 |       for (d=0; d<NDIM; d++) {
 | 
|---|
 | 914 |         FIon[d] = 0.;                   // zero all as a sign that's been moved
 | 
|---|
 | 915 |         FIonL[d] = 0.;
 | 
|---|
 | 916 |         FIonNL[d] = 0.;
 | 
|---|
 | 917 |         FEwald[d] = 0.;
 | 
|---|
 | 918 |       }
 | 
|---|
 | 919 |     }
 | 
|---|
 | 920 |   }
 | 
|---|
 | 921 | };
 | 
|---|
 | 922 | 
 | 
|---|
| [a0bcf1] | 923 | /** Changes ion's velocity according to acting force.
 | 
|---|
 | 924 |  * IonType::U is changed by the weighted force of actual step and last one
 | 
|---|
 | 925 |  * according to Newton.
 | 
|---|
 | 926 |  * \param *P Problem at hand
 | 
|---|
 | 927 |  * \sa UpdateIonsR
 | 
|---|
 | 928 |  * \sa CalculateIonForce
 | 
|---|
 | 929 |  * \warning R is not changed here.
 | 
|---|
 | 930 |  */
 | 
|---|
 | 931 | void UpdateIonsU(struct Problem *P)
 | 
|---|
 | 932 | {
 | 
|---|
 | 933 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 934 |   int is, ia, d;
 | 
|---|
 | 935 |   double *FIon, *FIon_old, *U;
 | 
|---|
 | 936 |   double IonMass, a;
 | 
|---|
 | 937 |   const int delta_t = P->R.delta_t;
 | 
|---|
 | 938 |   for (is=0; is < I->Max_Types; is++) {
 | 
|---|
 | 939 |     IonMass = I->I[is].IonMass;
 | 
|---|
 | 940 |     if (IonMass < MYEPSILON) fprintf(stderr,"UpdateIonsU: IonMass = %lg",IonMass);
 | 
|---|
 | 941 |     a = delta_t*0.5/IonMass;                            // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a
 | 
|---|
 | 942 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
 | 943 |       U = &I->I[is].U[NDIM*ia];
 | 
|---|
| [05fec0] | 944 |       if (I->I[is].Constraints[ia] != NULL) { // override current resulting R and U if constrained is given
 | 
|---|
 | 945 |         fprintf(stderr, "(%i) Setting constrained motion U at step %d on ion (%i,%i)\n", P->Par.me, I->I[is].Constraints[ia]->step, is, ia);
 | 
|---|
 | 946 |         if ((I->I[is].Constraints[ia]->step != P->R.OuterStep) && (P->Par.me == 0))
 | 
|---|
 | 947 |           fprintf(stderr, "(%i) WARNING: constraint step %d does not match Outerstep %d for ion (%d,%d)\n", P->Par.me, I->I[is].Constraints[ia]->step, P->R.OuterStep, is, ia);
 | 
|---|
 | 948 |         for (d=0; d<NDIM; d++)
 | 
|---|
 | 949 |           U[d] = I->I[is].Constraints[ia]->U[d];
 | 
|---|
 | 950 |         RemoveConstraintItem(&I->I[is],ia); // and remove this first item from the list
 | 
|---|
 | 951 |       } else {
 | 
|---|
 | 952 |         FIon = &I->I[is].FIon[NDIM*ia];
 | 
|---|
 | 953 |         FIon_old = &I->I[is].FIon_old[NDIM*ia];
 | 
|---|
 | 954 |         //if (I->I[is].IMT[ia] == MoveIon)
 | 
|---|
 | 955 |                         for (d=0; d<NDIM; d++) {
 | 
|---|
 | 956 |                                 U[d] += a * (FIon[d]+FIon_old[d]);
 | 
|---|
 | 957 |                         }
 | 
|---|
 | 958 |       }
 | 
|---|
| [a0bcf1] | 959 |     }
 | 
|---|
 | 960 |   }
 | 
|---|
 | 961 | }
 | 
|---|
 | 962 | 
 | 
|---|
 | 963 | /** CG process to optimise structure.
 | 
|---|
 | 964 |  * \param *P Problem at hand
 | 
|---|
 | 965 |  */
 | 
|---|
 | 966 | void UpdateIons(struct Problem *P)
 | 
|---|
 | 967 | {
 | 
|---|
 | 968 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 969 |   int is, ia, d;
 | 
|---|
 | 970 |   double *R, *R_old, *R_old_old, *FIon, *S, *GammaA;
 | 
|---|
 | 971 |   double IonFac, GammaB; //, GammaT;
 | 
|---|
 | 972 |   double FNorm, StepNorm;
 | 
|---|
 | 973 |   for (is=0; is < I->Max_Types; is++) {
 | 
|---|
 | 974 |     IonFac = I->I[is].IonFac;
 | 
|---|
 | 975 |     GammaA = I->I[is].GammaA;
 | 
|---|
 | 976 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
 | 977 |       FIon = &I->I[is].FIon[NDIM*ia];
 | 
|---|
 | 978 |       S = &I->I[is].SearchDir[NDIM*ia];
 | 
|---|
 | 979 |       GammaB = GammaA[ia];
 | 
|---|
 | 980 |       GammaA[ia] = RSP3(FIon,S);
 | 
|---|
 | 981 |       FNorm = sqrt(RSP3(FIon,FIon));
 | 
|---|
 | 982 |       StepNorm = log(1.+IonFac*FNorm); // Fix Hack
 | 
|---|
 | 983 |       if (FNorm != 0)
 | 
|---|
 | 984 |         StepNorm /= sqrt(RSP3(FIon,FIon));
 | 
|---|
 | 985 |       else
 | 
|---|
 | 986 |         StepNorm = 0;
 | 
|---|
 | 987 |       //if (GammaB != 0.0) {
 | 
|---|
 | 988 |       //        GammaT = GammaA[ia]/GammaB;
 | 
|---|
 | 989 |       //        for (d=0; d>NDIM; d++)
 | 
|---|
 | 990 |       //          S[d] = FIon[d]+GammaT*S[d];
 | 
|---|
 | 991 |       //      } else {
 | 
|---|
 | 992 |         for (d=0; d<NDIM; d++)
 | 
|---|
 | 993 |           S[d] = StepNorm*FIon[d];
 | 
|---|
 | 994 |         //      }
 | 
|---|
 | 995 |       R = &I->I[is].R[NDIM*ia];
 | 
|---|
 | 996 |       R_old = &I->I[is].R_old[NDIM*ia];
 | 
|---|
 | 997 |       R_old_old = &I->I[is].R_old_old[NDIM*ia];
 | 
|---|
 | 998 |       if (I->I[is].IMT[ia] == MoveIon)
 | 
|---|
 | 999 |         for (d=0; d<NDIM; d++) {
 | 
|---|
 | 1000 |           R_old_old[d] = R_old[d];
 | 
|---|
 | 1001 |           R_old[d] = R[d];
 | 
|---|
 | 1002 |           R[d] += S[d]; // FixHack*IonFac;
 | 
|---|
 | 1003 |         }
 | 
|---|
 | 1004 |     }
 | 
|---|
 | 1005 |   }
 | 
|---|
 | 1006 | }
 | 
|---|
 | 1007 | 
 | 
|---|
 | 1008 | /** Print coordinates of all ions to stdout.
 | 
|---|
 | 1009 |  * \param *P Problem at hand
 | 
|---|
| [774ae8] | 1010 |  * \param actual (1 - don't at current RunStruct#OuterStep, 0 - do)
 | 
|---|
| [a0bcf1] | 1011 |  */
 | 
|---|
| [774ae8] | 1012 | void OutputIonCoordinates(struct Problem *P, int actual)
 | 
|---|
| [a0bcf1] | 1013 | {
 | 
|---|
| [774ae8] | 1014 |   //struct RunStruct *R = &P->R;
 | 
|---|
| [a0bcf1] | 1015 |   struct Ions *I = &P->Ion;
 | 
|---|
| [c510a7] | 1016 |   char filename[MAXSTRINGSIZE];
 | 
|---|
| [774ae8] | 1017 |   FILE *output;
 | 
|---|
 | 1018 |   int is, ia, nr = 0;
 | 
|---|
 | 1019 |   double Bohr = (I->IsAngstroem) ? 1./ANGSTROEMINBOHRRADIUS : 1.;
 | 
|---|
 | 1020 | /*  if (P->Par.me == 0 && P->Call.out[ReadOut]) { 
 | 
|---|
 | 1021 |     fprintf(stderr, "(%i) ======= Differential Ion Coordinates =========\n",P->Par.me);
 | 
|---|
| [a0bcf1] | 1022 |     for (is=0; is < I->Max_Types; is++)
 | 
|---|
 | 1023 |       for (ia=0; ia < I->I[is].Max_IonsOfType; ia++)
 | 
|---|
 | 1024 |         //fprintf(stderr, "(%i) R[%i/%i][%i/%i] = (%e,%e,%e)\n", P->Par.me, is, I->Max_Types, ia, I->I[is].Max_IonsOfType, I->I[is].R[NDIM*ia+0],I->I[is].R[NDIM*ia+1],I->I[is].R[NDIM*ia+2]);  
 | 
|---|
| [774ae8] | 1025 |         fprintf(stderr, "Ion_Type%i_%i\t%.6f\t%.6f\t%.6f\t0\t# Atom from StructOpt\n", is+1, ia+1, I->I[is].R[NDIM*ia+0]-I->I[is].R_old[NDIM*ia+0],I->I[is].R[NDIM*ia+1]-I->I[is].R_old[NDIM*ia+1],I->I[is].R[NDIM*ia+2]-I->I[is].R_old[NDIM*ia+2]);
 | 
|---|
| [a0bcf1] | 1026 |     fprintf(stderr, "(%i) =========================================\n",P->Par.me);
 | 
|---|
| [774ae8] | 1027 |   }*/
 | 
|---|
 | 1028 |   if (actual)
 | 
|---|
 | 1029 |     sprintf(filename, "%s.MD", P->Call.MainParameterFile); 
 | 
|---|
 | 1030 |   else
 | 
|---|
 | 1031 |     sprintf(filename, "%s.opt", P->Call.MainParameterFile);
 | 
|---|
 | 1032 |   if (((actual) && (P->R.OuterStep <= 0)) || ((!actual) && (P->R.StructOptStep == 1))) { // on first step write complete config file 
 | 
|---|
 | 1033 |     WriteParameters(P, filename);
 | 
|---|
 | 1034 |   } else { // afterwards simply add the current ion coordinates as constrained steps
 | 
|---|
 | 1035 |     if ((P->Par.me == 0) && (output = fopen(filename,"a"))) {
 | 
|---|
 | 1036 |       fprintf(output,"# ====== MD step %d ========= \n", (actual) ? P->R.OuterStep : P->R.StructOptStep);
 | 
|---|
 | 1037 |       for (is=0; is < I->Max_Types; is++)
 | 
|---|
 | 1038 |         for (ia=0;ia<I->I[is].Max_IonsOfType;ia++) {
 | 
|---|
 | 1039 |           fprintf(output,"Ion_Type%i_%i\t%2.9f\t%2.9f\t%2.9f\t%i\t%2.9f\t%2.9f\t%2.9f\t# Number in molecule %i\n", is+1, ia+1, I->I[is].R[0+NDIM*ia]*Bohr, I->I[is].R[1+NDIM*ia]*Bohr, I->I[is].R[2+NDIM*ia]*Bohr, I->I[is].IMT[ia], I->I[is].U[0+NDIM*ia]*Bohr, I->I[is].U[1+NDIM*ia]*Bohr, I->I[is].U[2+NDIM*ia]*Bohr, ++nr);
 | 
|---|
 | 1040 |         }
 | 
|---|
 | 1041 |       fflush(output);
 | 
|---|
 | 1042 |     }
 | 
|---|
| [a0bcf1] | 1043 |   }
 | 
|---|
 | 1044 | }
 | 
|---|
 | 1045 | 
 | 
|---|
 | 1046 | /** Calculates kinetic energy (Ions::EKin) of movable Ions.
 | 
|---|
 | 1047 |  * Does 0.5 / IonType::IonMass * IonTye::U^2 for each Ion, 
 | 
|---|
 | 1048 |  * also retrieves actual temperatur by 2/3 from just
 | 
|---|
 | 1049 |  * calculated Ions::EKin.
 | 
|---|
 | 1050 |  * \param *P Problem at hand
 | 
|---|
 | 1051 |  */
 | 
|---|
 | 1052 | void CalculateEnergyIonsU(struct Problem *P)
 | 
|---|
 | 1053 | {
 | 
|---|
 | 1054 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 1055 |   int is, ia, d;
 | 
|---|
 | 1056 |   double *U;
 | 
|---|
 | 1057 |   double IonMass, a, ekin = 0;
 | 
|---|
 | 1058 |   for (is=0; is < I->Max_Types; is++) {
 | 
|---|
 | 1059 |     IonMass = I->I[is].IonMass;
 | 
|---|
 | 1060 |     a = 0.5*IonMass;
 | 
|---|
 | 1061 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
 | 1062 |       U = &I->I[is].U[NDIM*ia];
 | 
|---|
| [3716b2] | 1063 |       //if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
 | 
|---|
| [a0bcf1] | 1064 |                                 for (d=0; d<NDIM; d++) {
 | 
|---|
 | 1065 |                                         ekin += a * U[d]*U[d];
 | 
|---|
 | 1066 |                                 }
 | 
|---|
 | 1067 |     }
 | 
|---|
 | 1068 |   }
 | 
|---|
 | 1069 |   I->EKin = ekin;
 | 
|---|
 | 1070 |   I->ActualTemp = (2./(3.*I->Max_TotalIons)*I->EKin);
 | 
|---|
 | 1071 | }
 | 
|---|
 | 1072 | 
 | 
|---|
 | 1073 | /**     Scales ion velocities to match temperature.
 | 
|---|
 | 1074 |  * In order to match Ions::ActualTemp with desired RunStruct::TargetTemp
 | 
|---|
 | 1075 |  * each velocity in each dimension (for all types, all ions) is scaled
 | 
|---|
 | 1076 |  * with the ratio of these two. Ions::EKin is recalculated.
 | 
|---|
 | 1077 |  * \param *P Problem at hand
 | 
|---|
 | 1078 |  */
 | 
|---|
 | 1079 | void ScaleTemp(struct Problem *P)
 | 
|---|
 | 1080 | {
 | 
|---|
 | 1081 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 1082 |   int is, ia, d;
 | 
|---|
 | 1083 |   double *U;
 | 
|---|
 | 1084 |   double IonMass, a, ekin = 0;
 | 
|---|
 | 1085 |   if (I->ActualTemp < MYEPSILON) fprintf(stderr,"ScaleTemp: I->ActualTemp = %lg",I->ActualTemp);
 | 
|---|
 | 1086 |   double ScaleTempFactor = sqrt(P->R.TargetTemp/I->ActualTemp);
 | 
|---|
 | 1087 |   for (is=0; is < I->Max_Types; is++) {
 | 
|---|
 | 1088 |     IonMass = I->I[is].IonMass;
 | 
|---|
 | 1089 |     a = 0.5*IonMass;
 | 
|---|
 | 1090 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
 | 1091 |       U = &I->I[is].U[NDIM*ia];
 | 
|---|
| [3716b2] | 1092 |       //if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
 | 
|---|
| [a0bcf1] | 1093 |                                 for (d=0; d<NDIM; d++) {
 | 
|---|
 | 1094 |                                   U[d] *= ScaleTempFactor;
 | 
|---|
 | 1095 |                                   ekin += a * U[d]*U[d];
 | 
|---|
 | 1096 |                                 }
 | 
|---|
 | 1097 |     }
 | 
|---|
 | 1098 |   }
 | 
|---|
 | 1099 |   I->EKin = ekin;
 | 
|---|
 | 1100 |   I->ActualTemp = (2./(3.*I->Max_TotalIons)*I->EKin);
 | 
|---|
 | 1101 | }
 | 
|---|
 | 1102 | 
 | 
|---|
 | 1103 | /** Calculates mean force vector as stop criteria in structure optimization.
 | 
|---|
 | 1104 |  * Calculates a mean force vector per ion as the usual euclidian norm over total
 | 
|---|
 | 1105 |  * number of ions and dimensions, being the sum of each ion force (for all type,
 | 
|---|
 | 1106 |  * all ions, all dims) squared.
 | 
|---|
 | 1107 |  * The mean force is archived in RunStruct::MeanForce and printed to screen.
 | 
|---|
 | 1108 |  * \param *P Problem at hand
 | 
|---|
 | 1109 |  */
 | 
|---|
 | 1110 | void GetOuterStop(struct Problem *P)
 | 
|---|
 | 1111 | {
 | 
|---|
 | 1112 |   struct RunStruct *R = &P->R;
 | 
|---|
 | 1113 |   struct Ions *I = &P->Ion;
 | 
|---|
 | 1114 |   int is, ia, IonNo=0, i, d;
 | 
|---|
 | 1115 |   double MeanForce = 0.0;
 | 
|---|
 | 1116 |   for (is=0; is < I->Max_Types; is++) 
 | 
|---|
 | 1117 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
 | 1118 |       IonNo++;
 | 
|---|
 | 1119 |       for (d=0; d <NDIM; d++)
 | 
|---|
 | 1120 |                                 MeanForce += I->I[is].FIon[d+NDIM*ia]*I->I[is].FIon[d+NDIM*ia];
 | 
|---|
 | 1121 |     }
 | 
|---|
 | 1122 |   for (i=MAXOLD-1; i > 0; i--) 
 | 
|---|
 | 1123 |     R->MeanForce[i] = R->MeanForce[i-1];
 | 
|---|
 | 1124 |   MeanForce = sqrt(MeanForce/(IonNo*NDIM));
 | 
|---|
 | 1125 |   R->MeanForce[0] = MeanForce;
 | 
|---|
 | 1126 |   if (P->Call.out[LeaderOut] && (P->Par.me == 0))
 | 
|---|
 | 1127 |     fprintf(stderr,"MeanForce = %e\n", R->MeanForce[0]);
 | 
|---|
 | 1128 | }
 | 
|---|
 | 1129 | 
 | 
|---|
 | 1130 | 
 | 
|---|