Changeset f915e1


Ignore:
Timestamp:
Apr 18, 2008, 1:30:19 PM (17 years ago)
Author:
Frederik Heber <heber@…>
Children:
995ff3
Parents:
719746
Message:

function Thermostats() added

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified pcp/src/run.c

    r719746 rf915e1  
    3333#include <gsl/gsl_math.h>
    3434#include <gsl/gsl_min.h>
     35#include <gsl/gsl_randist.h>
    3536#include "mpi.h"
    3637#include "data.h"
     
    11981199 * \param *params additional arguments, here Problem at hand
    11991200 */
    1200 double my_f(const gsl_vector *v, void *params)
     1201double StructOpt_f(const gsl_vector *v, void *params)
    12011202{
    12021203  struct Problem *P = (struct Problem *)params;
     
    12581259}
    12591260
    1260 void my_df(const gsl_vector *v, void *params, gsl_vector *df)
     1261void StructOpt_df(const gsl_vector *v, void *params, gsl_vector *df)
    12611262{
    12621263  struct Problem *P = (struct Problem *)params;
     
    12731274}
    12741275
    1275 void my_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *df)
     1276void StructOpt_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *df)
    12761277{
    1277   *f = my_f(x, params);
    1278   my_df(x, params, df);
     1278  *f = StructOpt_f(x, params);
     1279  StructOpt_df(x, params, df);
    12791280}
    12801281
     
    13121313
    13131314  /* Initialize method and iterate */
    1314   minex_func.f = &my_f;
    1315   minex_func.df = &my_df;
    1316   minex_func.fdf = &my_fdf;
     1315  minex_func.f = &StructOpt_f;
     1316  minex_func.df = &StructOpt_df;
     1317  minex_func.fdf = &StructOpt_fdf;
    13171318  minex_func.n = np;
    13181319  minex_func.params = (void *)P;
     
    13411342  gsl_vector_free(x);
    13421343  gsl_multimin_fdfminimizer_free (s);
     1344}
     1345
     1346/** Implementation of various thermostats.
     1347 * All these thermostats apply an additional force which has the following forms:
     1348 * -# Woodcock
     1349 *  \f$p_i \rightarrow \sqrt{\frac{T_0}{T}} \cdot p_i\f$
     1350 * -# Gaussian
     1351 *  \f$ \frac{ \sum_i \frac{p_i}{m_i} \frac{\partial V}{\partial q_i}} {\sum_i \frac{p^2_i}{m_i}} \cdot p_i\f$
     1352 * -# Langevin
     1353 *  \f$p_{i,n} \rightarrow \sqrt{1-\alpha^2} p_{i,0} + \alpha p_r\f$ 
     1354 * -# Berendsen
     1355 *  \f$p_i \rightarrow \left [ 1+ \frac{\delta t}{\tau_T} \left ( \frac{T_0}{T} \right ) \right ]^{\frac{1}{2}} \cdot p_i\f$
     1356 * -# Nose-Hoover
     1357 *  \f$\zeta p_i \f$ with \f$\frac{\partial \zeta}{\partial t} = \frac{1}{M_s} \left ( \sum^N_{i=1} \frac{p_i^2}{m_i} - g k_B T \right )\f$
     1358 * These Thermostats either simply rescale the velocities, thus Thermostats() should be called after UpdateIonsU(), and/or
     1359 * have a constraint force acting additionally on the ions. In the latter case, the ion speeds have to be modified
     1360 * belatedly and the constraint force set.
     1361 * \param *P Problem at hand
     1362 * \param i which of the thermostats to take: 0 - none, 1 - Woodcock, 2 - Gaussian, 3 - Langevin, 4 - Berendsen, 5 - Nose-Hoover
     1363 * \sa InitThermostat()
     1364 */
     1365void Thermostats(struct Problem *P, enum thermostats i)
     1366{
     1367  struct FileData *Files = &P->Files;
     1368  struct Ions *I = &P->Ion;
     1369  int is, ia, d;
     1370  double *U;
     1371  double a, ekin = 0.;
     1372  double E = 0., F = 0.;
     1373  double delta_alpha = 0.;
     1374  const int delta_t = P->R.delta_t;
     1375  double ScaleTempFactor;
     1376  double sigma;
     1377  gsl_rng * r;
     1378  const gsl_rng_type * T;
     1379 
     1380  // calculate current temperature
     1381  CalculateEnergyIonsU(P); // Temperature now in I->ActualTemp
     1382  ScaleTempFactor = P->R.TargetTemp/I->ActualTemp;
     1383  //if ((P->Par.me == 0) && (I->ActualTemp < MYEPSILON)) fprintf(stderr,"Thermostat: (1) I->ActualTemp = %lg",I->ActualTemp);
     1384  if (Files->MeOutMes) fprintf(Files->TemperatureFile, "%d\t%lg",P->R.OuterStep, I->ActualTemp);
     1385   
     1386  // differentating between the various thermostats
     1387  switch(i) {
     1388     case None:
     1389      debug(P, "Applying no thermostat...");
     1390      break;
     1391     case Woodcock:
     1392      if ((P->R.ScaleTempStep > 0) && ((P->R.OuterStep-1) % P->R.ScaleTempStep == 0)) {
     1393        debug(P, "Applying Woodcock thermostat...");
     1394        for (is=0; is < I->Max_Types; is++) {
     1395          a = 0.5*I->I[is].IonMass;
     1396          for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
     1397            U = &I->I[is].U[NDIM*ia];
     1398            if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
     1399              for (d=0; d<NDIM; d++) {
     1400                U[d] *= sqrt(ScaleTempFactor);
     1401                ekin += 0.5*I->I[is].IonMass * U[d]*U[d];
     1402              }
     1403          }
     1404        }
     1405      }
     1406      break;
     1407     case Gaussian:
     1408      debug(P, "Applying Gaussian thermostat...");
     1409      for (is=0; is < I->Max_Types; is++) { // sum up constraint constant
     1410        for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
     1411          U = &I->I[is].U[NDIM*ia];
     1412          if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
     1413            for (d=0; d<NDIM; d++) {
     1414              F += U[d] * I->I[is].FIon[d+NDIM*ia];
     1415              E += U[d]*U[d]*I->I[is].IonMass;
     1416            }
     1417        }
     1418      }
     1419      if (P->Call.out[ValueOut]) fprintf(stderr, "(%i) Gaussian Least Constraint constant is %lg\n", P->Par.me, F/E);
     1420      for (is=0; is < I->Max_Types; is++) { // apply constraint constant on constraint force and on velocities
     1421        for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
     1422          U = &I->I[is].U[NDIM*ia];
     1423          if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
     1424            for (d=0; d<NDIM; d++) {
     1425              I->I[is].FConstraint[d+NDIM*ia] = (F/E) * (U[d]*I->I[is].IonMass);
     1426              U[d] += delta_t/I->I[is].IonMass * (I->I[is].FConstraint[d+NDIM*ia]);
     1427              ekin += 0.5*I->I[is].IonMass * U[d]*U[d];
     1428            }
     1429        }
     1430      }
     1431      break;
     1432     case Langevin:
     1433      debug(P, "Applying Langevin thermostat...");
     1434      // init random number generator
     1435      gsl_rng_env_setup();
     1436      T = gsl_rng_default;
     1437      r = gsl_rng_alloc (T);
     1438      // Go through each ion
     1439      for (is=0; is < I->Max_Types; is++) {
     1440        sigma  = sqrt(P->R.TargetTemp/I->I[is].IonMass); // sigma = (k_b T)/m (Hartree/atomicmass = atomiclength/atomictime)
     1441        for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
     1442          U = &I->I[is].U[NDIM*ia];
     1443          // throw a dice to determine whether it gets hit by a heat bath particle
     1444          if (((((rand()/(double)RAND_MAX))*P->R.TempFrequency) < 1.)) {  // (I->I[is].IMT[ia] == MoveIon) &&  even FixedIon moves, only not by other's forces
     1445            if (P->Par.me == 0) fprintf(stderr,"(%i) Particle %i,%i was hit (sigma %lg): %lg -> ", P->Par.me, is, ia, sigma, sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]));
     1446            // pick three random numbers from a Boltzmann distribution around the desired temperature T for each momenta axis
     1447            for (d=0; d<NDIM; d++) {
     1448              U[d] = gsl_ran_gaussian (r, sigma);
     1449            }
     1450            if (P->Par.me == 0) fprintf(stderr,"%lg\n", sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]));
     1451          }
     1452          for (d=0; d<NDIM; d++)
     1453            ekin += 0.5*I->I[is].IonMass * U[d]*U[d];
     1454        }
     1455      }
     1456      break;
     1457     case Berendsen:
     1458      debug(P, "Applying Berendsen-VanGunsteren thermostat...");
     1459      for (is=0; is < I->Max_Types; is++) {
     1460        for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
     1461          U = &I->I[is].U[NDIM*ia];
     1462          if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
     1463            for (d=0; d<NDIM; d++) {
     1464              U[d] *= sqrt(1+(P->R.delta_t/P->R.TempFrequency)*(ScaleTempFactor-1));
     1465              ekin += 0.5*I->I[is].IonMass * U[d]*U[d];
     1466            }
     1467        }
     1468      }
     1469      break;
     1470     case NoseHoover:
     1471      debug(P, "Applying Nose-Hoover thermostat...");
     1472      // dynamically evolve alpha (the additional degree of freedom)
     1473      delta_alpha = 0.;
     1474      for (is=0; is < I->Max_Types; is++) { // sum up constraint constant
     1475        for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
     1476          U = &I->I[is].U[NDIM*ia];
     1477          if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
     1478            for (d=0; d<NDIM; d++) {
     1479              delta_alpha += U[d]*U[d]*I->I[is].IonMass;
     1480            }
     1481        }
     1482      }
     1483      delta_alpha = (delta_alpha - (3.*I->Max_TotalIons+1.) * P->R.TargetTemp)/(P->R.HooverMass*Units2Electronmass);
     1484      P->R.alpha += delta_alpha*delta_t;
     1485      if (P->Par.me == 0) fprintf(stderr,"(%i) alpha = %lg * %i = %lg\n", P->Par.me, delta_alpha, delta_t, P->R.alpha);
     1486      // apply updated alpha as additional force
     1487      for (is=0; is < I->Max_Types; is++) { // apply constraint constant on constraint force and on velocities
     1488        for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
     1489          U = &I->I[is].U[NDIM*ia];
     1490          if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
     1491            for (d=0; d<NDIM; d++) {
     1492              I->I[is].FConstraint[d+NDIM*ia] = - P->R.alpha * (U[d] * I->I[is].IonMass);
     1493              U[d] += delta_t/I->I[is].IonMass * (I->I[is].FConstraint[d+NDIM*ia]);
     1494              ekin += (0.5*I->I[is].IonMass) * U[d]*U[d];
     1495            }
     1496        }
     1497      }
     1498      break;
     1499  }   
     1500  I->EKin = ekin;
     1501  I->ActualTemp = (2./(3.*I->Max_TotalIons)*I->EKin);   
     1502  //if ((P->Par.me == 0) && (I->ActualTemp < MYEPSILON)) fprintf(stderr,"Thermostat: (2) I->ActualTemp = %lg",I->ActualTemp);
     1503  if (Files->MeOutMes) { fprintf(Files->TemperatureFile, "\t%lg\n", I->ActualTemp); fflush(Files->TemperatureFile); }
    13431504}
    13441505
Note: See TracChangeset for help on using the changeset viewer.