git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@6378 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp 2011-06-13 22:22:33 +00:00
parent abec044421
commit 7025ec968f
21 changed files with 6425 additions and 1 deletions

View File

@ -11,7 +11,9 @@ The libraries included in the LAMMPS distribution are the following:
atc atomistic-to-continuum methods
from Reese Jones, Jeremy Templeton, Jon Zimmerman (Sandia)
gpu graphical processor (GPU) routines, currently NVIDIA specific,
awpmd antisymmetrized wave packet molecular dynamics
from Ilya Valuev (JIHT RAS)
gpu graphical processor (GPU) routines, currently NVIDIA specific
from Mike Brown (Sandia)
poems POEMS rigid-body integration package
from RPI

View File

@ -0,0 +1,64 @@
SHELL = /bin/sh
# ------ FILES ------
SRC = \
ivutils/src/logexc.cpp \
systems/interact/TCP/wpmd.cpp \
systems/interact/TCP/wpmd_split.cpp
INC = \
cerf.h \
cerf2.h \
cerf_octave.h \
cvector_3.h \
lapack_inter.h \
logexc.h \
pairhash.h \
refobj.h \
tcpdefs.h \
vector_3.h \
wavepacket.h \
wpmd.h \
wpmd_split.h
# ------ DEFINITIONS ------
LIB = libawpmd.a
OBJ = $(SRC:.cpp=.o)
# ------ SETTINGS ------
# include any MPI settings needed for the ATC library to build with
# the same MPI library that LAMMPS is built with
CC = mpic++
CCFLAGS = -O -Isystems/interact/TCP/ -Isystems/interact -Iivutils/include
ARCHIVE = ar
ARCHFLAG = -rc
DEPFLAGS = -M
#LINK =
#LINKFLAGS =
USRLIB =
SYSLIB =
# ------ MAKE PROCEDURE ------
lib: $(OBJ)
$(ARCHIVE) $(ARFLAGS) $(LIB) $(OBJ)
# ------ COMPILE RULES ------
%.o:%.cpp
$(CC) $(CCFLAGS) -c $< -o $@
%.d:%.cpp
$(CC) $(CCFLAGS) $(DEPFLAGS) $< > $@
# ------ DEPENDENCIES ------
DEPENDS = $(OBJ:.o=.d)
# ------ CLEAN ------
clean:
rm *.d *~ $(OBJ) $(LIB)

29
lib/awpmd/README Normal file
View File

@ -0,0 +1,29 @@
AWPMD (Antisymmetrized Wave Packet Molecular Dynamics) library
Ilya Valuev, Igor Morozov, JIHT RAS
valuev at physik.hu-berlin.de
June 2011
--------------
This is version 0.9 of the AWPMD library taken from JIHT GridMD project.
It contains interface to calculate electronic and electron-ion Hamiltonian,
norm matrix and forces for AWPMD method.
This library must be built with a C++ compiler, before LAMMPS is
built, so LAMMPS can link against it.
Build the library using one of the provided Makefiles or creating your
own, specific to your compiler and system. For example:
make -f Makefile.openmpi++
If the build is successful, you should end up with a libawpmd.a file.
--------------
AWPMD is an open source program distributed under the terms
of wxWidgets Library License (see license directory for details).

View File

@ -0,0 +1,245 @@
# ifndef CERF_H
# define CERF_H
# include <complex>
# include <cmath>
/*
Copyright (C) 1998, 1999 John Smith
This file is part of Octave.
Or it might be one day....
Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// Put together by John Smith john at arrows dot demon dot co dot uk,
// using ideas by others.
//
// Calculate erf(z) for complex z.
// Three methods are implemented; which one is used depends on z.
//
// The code includes some hard coded constants that are intended to
// give about 14 decimal places of accuracy. This is appropriate for
// 64-bit floating point numbers.
//
// Oct 1999: Fixed a typo that in
// const Complex cerf_continued_fraction( const Complex z )
// that caused erroneous answers for erf(z) where real(z) negative
//
//#include <math.h>
//#include <octave/oct.h>
//#include "f77-fcn.h"
//
// Abramowitz and Stegun: (eqn: 7.1.14) gives this continued
// fraction for erfc(z)
//
// erfc(z) = sqrt(pi).exp(-z^2). 1 1/2 1 3/2 2 5/2
// --- --- --- --- --- --- ...
// z + z + z + z + z + z +
//
// This is evaluated using Lentz's method, as described in the narative
// of Numerical Recipes in C.
//
// The continued fraction is true providing real(z)>0. In practice we
// like real(z) to be significantly greater than 0, say greater than 0.5.
//
template< class Complex>
const Complex cerfc_continued_fraction( const Complex z )
{
double tiny = 1e-20 ; // a small number, large enough to calculate 1/tiny
double eps = 1e-15 ; // large enough so that 1.0+eps > 1.0, when using
// the floating point arithmetic
//
// first calculate z+ 1/2 1
// --- --- ...
// z + z +
Complex f(z) ;
Complex C(f) ;
Complex D(0.0) ;
Complex delta ;
double a ;
a = 0.0 ;
do
{
a = a + 0.5 ;
D = z + a*D ;
C = z + a/C ;
if (D.real() == 0.0 && D.imag() == 0.0)
D = tiny ;
D = 1.0 / D ;
delta = (C * D) ;
f = f * delta ;
} while (abs(1.0-delta) > eps ) ;
//
// Do the first term of the continued fraction
//
f = 1.0 / f ;
//
// and do the final scaling
//
f = f * exp(-z*z)/ sqrt(M_PI) ;
return f ;
}
template< class Complex>
const Complex cerf_continued_fraction( const Complex z )
{
// warning("cerf_continued_fraction:");
if (z.real() > 0)
return 1.0 - cerfc_continued_fraction( z ) ;
else
return -1.0 + cerfc_continued_fraction( -z ) ;
}
//
// Abramawitz and Stegun, Eqn. 7.1.5 gives a series for erf(z)
// good for all z, but converges faster for smallish abs(z), say abs(z)<2.
//
template< class Complex>
const Complex cerf_series( const Complex z )
{
double tiny = 1e-20 ; // a small number compared with 1.
// warning("cerf_series:");
Complex sum(0.0) ;
Complex term(z) ;
Complex z2(z*z) ;
for (int n=0; n<3 || abs(term) > abs(sum)*tiny; n++)
{
sum = sum + term / (2*n+1) ;
term = -term * z2 / (n+1) ;
}
return sum * 2.0 / sqrt(M_PI) ;
}
//
// Numerical Recipes quotes a formula due to Rybicki for evaluating
// Dawson's Integral:
//
// exp(-x^2) integral exp(t^2).dt = 1/sqrt(pi) lim sum exp(-(z-n.h)^2) / n
// 0 to x h->0 n odd
//
// This can be adapted to erf(z).
//
template< class Complex>
const Complex cerf_rybicki( const Complex z )
{
// warning("cerf_rybicki:");
double h = 0.2 ; // numerical experiment suggests this is small enough
//
// choose an even n0, and then shift z->z-n0.h and n->n-h.
// n0 is chosen so that real((z-n0.h)^2) is as small as possible.
//
int n0 = 2*(int) (floor( z.imag()/(2*h) + 0.5 )) ;
Complex z0( 0.0, n0*h ) ;
Complex zp(z-z0) ;
Complex sum(0.0,0.0) ;
//
// limits of sum chosen so that the end sums of the sum are
// fairly small. In this case exp(-(35.h)^2)=5e-22
//
//
for (int np=-35; np<=35; np+=2)
{
Complex t( zp.real(), zp.imag()-np*h) ;
Complex b( exp(t*t) / (np+n0) ) ;
sum += b ;
}
sum = sum * 2 * exp(-z*z) / M_PI ;
return Complex(-sum.imag(), sum.real()) ;
}
template< class Complex>
const Complex cerf( const Complex z )
{
//
// Use the method appropriate to size of z -
// there probably ought to be an extra option for NaN z, or infinite z
//
//
if (abs(z) < 2.0)
return cerf_series( z ) ;
else if (abs(z.real()) < 0.5)
return cerf_rybicki( z ) ;
else
return cerf_continued_fraction( z ) ;
}
//
// Footnote:
//
// Using the definitions from Abramowitz and Stegun (7.3.1, 7.3.2)
// The fresnel intgerals defined as:
//
// / t=x
// C(x) = | cos(pi/2 t^2) dt
// /
// t=0
//
// and
// / t=x
// S(x) = | sin(pi/2 t^2) dt
// /
// t=0
//
// These can be derived from erf(x) using 7.3.22
//
// C(z) +iS(z) = (1+i) erf( sqrt(pi)/2 (1-i) z )
// -----
// 2
//
// --------------------------------------------------------------------------
// Some test examples -
// comparative data taken from Abramowitz and Stegun table 7.9.
// Table 7.9 tabulates w(z), where w(z) = exp(-z*z) erfc(iz)
// I have copied twelve values of w(z) from the table, and separately
// calculated them using this code. The results are identical.
//
// x y Abramowitz & Stegun | Octave Calculations
// w(x+iy) | w(x+iy) cerf ( i.(x+iy))
// 0.2 0.2 0.783538+0.157403i | 0.783538 +0.157403 0.23154672 -0.219516
// 0.2 0.7 0.515991+0.077275i | 0.515991 +0.077275 0.69741968 -0.138277
// 0.2 1.7 0.289309+0.027154i | 0.289309 +0.027154 0.98797507 -0.011744
// 0.2 2.7 0.196050+0.013002i | 0.196050 +0.013002 0.99994252 -0.000127
// 1.2 0.2 0.270928+0.469488i | 0.270928 +0.469488 0.90465623 -2.196064
// 1.2 0.7 0.280740+0.291851i | 0.280740 +0.291851 1.82926135 -0.639343
// 1.2 1.7 0.222436+0.129684i | 0.222436 +0.129684 1.00630308 +0.060067
// 1.2 2.7 0.170538+0.068617i | 0.170538 +0.068617 0.99955699 -0.000290
// 2.2 0.2 0.041927+0.287771i | 0.041927 +0.287771 24.70460755-26.205981
// 2.2 0.7 0.099943+0.242947i | 0.099943 +0.242947 9.88734713+18.310797
// 2.2 1.7 0.135021+0.153161i | 0.135021 +0.153161 1.65541359 -1.276707
// 2.2 2.7 0.127900+0.096330i | 0.127900 +0.096330 0.98619434 +0.000564
# endif

View File

@ -0,0 +1,75 @@
/*s***************************************************************************
*
* Copyright (c), Ilya Valuev 2005 All Rights Reserved.
*
* Author : Ilya Valuev, MIPT, Moscow, Russia
*
* Project : GridMD, ivutils
*
*
*
*****************************************************************************/
/*r @file vector_3.h @brief ðàáîòà ñ òðåõìåðíûìè êîìïëåêñíûìè âåêòîðàìè
*/
# ifndef CVECTOR_3A_H
# define CVECTOR_3A_H
# include <complex>
# include <cmath>
# include "vector_3.h"
using namespace std;
typedef complex<vec_type> cdouble;
typedef Vector_Nt<cdouble,3> cVector_3;
//------------------------------------------------------
// Overloads for cdouble
//------------------------------------------------------
inline cdouble operator*(int a, const cdouble &b){
return ((double)a)*b;
}
inline cdouble operator*(const cdouble &b,int a){
return a*b;
}
inline cdouble operator/(const cdouble &b,int a){
return (1./a)*b;
}
inline cdouble operator/(int a, const cdouble &b){
return (a)*(1./b);
}
//------------------------------------------------------
// Overloads for cVector_3
//------------------------------------------------------
inline cVector_3 operator*(const cdouble &a, const Vector_3 &v){
return cVector_3(a*v[0], a*v[1], a*v[2]); // a*cVector_3(v);
}
inline cVector_3 operator*(const Vector_3 &v, const cdouble &a){
return a*v;
}
inline Vector_3 real(const cVector_3 &cv){
return Vector_3(cv[0].real(), cv[1].real(), cv[2].real());
}
inline Vector_3 imag(const cVector_3 &cv){
return Vector_3(cv[0].imag(), cv[1].imag(), cv[2].imag());
}
inline cVector_3 conj(const cVector_3 &cv){
return cVector_3(conj(cv[0]), conj(cv[1]), conj(cv[2]));
}
inline cVector_3 rcell1(cVector_3& cv, Vector_3 &cell, int flags=0xffff) {
return cVector_3( real(cv).rcell1(cell, flags) ) + cdouble(0,1)*imag(cv);
}
# endif // __CVECTOR_3A_H

View File

@ -0,0 +1,19 @@
# ifndef ERF_H
# define ERF_H
# ifdef _WIN32
# ifdef __cplusplus
extern "C" {
# endif
double erf(double x);
double erfc(double x);
# ifdef __cplusplus
}
# endif
# endif
# endif

View File

@ -0,0 +1,53 @@
// Interface for LAPACK function
# ifndef LAPACK_INTER_H
# define LAPACK_INTER_H
#include <complex>
typedef int lapack_int;
typedef complex<float> lapack_complex_float;
typedef complex<double> lapack_complex_double;
#ifdef _WIN32
//#define MKL_Complex8 lapack_complex_float
//#define MKL_Complex16 lapack_complex_double
#include "mkl.h"
inline void ZPPTRF( char* uplo, const lapack_int* n, lapack_complex_double* ap, lapack_int* info ) {
ZPPTRF(uplo, (int*)n, (MKL_Complex16*)ap, (int*)info);
}
inline void ZPPTRI( char* uplo, const lapack_int* n, lapack_complex_double* ap, lapack_int* info ){
ZPPTRI(uplo, (int*)n, (MKL_Complex16*)ap, (int*)info);
}
#else
#define DGETRF dgetrf_
#define DGETRS dgetrs_
#define DGETRI dgetri_
#define ZPPTRF zpptrf_
#define ZPPTRI zpptri_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void dgetrf_( const lapack_int* m, const lapack_int* n, double* a, const lapack_int* lda,
lapack_int* ipiv, lapack_int* info );
void dgetrs_( const char* trans, const lapack_int* n, const lapack_int* nrhs,
const double* a, const lapack_int* lda, const lapack_int* ipiv,
double* b, const lapack_int* ldb, lapack_int* info );
void dgetri_( const lapack_int* n, double* a, const lapack_int* lda,
const lapack_int* ipiv, double* work, const lapack_int* lwork,
lapack_int* info );
void zpptrf_( const char* uplo, const lapack_int* n, lapack_complex_double* ap,
lapack_int* info );
void zpptri_( const char* uplo, const lapack_int* n, lapack_complex_double* ap,
lapack_int* info );
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
#endif /* lapack_intER_H */

View File

@ -0,0 +1,315 @@
# ifndef LOGEXC_H
# define LOGEXC_H
#include <stdlib.h>
#include <stdarg.h>
#include <stdexcept>
#include <string>
# ifndef _WIN32
# include <typeinfo>
# endif
/// this specifies whether to put file/line info in error messages
# ifndef LINFO
# define LINFO 1
# endif
using namespace std;
/// verbosity levels
enum vbLEVELS{
vblNONE = 0, ///< completely silent
vblFATAL = 0x1, ///< report fatal errors
vblOERR = 0x2, ///< report other errors
vblERR = vblFATAL|vblOERR, ///< report all errors
vblWARN = 0x4, ///< report warnings
vblALLBAD = vblWARN|vblERR, ///< report all errors and warnings
vblMESS1 = 0x8, ///< report messages of level 1 (important)
vblMESS2 = 0x10, ///< report messages of level 2 (less important)
vblMESS3 = 0x20, ///< report messages of level 3 (not important)
vblMESS4 = 0x40, ///< report messages of level 4 (anything possible)
vblALLMESS = vblMESS1|vblMESS2|vblMESS3|vblMESS4, ///< report all messages
vblPROGR = 0x80, ///< report progress
vblALL = 0xffff
};
/// traits structure to deduce exception level and name from exception class
/// by default all exceptions have vblFATAL level
template<class exc_t>
struct log_exception_traits{
/// exeption level according to the vbLEVELS
static int level(const exc_t &signal){ return vblFATAL; }
/// the string name of exception category
static string name(const exc_t &signal){ return typeid(exc_t).name();}
/// adds some more explanations to the description
/// default behaviour: nothing done
static exc_t add_words(const exc_t &orig, const char *words){
return orig;
}
};
/// integer exceptions have the level equal to their value
template<>
struct log_exception_traits<int>{
/// exeption level according to the vbLEVELS
static int level(const int &signal){ return signal; }
/// the string name of exception category
static string name(const int &signal){
if(signal&vblFATAL)
return "fatal error";
else if(signal&vblOERR)
return "error";
else if(signal&vblWARN)
return "warning";
else
return "";
/*
else if(signal&vblALLMESS)
return "message";
else if(signal&vblPROGR)
return "progress report";
else
return "integer exception";*/
}
/// default behaviour: nothing done
static int add_words(const int &orig, const char *words){
return orig;
}
};
/// vbLEVELS exceptions act as integers
template<>
struct log_exception_traits<enum vbLEVELS>{
static int level(const enum vbLEVELS &signal){ return log_exception_traits<int>::level(signal); }
static string name(const enum vbLEVELS &signal){ return log_exception_traits<int>::name(signal); }
static enum vbLEVELS add_words(const enum vbLEVELS &orig, const char *words){
return orig;
}
};
/// Logger class to control (computational) function behaviour when something requiring user attention has happened.
/// message(signal,errcode, text) is used to either throw an exception or return errorcode
/// At first, the the level of error is determined via log_exception_traits<>::level(signal)
/// For integer (enum) signals the level is the signal itself.
/// Then text is printed, if signal level is listed in output levels or (or in extra outlevels, if they are set)
/// via log_text() function.
/// If level has vblERR bit, the behaviour is controlled by the flag specified in set_throw(flag):
/// flag=0: nothing done;
/// flag=1: calls add_words() for signal and throws signal;
/// flag=2: throws pair<>(errcode, text);
/// flag=3: throws errcode.
/// Then, if the level is listed in stop_levels (or in extra stop levels, if they are set), the program is aborted,
/// otherwise errcode is returned;
/// The function set_levels(out_levels,stop_levels) is used to specify bitflags for the levels which
/// require message output or/and program termination. Stop level has effect only when exceptions are not thrown.
/// The function extra_levels(eout_levels,estop_levels) is used to temporarily set the corresponding levels,
/// they are unset (the original levels are restored) by calling extra_levels(0,0).
class message_logger {
// global message is a friend
template<class exc_t>
friend int message(const exc_t &signal, int errcode, const char *what, ...);
protected:
string descriptor;
int throw_ex;
int outlevel, eoutlevel;
int stoplevel, estoplevel;
static message_logger *glogp;
/// used to restore the previous global logger
message_logger *prev, *next;
public:
message_logger(const string &descriptor_="", int out_level=vblALLBAD|vblMESS1,
int stop_level=vblFATAL, int throw_exceptions=0, int use_globally=0)
:descriptor(descriptor_),prev(NULL),next(NULL){
set_throw(throw_exceptions);
set_levels(out_level,stop_level);
extra_levels(0,0);
if(use_globally){
set_global(true);
}
}
/// returns a reference to global logger
/// if not set, links with default message_logger
static message_logger &global();
/// sets/unsets this logger as the global logger
int set_global(bool set){
if(set){
if(prev) // already set
return -1;
if(glogp)
glogp->next=this;
prev=glogp;
glogp=this;
}
else{
if(glogp!=this) // was not set as the global
return -1;
glogp=prev;
if(glogp)
glogp->next=NULL;
prev=NULL;
}
return 1;
}
virtual void set_throw(int throw_exceptions){
throw_ex=throw_exceptions;
}
virtual void set_levels(int out_level=vblALLBAD|vblMESS1, int stop_level=vblFATAL){
outlevel=out_level;
stoplevel=stop_level;
}
/// nonzero extra levels are applied instead of set ones
virtual void extra_levels(int out_level=vblALLBAD|vblMESS1, int stop_level=vblFATAL){
eoutlevel=out_level;
estoplevel=stop_level;
}
template<class exc_t>
int message(const exc_t &signal, int errcode, const char *what, ...){
int level=log_exception_traits<exc_t>::level(signal);
char buff[1024];
if(level&(eoutlevel ? eoutlevel : outlevel)){ //needs to print a message
va_list args;
va_start(args,what);
vsnprintf(buff,1024,what,args);
log_text(level,log_exception_traits<exc_t>::name(signal).c_str(),buff);
}
if(level&vblERR){
if(throw_ex==1) // throws exc_t exception
throw log_exception_traits<exc_t>::add_words(signal,buff);
else if(throw_ex==2) // throws pair<>(int,const char*) exception
throw make_pair(errcode,what);
else if(throw_ex==3) // throws int exception
throw errcode;
}
if(level&(estoplevel ? estoplevel: stoplevel) ){ // needs to stop
exit(errcode);
}
return errcode;
}
virtual void log_text(int level, const char *messtype, const char *messtext){
if(descriptor!="") // descriptor is used as header
printf("%s:\n",descriptor.c_str());
if(messtype!="")
printf("%s: ",messtype);
printf("%s\n",messtext);
}
/// checks that the deleted one is not in global logger chain
~message_logger(){
if(prev){
prev->next=next;
if(next)
next->prev=prev;
}
set_global(false);
}
};
/// global message function
template<class exc_t>
int message(const exc_t &signal, int errcode, const char *what, ...){
if(message_logger::glogp){
va_list args;
va_start(args,what);
char buff[1024];
vsnprintf(buff,1024,what,args);
return message_logger::glogp->message(signal,errcode,buff);
}
else
return -1;
}
/// message logger for which std and error streams may be specified
class stdfile_logger: public message_logger {
protected:
FILE *fout, *ferr;
public:
stdfile_logger(const string &descriptor_="", int throw_exceptions=0,
FILE *out=stdout, FILE *err=stderr,
int out_level=vblALLBAD|vblMESS1,int stop_level=vblFATAL,
int use_globally=0)
: message_logger(descriptor_,out_level,stop_level,throw_exceptions,use_globally),fout(NULL), ferr(NULL){
set_out(out);
set_err(err);
}
virtual void set_out(FILE *out, int close_prev=0){
if(close_prev && fout && fout!=stderr && fout !=stdout)
fclose(fout);
fout=out;
}
virtual void set_err(FILE *err, int close_prev=0){
if(close_prev && ferr && ferr!=stderr && ferr !=stdout)
fclose(ferr);
ferr=err;
}
virtual void log_text(int level, const char *messtype, const char *messtext){
FILE *f= (level&vblALLBAD ? ferr : fout);
if(!f)
return;
if(descriptor!="") // descriptor is used as header
fprintf(f,"%s:\n",descriptor.c_str());
if(string(messtype)!="")
fprintf(f,"%s: ",messtype);
fprintf(f,"%s\n",messtext);
}
};
/// format a string
const char *fmt(const char *format,...);
/// macros with common usage
#define LOGFATAL(code,text,lineinfo) ((lineinfo) ? ::message(vblFATAL,(code)," %s at %s:%d",(text),__FILE__,__LINE__) : \
(::message(vblFATAL,(code)," %s",(text))) )
#define LOGERR(code,text,lineinfo) ((lineinfo) ? ::message(vblOERR,(code)," %s at %s:%d",(text),__FILE__,__LINE__) : \
(::message(vblOERR,(code)," %s",(text))) )
#define LOGMSG(cat,text,lineinfo) ((lineinfo) ? ::message((cat),0," %s at %s:%d",(text),__FILE__,__LINE__) : \
(::message((cat),0," %s",(text))) )
# if 0 /// did not work
/// this may be used to inherit exceptions
/// where level and name are defined whithin a class
struct log_exception {
/// exeption level according to the vbLEVELS
static int level(const log_exception &signal){ return vblFATAL; }
/// the string name of exception category
static string name(const log_exception &signal){ return "undefined exception";}
};
/// log_exceptions act as themselves
template<>
struct log_exception_traits<log_exception>{
static int level(const log_exception &signal){ return log_exception::level(signal); }
static string name(const log_exception &signal){ return log_exception::name(signal); }
};
# endif
# endif

View File

@ -0,0 +1,683 @@
/*e***************************************************************************
*
* Copyright (c), Ilya Valuev 2005 All Rights Reserved.
*
* Author : Ilya Valuev, MIPT, Moscow, Russia
*
* Project : ivutils
*
*
*****************************************************************************/
/*e****************************************************************************
* $Log: pairhash.h,v $
* Revision 1.3 2011/06/11 18:18:50 morozov
* USER-AWPMD compiles on Linux now!
*
* Revision 1.2 2011/06/11 16:53:55 valuev
* sync with LAMMPS
*
* Revision 1.1 2011/06/10 17:15:07 morozov
* First Windows project with the correct directory structure
*
* Revision 1.27 2011/06/09 22:55:08 valuev
* norm matrices
*
* Revision 1.26 2011/06/07 17:43:00 valuev
* added Y derivatives
*
* Revision 1.25 2011/05/24 19:54:32 valuev
* fixed sqmatrix::iterator
*
* Revision 1.24 2011/05/21 23:06:49 valuev
* Norm matrix transform to pysical variables
*
* Revision 1.23 2009/09/24 10:06:38 valuev
* moved matrix printing to template function, reproducing old TB calculations
*
* Revision 1.22 2009/02/10 14:20:45 valuev
* sync with FDTD project
*
* Revision 1.4 2009/01/30 13:54:05 valuev
* restructured as a library
*
* Revision 1.21 2008/08/27 13:34:32 valuev
* made icc-compilable
*
* Revision 1.20 2008/08/25 21:06:11 valuev
* moved using delaration to public
*
* Revision 1.19 2008/07/23 16:55:05 morozov
* *** empty log message ***
*
* Revision 1.18 2008/07/23 16:21:52 morozov
* Corrected Makefile for unix compilation of tcpengine
*
* Revision 1.17 2008/07/18 18:15:31 morozov
* *** empty log message ***
*
* Revision 1.16 2008/07/02 13:11:32 valuev
* new C60+O2 experiments
*
* Revision 1.15 2008/06/24 08:50:00 valuev
* made icc-compilable
*
* Revision 1.14 2008/06/24 08:39:57 valuev
* added ESSL support to TB
*
* Revision 1.13 2008/05/29 14:47:33 valuev
* made icc-compilable
*
* Revision 1.12 2008/05/14 17:17:22 morozov
* Passed 2- and 3-electron test. Added Norm matrix.
*
* Revision 1.11 2008/05/05 17:27:43 morozov
* cvector_3.h is the new header for class cVector_3. Old one is moved to cvector_3old.h
* class hmatrix is added to pairhash.h
* wavepackets.h contains class WavePacket
*
* Revision 1.10 2008/04/21 22:42:30 valuev
* *** empty log message ***
*
* Revision 1.9 2008/04/15 13:11:41 valuev
* Added antisymmetrized wave packets
*
* Revision 1.8 2008/02/28 13:26:04 valuev
* vasp scanner
*
* Revision 1.7 2007/12/13 19:48:59 valuev
* added newlines
*
* Revision 1.6 2006/12/20 14:29:33 valuev
* Updated workflow, sync with FDTD
*
* Revision 1.3 2006/10/27 20:41:01 valuev
* Added detectors sceleton. Updated some of ivutils from MD project.
*
* Revision 1.5 2006/09/26 10:59:42 valuev
* Added nonorthogonal TB (Menon-Subbaswamy)
*
* Revision 1.4 2006/07/21 16:22:03 valuev
* Added Tight Binding for graphite+O
*
* Revision 1.3 2006/04/26 12:12:01 valuev
* Fixed Neighbour Lists (double-single counting), added twostep NL scheme, added Step2 to mdtutorial (use of template potentials), added DelAtom to mdStructure
*
* Revision 1.2 2005/12/09 21:06:38 valuev
* Added neighbour list to mdPotential interface.
* Added missing files to ivutils directory.
* Added mdtutorial and step1 project
*
* Revision 1.1 2005/12/02 18:51:06 valuev
* added HEAD project tree
*
* Revision 1.1 2005/11/30 23:36:11 valuev
* put ivutils to cvs on biolab1.mipt.ru
*
* Revision 1.1 2005/11/30 23:15:43 valuev
* put ivutils on cvs biolab1.mipt.ru
*
*
*******************************************************************************/
# ifndef PAIRHASH_H
# define PAIRHASH_H
/*e @file pairhash.h @brief pair hash table
*/
/*r @file pairhash.h @brief ðàáîòà ñ õåø-òàáëèöàìè ïàðíûõ âåëè÷èí
*/
# include "refobj.h"
///\en Rectangular matrix
template <class T>
class recmatrix{
protected:
mngptr<T> parr;
public:
class iterator{
friend class recmatrix<T>;
T *ptr;
size_t incr;
iterator(const recmatrix<T> *parent,size_t first_,size_t second_, bool inc_first=false){
ptr=parent->arr+parent->index(first_,second_);
incr=inc_first ? parent->sizex : 1 ;
};
iterator(T *ptr_,size_t incr_):ptr(ptr_),incr(incr_){}
public:
iterator(const iterator &other):ptr(other.ptr),incr(other.incr){
}
iterator():ptr(NULL),incr(0){}
iterator &operator++(){ // prefix
ptr+=incr;
return *this;
}
iterator operator++(int){ // postfix
iterator tmp=*this;
++*this;
return tmp;
}
iterator operator+(int delta) const {
return iterator(ptr+delta*incr,incr);
}
bool operator!=(const iterator &other) const {
if(ptr!=other.ptr)return true;
else return false;
}
T &operator*() const {
return *ptr;
}
};
T *arr;
size_t sizex, sizey;
//e default constructor
recmatrix(): parr(NULL,1) {
sizey=sizex=0;
arr=NULL;
}
//e copy constructor: makes a managed copy
recmatrix(const recmatrix &other):sizex(0),sizey(0),arr(NULL){
*this=other;
}
recmatrix &operator=(const recmatrix &other){
if(this!=&other){
if(other.sizex*other.sizey<=sizex*sizey)
init(other.sizex,other.sizey,-1); // keeping old array
else
init(other.sizex,other.sizey,1);
size_t n=get_datasize(sizex,sizey);
for(size_t i=0;i<n;i++)
arr[i]=other.arr[i];
}
return *this;
}
virtual size_t get_datasize(size_t nx, size_t ny) const{
return nx*ny;
}
// i is y (row number), j is x (column number)
size_t index(size_t i, size_t j) const {
return sizey*i+j;
}
T &operator()(size_t i,size_t j){
return arr[index(i,j)];
}
T operator()(size_t i,size_t j) const {
return arr[index(i,j)];
}
void set(long i,long j,const T& val){
(*this)(i,j)=val;
}
virtual int init(size_t nx, size_t ny, int smanaged=-1){
int managed=parr.managed();
if(managed && (sizex!=nx || sizey!=ny)){
parr.reset(NULL,0);
}
if(smanaged>=0){ // for changing the managed flag?
parr.reset(parr.ptr(),smanaged ? smanaged|0x8 : 0 );
managed=smanaged;
}
if(sizex==nx && sizey==ny) // no need to allocate
return 1;
sizex=nx;
sizey=ny;
if(managed){
if(sizex>0 && sizey>0)
parr.reset(new T[get_datasize(sizex,sizey)],managed|0x8);
arr=parr.ptr();
}
return 1;
}
recmatrix(size_t nx, size_t ny):sizex(0), sizey(0){
init(nx,ny,1);
}
//e initializes by unmanaged pointer
recmatrix(size_t nx, size_t ny , T *ptr):parr(ptr,0),sizex(nx), sizey(ny) {
init(nx,ny);
}
//e attaches to new pointer and sets unmanaged size
void AttachTo(size_t nx,size_t ny, T *ptr){
init(0,0);
sizex=nx;
sizey=ny;
parr.reset(ptr,0);
}
void Set(const T &val){
size_t i, n=get_datasize(sizex,sizey);
for(i=0;i<n;i++)arr[i]=val;
}
void SetDiag(const T &val){
size_t i, size=(sizex>sizey? sizey: sizex);
for(i=0;i<size;i++){
(*this)(i,i)=val;
}
}
/// returns iterator with fixed first index to iterate through matrix line elements
iterator fix_first(size_t first, size_t second) const {
return iterator(this,first,second,false);
}
/// returns iterator with fixed second index to iterate through matrix column elements
iterator fix_second(size_t first, size_t second) const {
return iterator(this,first,second, true);
}
};
//e square matrix
template <class T>
class sqmatrix: public recmatrix<T> {
public:
size_t size;
//e default constructor
sqmatrix(){}
//e copy constructor: makes a managed copy
sqmatrix(const sqmatrix &other):size(0){
*this=other;
}
sqmatrix &operator=(const sqmatrix &other){
if(this!=&other){
*((recmatrix<T> *)this)=*((recmatrix<T> *)&other);
size=other.size;
}
return *this;
}
virtual size_t get_datasize(size_t n) const{
return n*n;
}
virtual int init(size_t n, int smanaged=-1){
size=n;
return recmatrix<T>::init(n,n,smanaged);
int managed=recmatrix<T>::parr.managed();
}
sqmatrix(size_t n):size(0){
init(n,1);
}
//e initializes by unmanaged pointer
sqmatrix(size_t n, T *ptr):size(n){
init(n);
}
//e attaches to new pointer and sets unmanaged size
void AttachTo(size_t n, T *ptr){
init(0);
size=n;
recmatrix<T>::parr.reset(ptr,0);
}
};
# if 0
//e square matrix
template <class T>
class sqmatrix{
mngptr<T> parr;
public:
class iterator{
friend class sqmatrix<T>;
T *ptr;
size_t incr;
iterator(const sqmatrix<T> *parent,size_t first_,size_t second_, bool inc_first=false){
ptr=parent->arr+parent->index(first_,second_);
incr=inc_first ? parent->size : 1 ;
};
iterator(T *ptr_,size_t incr_):ptr(ptr_),incr(incr_){}
public:
iterator(const iterator &other):ptr(other.ptr),incr(other.incr){
}
iterator():ptr(NULL),incr(0){}
iterator &operator++(){ // prefix
ptr+=incr;
return *this;
}
iterator operator++(int){ // postfix
iterator tmp=*this;
++*this;
return tmp;
}
iterator operator+(int delta) const {
return iterator(ptr+delta*incr,incr);
}
bool operator!=(const iterator &other) const {
if(ptr!=other.ptr)return true;
else return false;
}
T &operator*() const {
return *ptr;
}
};
T *arr;
size_t size;
//e default constructor
sqmatrix(): parr(NULL,1) {
size=0;
arr=NULL;
}
//e copy constructor: makes a managed copy
sqmatrix(const sqmatrix &other):size(0),arr(NULL){
*this=other;
}
sqmatrix &operator=(const sqmatrix &other){
if(this!=&other){
if(other.size<=size)
init(other.size,-1); // keeping old array
else
init(other.size,1);
size_t n=get_datasize(size);
for(size_t i=0;i<n;i++)
arr[i]=other.arr[i];
}
return *this;
}
virtual size_t get_datasize(size_t n) const{
return n*n;
}
size_t index(size_t i, size_t j) const {
return size*i+j;
}
T &operator()(size_t i,size_t j){
return arr[index(i,j)];
}
T operator()(size_t i,size_t j) const {
return arr[index(i,j)];
}
void set(long i,long j,const T& val){
(*this)(i,j)=val;
}
virtual int init(size_t n, int smanaged=-1){
int managed=parr.managed();
if(managed && size!=n){
parr.reset(NULL,0);
}
if(smanaged>=0){ // for changing the managed flag?
parr.reset(parr.ptr(),smanaged ? smanaged|0x8 : 0 );
managed=smanaged;
}
if(size==n) // no need to allocate
return 1;
size=n;
if(managed){
if(size>0)
parr.reset(new T[get_datasize(size)],managed|0x8);
arr=parr.ptr();
}
return 1;
}
sqmatrix(size_t n):size(0){
init(n,1);
}
//e initializes by unmanaged pointer
sqmatrix(size_t n, T *ptr):parr(ptr,0),size(n){
init(n);
}
//e attaches to new pointer and sets unmanaged size
void AttachTo(size_t n, T *ptr){
init(0);
size=n;
parr.reset(ptr,0);
}
void Set(const T &val){
size_t i, n=get_datasize(size);
for(i=0;i<n;i++)arr[i]=val;
}
void SetDiag(const T &val){
size_t i;
for(i=0;i<size;i++){
(*this)(i,i)=val;
}
}
/// returns iterator with fixed first index to iterate through matrix line elements
iterator fix_first(size_t first, size_t second) const {
return iterator(this,first,second,false);
}
/// returns iterator with fixed second index to iterate through matrix column elements
iterator fix_second(size_t first, size_t second) const {
return iterator(this,first,second, true);
}
};
# endif
//e prints the matrix into a file
template< class matrix_t>
int fileout(FILE *f, const matrix_t &matr, const char *elm_fmt, const char *elm_sep=" ", const char *line_sep="\n"){
size_t i, j;
int res=0;
for(i=0;i<matr.size;i++){
for(j=0;j<matr.size;j++){
res+=fprintf(f,elm_fmt,matr(i,j));
fprintf(f,elm_sep);
}
fprintf(f,line_sep);
}
return res;
}
//e symmetric matrix
template <class T>
class smatrix: public sqmatrix<T>{
typedef sqmatrix<T> base_t;
public:
virtual size_t get_datasize(size_t n) const{
return n*(n+1)/2;
}
size_t index(size_t i, size_t j) const {
if(i>=j)
return (2*base_t::size-j-1)*j/2+i;
else
return (2*base_t::size-i-1)*i/2+j;
}
T &operator()(size_t i,size_t j){
return base_t::arr[index(i,j)];
}
T operator()(size_t i,size_t j) const {
return base_t::arr[index(i,j)];
}
void set(long i,long j,const T& val){
(*this)(i,j)=val;
}
void SetDiag(const T &val){
size_t i;
for(i=0;i<base_t::size;i++){
(*this)(i,i)=val;
}
}
smatrix(){}
//e copy constructor: makes a managed copy
smatrix(const smatrix &other):sqmatrix<T>(other){}
smatrix &operator=(const smatrix &other){
return (smatrix&)( *(sqmatrix<T> *)this = (sqmatrix<T> &)other );
}
smatrix(size_t n):sqmatrix<T>(n){}
//e initializes by unmanaged pointer
smatrix(size_t n, T *ptr):sqmatrix<T>(n,ptr){}
};
//e Hermitian matrix
template<class T>
class hmatrix : public smatrix<T>
{
public:
using smatrix<T>::arr;
using smatrix<T>::size;
hmatrix() : smatrix<T>() {}
hmatrix(const smatrix<T> &other) : smatrix<T>(other) {}
//e copy constructor: makes a managed copy
hmatrix(const hmatrix &other): smatrix<T>(other){}
hmatrix &operator=(const hmatrix &other) {
return (hmatrix&)( *(smatrix<T>*)this = (smatrix<T>&)other );
}
hmatrix(size_t n) : smatrix<T>(n) {}
hmatrix(size_t n, T *ptr) : smatrix<T>(n, ptr) {}
T operator()(size_t i, size_t j) const {
if(i<=j) return arr[(2*size-i-1)*i/2+j];
else return conj( arr[(2*size-j-1)*j/2+i] );
}
void set(long i,long j,const T& val){
if(i<=j) arr[(2*size-i-1)*i/2+j] = val;
else arr[(2*size-j-1)*j/2+i] = conj(val);
}
};
//e Basic pair hash class
template <class T>
class PairHash{
public:
//e find the value with indexes i, j
//e @return 0 if not found, 1 otherwise
//e if retval is not NULL, puts the found value there
virtual int Find(long i, long j, T *retval=NULL)=0;
virtual int Find(long i, long j, T **retval=NULL)=0;
virtual int Del(long i, long j)=0;
virtual int Put(long i, long j, const T *value)=0;
virtual int Put(long i, long j, const T& value)=0;
virtual int Clear()=0;
virtual ~PairHash(){}
};
//e Hash with symmetric matrix
template <class T>
class PairHashM: public PairHash<T>{
smatrix<long> indm;
T *arr;
int as;
public:
PairHashM(long n, int antisymmetric =0):indm(n),as(antisymmetric){
indm.Set(-1);
arr= new T[n*(n+1)/2];
}
int Find(long i, long j, T *retval=NULL){
long ind=indm(i,j);
if(ind>=0){
if(retval){
if(as && i<j)*retval=-arr[ind];
else *retval=arr[ind];
}
return 1;
}
return 0;
}
int Find(long i, long j, T **retval){
long ind=indm(i,j);
if(ind>=0){
*retval=&arr[ind];
if(as && i<j)return -1;
return 1;
}
return 0;
}
int Del(long i, long j){
indm(i,j)=-1;
return 1;
}
int Put(long i, long j, const T *value){
long ind=indm.index(i,j);
indm.arr[ind]=ind;
arr[ind]=*value;
if(as && i<j)arr[ind]=-arr[ind];
return 1;
}
int Put(long i, long j, const T& value){
long ind=indm.index(i,j);
indm.arr[ind]=ind;
arr[ind]=value;
if(as && i<j)arr[ind]=-arr[ind];
return 1;
}
int Clear(){
indm.Set(-1);
return 1;
}
virtual ~PairHashM(){
delete [] arr;
}
};
# endif

View File

@ -0,0 +1,470 @@
/*s***************************************************************************
*
* Copyright (c), Ilya Valuev 2006 All Rights Reserved.
*
* Author : Ilya Valuev, MIPT, Moscow, Russia
*
* Project : ivutils
*
*****************************************************************************/
/*s****************************************************************************
* $Log: refobj.h,v $
* Revision 1.2 2011/06/11 16:53:55 valuev
* sync with LAMMPS
*
* Revision 1.1 2011/06/10 17:15:07 morozov
* First Windows project with the correct directory structure
*
* Revision 1.15 2010/10/07 11:20:31 valuev
* preliminary program restart
*
* Revision 1.14 2009/07/24 05:08:46 valuev
* Sync with FDTD, added molecule setup
*
* Revision 1.33 2009/05/19 21:50:17 valuev
* Added TestRay for plane
*
* Revision 1.32 2009/03/23 22:00:48 lesha
* const mngptr &operator=(const mngarg<T> &arg) is added
*
* Revision 1.31 2009/01/30 13:54:05 valuev
* restructured as a library
*
* Revision 1.30 2009/01/21 09:28:15 lesha
* refvector::clear is added
*
* Revision 1.29 2009/01/15 07:31:07 lesha
* *** empty log message ***
*
* Revision 1.28 2009/01/14 10:02:36 lesha
* operator [] is added to mngptr
*
* Revision 1.27 2008/04/29 01:23:59 lesha
* nothing important
*
* Revision 1.26 2008/02/28 08:57:27 lesha
* shptr::free() is made public
*
* Revision 1.25 2008/02/27 13:37:23 lesha
* shptr is added
*
* Revision 1.24 2008/01/22 10:14:05 lesha
* mngarg is added
*
* Revision 1.23 2007/08/08 10:55:37 lesha
* constructor in refvector is correted
*
* Revision 1.22 2007/07/10 19:52:44 lesha
* make gcc compilable
*
* Revision 1.21 2007/07/06 12:23:37 valuev
* made compilable with icc 9
*
* Revision 1.20 2007/06/22 09:42:25 valuev
* *** empty log message ***
*
* Revision 1.19 2007/06/17 00:51:44 lesha
* refobj, refcounter :: reset is modified for ptr==this->ptr case
*
* Revision 1.18 2007/06/05 16:30:53 lesha
* make gcc compilable
*
* Revision 1.17 2007/06/05 11:37:53 lesha
* make gcc compilable
*
* Revision 1.16 2007/06/05 11:07:04 lesha
* make gcc compilable
*
* Revision 1.15 2007/06/04 14:03:55 lesha
* *** empty log message ***
*
* Revision 1.14 2007/05/31 18:00:42 lesha
* *** empty log message ***
*
* Revision 1.13 2007/05/31 16:57:30 lesha
* ref_sequence is added
*
* Revision 1.12 2007/05/31 01:25:01 lesha
* new version of mng_ptr, pencil etc
*
* Revision 1.11 2007/02/20 10:26:11 valuev
* added newlines at end of file
*
* Revision 1.10 2007/02/16 10:16:51 valuev
* allowed array mngptr
*
* Revision 1.4 2007/02/16 09:40:32 valuev
* Added Nudged Elastic Band saddle point search
*
* Revision 1.3 2006/12/20 14:29:33 valuev
* Updated workflow, sync with FDTD
*
* Revision 1.9 2006/12/14 08:42:36 valuev
* reformulated detector
* projectors, corrected open file limit control, tested Fourier sceleton
*
* Revision 1.8 2006/11/29 18:05:05 valuev
* made the code compilable with g++
*
* Revision 1.7 2006/11/29 17:17:01 valuev
* added using base_t::member for ANSI-compatibility
*
* Revision 1.6 2006/11/29 17:11:59 valuev
* added includes
*
* Revision 1.5 2006/11/28 09:16:59 valuev
* Fixed vectors storing managed pointers
*
* Revision 1.4 2006/11/24 20:17:31 valuev
* Added CVS headers
*
*******************************************************************************/
#ifndef _REFOBJ_H
#define _REFOBJ_H
# include <utility>
# include <vector>
# include <map>
using namespace std;
template<class T>
class mngarg: public pair<T *, int>{
public:
typedef pair<T *, int> base_t;
using base_t::second;
using base_t::first;
mngarg(T *ptr, int managed=0): pair<T*,int>(ptr,managed){}
template<class A>
mngarg(const mngarg<A> &arg): pair<T*,int>(arg.first,arg.second){}
};
template<class T>
mngarg<T> make_mngarg(T *ptr, int managed=1){
return mngarg<T>(ptr,managed);
}
/// managed pointer
/// managed==0 do not delete
/// managed==1 delete
/// (NOT IMPLEMENTED) managed==2 copy and delete, requires copy constructor
/// flag 0x8 -- delete as array
template<class T>
class mngptr: public pair<T *, int>{
public:
typedef pair<T *, int> base_t;
typedef T *pointer;
using base_t::second;
using base_t::first;
mngptr(T* ptr=NULL, int managed=0): pair<T*,int>(ptr,managed){
//if(managed==2)ptr= new T(*ptr);
}
mngptr(const mngarg<T> &arg): pair<T*,int>(arg.first,arg.second){}
const mngptr &operator=(const mngarg<T> &arg){
reset(arg.first,arg.second);
return *this;
}
void reset(T* ptr=NULL, int managed=0){
if(second && first && first!=ptr){
if(second&0x8)delete [] first;
else delete first;
}
first=ptr;
second=managed;
}
void reset(const mngarg<T> &arg){
reset(arg.first,arg.second);
}
T* ptr() const {
return first;
}
T* operator->() const {
return first;
}
T& operator*() const{
return *first;
}
T& operator[] (int i) const{
return *(first+i);
}
int managed() const {
return second;
}
~mngptr(){
reset();
}
};
# if 0
template <template<class _type> class cont_tt, class T>
class refcontainer: public cont_tt< T * >{
protected:
int man;
public:
typedef cont_tt< T * > base_t;
typedef typename base_t::iterator iterator;
typedef typename base_t::const_iterator const_iterator;
refcontainer(int smanaged=0):man(smanaged){}
refcontainer(size_t n, int smanaged=0):base_t(n),man(smanaged){}
void set_managed(int sman){
man=sman;
}
~refcontainer(){
if(man){
size_t i, n=base_t::size();
for(i=0;i<n;i++)
if((*this)[i]) delete (*this)[i];
}
}
};
# endif
template < class T >
class refvector: public std::vector< T * >{
protected:
int man;
public:
typedef vector<T*> base_t;
typedef typename base_t::iterator iterator;
typedef typename base_t::const_iterator const_iterator;
refvector(int smanaged=0):man(smanaged){}
// refvector(size_t n, int smanaged=0):base_t(n),man(smanaged){} // ambigious constructors
refvector(size_t n, int smanaged):base_t(n),man(smanaged){}
void set_managed(int sman){
man=sman;
}
~refvector(){
clear();
}
void clear() {
if(man){
iterator it=base_t::begin();
for(;it!=base_t::end();++it)
if(*it)
delete (*it);
}
base_t::clear();
}
iterator erase(iterator it){
if(man && *it)
delete (*it);
return base_t::erase(it);
}
};
template <class key_tt, class T >
class refmap: public std::map<key_tt, T * >{
protected:
int man;
public:
typedef std::map<key_tt, T * > base_t;
typedef typename base_t::iterator iterator;
typedef typename base_t::const_iterator const_iterator;
refmap(int smanaged=0):man(smanaged){}
refmap(size_t n, int smanaged=0):base_t(n),man(smanaged){}
void set_managed(int sman){
man=sman;
}
~refmap(){
clear();
}
void clear() {
if(man){
for(typename base_t::iterator i=base_t::begin();i!=base_t::end();++i)
if(i->second) delete i->second;
}
base_t::clear();
}
iterator erase(iterator it){
if(man && it->second)
delete it->second;
return base_t::erase(it);
}
};
template<class T>
class delete_ptr{
public:
void operator()(T *ptr){
delete ptr;
}
};
template<class T, class delete_t=delete_ptr<T> >
class shptr{
template<class Y, class Z> friend class shptr;
T *p;
int *num; //if num==NULL than p is not managed (as in mngptr)
void set(T *p_, int managed){
p=p_;
if(p&&managed){
num=new int;
*num=1;
}
else num=NULL;
}
template<class Y>
void set(const Y &other){
p=other.p;
if(p){
num=other.num;
if(num)(*num)++;
}
else num=NULL;
}
void set(const shptr &other){
p=other.p;
if(p){
num=other.num;
if(num)(*num)++;
}
else num=NULL;
}
public:
shptr(T* p=NULL, int managed=1){
set(p,managed);
}
shptr(const mngarg<T> &arg){
set(arg.first,arg.second);
}
template<class Y>
shptr(const Y &other){
set(other);
}
shptr(const shptr &other){
set(other);
}
void reset(T *p_, int managed=1) {
if(p!=p_){
free();
set(p_,managed);
}
}
void reset(const shptr &other) {
if(this!=&other){
free();
set(other);
}
}
const shptr &operator=(T *p) {
reset(p,0);
return *this;
}
const shptr &operator=(const mngarg<T> &arg) {
reset(arg.first,arg.second);
return *this;
}
template<class Y>
const shptr &operator=(const Y &other){
reset(other);
return *this;
}
const shptr &operator=(const shptr &other) {
reset(other);
return *this;
}
virtual ~shptr(){
free();
}
void free(){
if(p){
if(num){
(*num)--;
if((*num)==0){
delete_t()(p);
delete num;
}
num=NULL;
}
p=NULL;
}
}
bool valid() const {
return p!=NULL;
}
T* ptr() const {
return p;
}
T* operator->() const {
return p;
}
T& operator*() const{
return *p;
}
};
/*
class RefObject{
void *ref_data;
int ref_count;
public:
protected:
virtual void delete_data(void *data);
virtual void *new_data();
virtual void *copy_data(void *data);
}
class RefA: public RefObject{
public:
refA(){
ref_data = new A;
}
refA(const refA &other){
Ref(other);
}
refA& operator=(const refA &other){
if(ref_data != other.ref_data){
Ref(other);
}
return *this;
}
private:
void delete_data(void *data){
delete (A *)data;
}
void *new_data(){
return (void *)new A;
}
void *copy_data(void *data){
return (void *)(new A(*((A*)data)));
}
}*/
#endif

View File

@ -0,0 +1,707 @@
/*s***************************************************************************
*
* Copyright (c), Ilya Valuev 2005 All Rights Reserved.
*
* Author : Ilya Valuev, MIPT, Moscow, Russia
*
* Project : GridMD, ivutils
*
*****************************************************************************/
/*s****************************************************************************
* $Log: vector_3.h,v $
* Revision 1.2 2011/06/11 16:53:55 valuev
* sync with LAMMPS
*
* Revision 1.1 2011/06/10 17:15:07 morozov
* First Windows project with the correct directory structure
*
* Revision 1.22 2010/11/17 02:13:32 valuev
* Added analysis phase, fixed some memory leaks
*
* Revision 1.21 2009/09/09 14:43:35 valuev
* fixed trajreader
*
* Revision 1.20 2009/07/24 05:08:46 valuev
* Sync with FDTD, added molecule setup
*
* Revision 1.33 2009/06/01 13:01:42 valuev
* Added ShearBox
*
* Revision 1.32 2009/05/28 07:49:00 valuev
* updated chemosensor
*
* Revision 1.31 2009/05/22 08:53:52 valuev
* new uiExperiment interface
*
* Revision 1.30 2009/02/22 10:49:56 lesha
* Vector_Nt constructors are modified
*
* Revision 1.29 2009/02/04 14:23:31 valuev
* fixed bug in maxabscoord and minabscoord functions
*
* Revision 1.28 2009/02/04 10:56:30 lesha
* SINGLE_PRECISION is recovered
*
* Revision 1.27 2009/02/03 00:47:35 lesha
* *** empty log message ***
*
* Revision 1.26 2009/01/30 13:54:05 valuev
* restructured as a library
*
* Revision 1.16 2008/08/18 21:40:09 valuev
* added Gurski-Krasko potential
*
* Revision 1.15 2008/05/05 17:27:43 morozov
* cvector_3.h is the new header for class cVector_3. Old one is moved to cvector_3old.h
* class hmatrix is added to pairhash.h
* wavepackets.h contains class WavePacket
*
* Revision 1.14 2008/04/22 12:44:17 valuev
* made gcc 4.12 compilable
*
* Revision 1.13 2008/04/21 23:13:44 valuev
* made gcc 4.12 compilable
*
* Revision 1.12 2008/04/21 22:42:30 valuev
* *** empty log message ***
*
* Revision 1.11 2008/04/15 13:11:41 valuev
* Added antisymmetrized wave packets
*
*
*******************************************************************************/
/*r @file vector_3.h @brief ðàáîòà ñ òðåõìåðíûìè âåêòîðàìè
*/
# ifndef VECTOR_3_H
# define VECTOR_3_H
# define _USE_MATH_DEFINES
# include <iostream>
# include <cmath>
# include <limits>
# include <stdlib.h>
// some compilers don't define PI!
# ifndef M_PI
# define M_PI 3.1415926535897932385
# endif
# ifndef fmod
//r äåëåíèå ïî ìîäóëþ ÷èñåë ñ ïëàâàþùåé òî÷êîé
# define fmod(a,b) ((a)-((long)((a)/(b))*(b)))
# endif
using namespace std;
#ifndef SINGLE_PRECISION
typedef double vec_type;
#else
typedef float vec_type;
#endif
//e "infinitely" large number in Vector_3 sense
//r "áåñêîíå÷íî áîëüøîå" ÷èñëî â ñìûñëå Vector_3
//# ifndef SINGLE_PRECISION
//# define VEC_INFTY 1.e20
//# else
//# define VEC_INFTY 1.e20f
//# endif
#define VEC_INFTY numeric_limits<vec_type>::max()
//e "infinitely" small number in Vector_3 sense (used for vector comparisons)
//r "áåñêîíå÷íî ìàëîå" ÷èñëî â ñìûñëå Vector_3 (èñïîëüçóåòñÿ äëÿ ñðàâíåíèé)
//# ifndef SINGLE_PRECISION
//# define VEC_ZERO 1.e-20
//# else
//# define VEC_ZERO 1.e-20f
//# endif
#define VEC_ZERO 512*numeric_limits<vec_type>::epsilon()
//r N-ìåðíûé âåêòîð òèïà T, ñ íåêîòîðûìè ïîëåçíûìè îïåðàöèÿìè
template <class T, const int N=3>
struct Vector_Nt {
typedef T value_type;
T v[N];
Vector_Nt(const T &a=0){
for (int i=0; i<N; i++)
v[i]=a;
}
explicit Vector_Nt(const T &a1, const T &a2) {
if(N>0)v[0]=a1;
if(N>1)v[1]=a2;
for(int i=2;i<N;i++)v[i]=0;
}
explicit Vector_Nt(const T &s1, const T &s2, const T& s3) {
if(N>0)v[0]=s1;
if(N>1)v[1]=s2;
if(N>2)v[2]=s3;
for(int i=3;i<N;i++)v[i]=0;
}
//e construct from input iterator (or array)
template <class A>
Vector_Nt(const A *beg) {
for (int i=0; i<N; i++, ++beg)
v[i]=*beg;
};
//e construct from another vector
template <class A>
Vector_Nt(const Vector_Nt<A,N>& v1) {
for (int i=0; i<N; i++) v[i]=v1[i];
};
//r Êîïèðóåò ñîäåðæèìîå âåêòîðà â it
template <class A>
void copy_to(A *beg) const {
for (int i=0; i<N; i++, ++beg)
*beg=v[i];
};
//r ïîëó÷åíèå ýëåìåíòà
inline T& operator[](int i) const { return (T&)v[i]; };
inline Vector_Nt& operator=(const Vector_Nt &vect){
for (int i=0; i<N; i++)
v[i]=vect.v[i];
return *this;
}
//r ïðèñâàèâàåò âñåì êîìïîíåíòàì çíà÷åíèå a.
inline Vector_Nt& operator=(const T &a){
for (int i=0; i<N; i++)
v[i]=a;
return *this;
};
//r ñðàâíåíèå. Ïðè îòëè÷èè ìåíüøå ÷åì íà VEC_ZERO êîìïîíåíòû ñ÷èòàþòñÿ îäèíàêîâûìè
inline bool operator==(const Vector_Nt &vect) const{
for (int i=0; i<N ;i++)
if(fabs(v[i]-vect.v[i])>VEC_ZERO)return false;
return true;
};
inline bool operator!=(const Vector_Nt &vect) const{
return (!(this->operator==(vect)));
};
inline Vector_Nt operator+(const Vector_Nt& vect) const{
Vector_Nt result;
for (int i=0; i<N ;i++)
result.v[i]=v[i]+vect.v[i];
return result;
}
inline Vector_Nt operator-(const Vector_Nt &vect) const {
Vector_Nt result;
for (int i=0; i<N ;i++)
result.v[i]=v[i]-vect.v[i];
return result;
}
//r Ñêàëÿðíîå ïðîèçâåäåíèå âåêòîðîâ
inline T operator*(const Vector_Nt& vect) const {
T result=0;
for (int i=0; i<N; i++)
result+=v[i]*vect.v[i];
return result;
}
//r Ïîêîìïîíåíòíîå óìíîæåíèå íà êîýôôèöèåíò
inline Vector_Nt operator*(const T &coeff) const {
Vector_Nt result;
for (int i=0; i<N; i++)
result[i]=coeff*v[i];
return result;
}
//e vector multiplication (N=3 only)
//r Âåêòîðíîå ïðîèçâåäåíèå
inline Vector_Nt operator%(const Vector_Nt &r) const{ //reserved for N specializations
if(N==3){
return Vector_Nt(v[1]*r.v[2]-v[2]*r.v[1],v[2]*r.v[0]-v[0]*r.v[2],v[0]*r.v[1]-v[1]*r.v[0]);
}
return *this;
}
//r Óìíîæåíèå ÷èñëà íà âåêòîð (ïåðåñòàâëåíû ìåñòàìè ìíîæèòåëè).
// friend Vector_Nt operator*(T coeff,const Vector_Nt& vec);
//r Ïîêîìïîíåíòíîå äåëåíèå íà êîýôôèöèåíò
inline Vector_Nt operator/(const T &coeff) const {
Vector_Nt result;
for (int i=0; i<N; i++)
result[i]=v[i]/coeff;
return result;
}
//r Óìíîæåíèå âåêòîðà íà -1
inline Vector_Nt operator-() const {
Vector_Nt r;
for (int i=0; i<N; i++)
r.v[i]=-v[i];
return r;
}
//r Ñëîæåíèå ñ ïðèñâàèâàíèåì
inline Vector_Nt& operator+=(const Vector_Nt &vect){
for (int i=0; i<N; i++)
v[i]+=vect.v[i];
return *this;
}
//r Âû÷èòàíèå ñ ïðèñâàèâàíèåì
inline Vector_Nt& operator-=(const Vector_Nt &vect){
for (int i=0; i<N; i++)
v[i]-=vect.v[i];
return *this;
}
//r Óìíîæåíèå íà êîýôôèöèåíò ñ ïðèñâàèâàíèåì
inline Vector_Nt& operator*=(const T &coeff){
for (int i=0; i<N; i++)
v[i]*=coeff;
return *this;
}
//r Äåëåíèå íà ñêàëÿð ñ ïðèñâàèâàíèåì
inline Vector_Nt& operator/=(const T &coeff){
for (int i=0; i<N; i++)
v[i]/=coeff;
return *this;
}
//r Êâàäðàò íîðìû âåêòîðà
T norm2() const {
T result=0;
for (int i=0; i<N; i++)
result+=v[i]*v[i];
return result;
}
//r Íîðìà âåêòîðà
T norm() const {
return sqrt(norm2());
}
//r Âîçâðàùàåò íîðìó è íîðìàëèçóåò âåêòîð (ïîñëå ýòîãî åãî norm() âåðíåò newnorm).
T normalize(T newnorm=1.){
T norm=this->norm();
if(norm>=VEC_ZERO){
T c=newnorm/norm;
for (int i=0; i<N; i++)
v[i]*=c;
}
return norm;
}
//e Normalizes a vector that may have infinite components
T inormalize(T newnorm=1.){
T result=0;
for (int i=0; i<N; i++){
if(fabs(v[i])>=VEC_INFTY){
if(result>=0)
result=0.;
result-=1;
v[i]=v[i]>0 ? 1 : -1;
}
else if(result>=0) //still summing the normal components
result+=v[i]*v[i];
else
v[i]=0.;
}
if(fabs(result)<VEC_ZERO)
return 0.;
newnorm/=sqrt(fabs(result));
for (int i=0; i<N; i++)
v[i]*=newnorm;
return result<0 ? VEC_INFTY : result;
}
//e nearest image distance within rectangular cell (FOR DISTANCE MEASUREMENTS)
//e assumes that each coordinate absolute value is in the range [0,cell[i])
//e returned vector is in the range [-cell[i]/2,cell[i]/2)
//e flags indicate the periodicity in specific directions: 0x1 for X, 0x2 for Y, 0x4 for Z
//r Áëèæàéøèé îáðàç â ïðÿìîóãîëüíîé ÿ÷åéêå
/*r Ñ÷èòàåì, ÷òî âñå ïðîñòðàíñòâî ðàçäåëåíî íà ÿ÷åéêè - ïàðàëëåëåïèïåäû ñ ðåáðàìè, ïàðàëëåëüíûìè
îñÿì êîîðäèíàò è äèàãîíàëüþ, çàäàííîé âåêòîðîì rcell, ïðè÷åì íà÷àëî êîîðäèíàò ÿâëÿåòñÿ
öåíòðîì îäíîé èç ÿ÷ååê. Åñëè *this íàõîäèòñÿ öåíòðàëüíîé ÿ÷åéêå, âîçâðàùàåòñÿ êîïèÿ *this.\n
Èíà÷å, åñëè *this íàõîäèòñÿ â êóáå 3*3 ÿ÷åéêè ñ öåíòðîì â íà÷àëå êîîðäèíàò, òî ñîçäàåò îáðàç
*this â öåíòðàëüíîé ÿ÷åéêå.\n
Èíà÷å, âîçâðàùàåò íåîïðåäåëåííîå çíà÷åíèå.
*/
Vector_Nt rcell1(const Vector_Nt &cell,int flags=0xffff) const{
Vector_Nt ret(*this);
int i;
for(i=0;i<N;i++){
if(flags&(0x1<<i)){
if(v[i]>cell[i]/2){
ret[i]-=cell[i];
}
else if(v[i]<-cell[i]/2){
ret[i]+=cell[i];
}
}
}
return ret;
}
//e @return a vector projection on a given axis
Vector_Nt prj(int i) const {
Vector_Nt res;
res[i]=v[i];
return res;
}
//e @return a vector projection on a given vector (k*v)*k
Vector_Nt prj(const Vector_Nt &k) const {
return k*(k*(*this));
}
//e @return a vector of length l parallel to this
Vector_Nt unit(T l=1) const {
Vector_Nt res(*this);
res.normalize(l);
return res;
}
//e reduction to elementary cell [0, cell[i]) (FOR REDUCTION TO ELEMENTARY CELL)
//e flags indicate the periodicity in specific directions: 0x1 for X, 0x2 for Y, 0x4 for Z
//r Ïî÷òè òî æå, ÷òî è rcell1, íî áåç îãðàíè÷åíèÿ íà ïîëîæåíèå *this è ñ äðóãîé ñèñòåìîé ÿ÷ååê.
/*r  íà÷àëå êîîðäèíàò íàõîäèòñÿ íå öåíòð ÿ÷åéêè, à åå óãîë. Ìîæåò ðàáîòàòü ìåäëåííåå èç-çà íàëè÷èÿ
îïåðàöèè äåëåíèÿ ïî ìîäóëþ ñ ïëàâàþùåé òî÷êîé */
Vector_Nt rcell(const Vector_Nt &cell, int flags=0xffff) const {
Vector_Nt ret(*this);
for (int i=0, flag=1; i<N; i++, flag<<=1) {
if(flags&flag){
ret.v[i]=fmod(v[i],cell[i]);
if(ret.v[i]<0)ret.v[i]+=cell[i];
// if(ret.v[i]<0 || ret.v[i]>cell[i])
// printf("!");
}
}
return ret;
}
Vector_Nt rpcell(const Vector_Nt &p1, const Vector_Nt &cell, int flags=0xfff) const {
Vector_Nt ret(*this);
for (int i=0, flag=1; i<N; i++, flag<<=1) {
if(flags&flag){
if (ret.v[i]<p1[i] || ret.v[i]>p1[i]+cell[i]) {
ret.v[i]=fmod(v[i]-p1[i],cell[i])+p1[i];
if (ret.v[i]<p1[i]) ret.v[i]+=cell[i];
}
}
}
return ret;
}
//r Âîçâðàùàåò ìàêñèìàëüíóþ êîìïîíåíòó âåêòîðà è åå èíäåêñ â ind
T maxcoord(int *ind=NULL) const {
int im=0;
T vv=v[0];
for (int i=1; i<N; i++) {
if(v[i]>vv){
im=i;
vv=v[i];
}
}
if(ind)*ind=im;
return vv;
}
//e returns the corrd having maximal absolute value
T maxabscoord(int *ind=NULL) const {
int im=0;
T vv=fabs(v[0]);
for (int i=1; i<N; i++) {
if(fabs(v[i])>vv){
im=i;
vv=fabs(v[i]);
}
}
if(ind)*ind=im;
return v[im];
}
//e returns the corrd having minimal absolute value
T minabscoord(int *ind=NULL) const {
int im=0;
T vv=fabs(v[0]);
for (int i=1; i<N; i++) {
if(fabs(v[i])<vv){
im=i;
vv=fabs(v[i]);
}
}
if(ind)*ind=im;
return v[im];
}
//r Âîçâðàùàåò ìèíèìàëüíóþ êîìïîíåíòó âåêòîðà è åå èíäåêñ â ind
T mincoord(int *ind=NULL) const {
int im=0;
T vv=v[0];
for (int i=1; i<N; i++) {
if(v[i]<vv){
im=i;
vv=v[i];
}
}
if(ind)*ind=im;
return vv;
}
//r Âûâîäèò âåêòîð â ïîòîê âûâîäà ïî óìîë÷àíèþ, â ôîðìàòå (x,y,z)\\n
void print() const{
cout<< "(";
for(int i=0;i<N;i++){
cout<< v[i];
if(i!=N-1)
cout<< ", ";
}
cout<< ")\n";
}
//e returns true if the vector has infinite components
bool infinite() const {
for(int i=0;i<N;i++){
if(fabs(v[i])>=VEC_INFTY)
return true;
}
return false;
}
};
template<class T , int N>
Vector_Nt<T, N> operator*(const T &coeff,const Vector_Nt<T, N> &vec){
return vec*coeff;
}
template<class T , int N>
Vector_Nt<T, N> operator*(int coeff,const Vector_Nt<T, N> &vec){
return vec*coeff;
}
//template <> Vector_Nt<double, 3> operator*(const double &coeff,const Vector_Nt<double,3> &vec);
// old Vector_3 compatibility typedefs and functions
typedef Vector_Nt<vec_type, 3> Vector_3;
typedef Vector_3 *Vector_3P;
typedef Vector_Nt<vec_type, 2> Vector_2;
typedef Vector_2 *Vector_2P;
template <int N>
class Vector_N: public Vector_Nt<vec_type, N>{
};
//Vector_3 operator*(int coeff,const Vector_3 &vec){
// return vec*((vec_type)coeff);
//}
//e finds the maximum distance between vector pairs
//r Íàõîäèò ìàêñèìàëüíîå ðàññòîÿíèå ìåæäó âåêòîðàìè va1[i], va2[i], i=1..n
/*r @param va1 - ìàññèâ Vector_3[n]
@param n - äëèíà ìàññèâîâ va1 è va2
*/
vec_type dist_max(Vector_3 *va1,Vector_3 *va2,int n);
//e finds average distance between vector pairs
//r Íàõîäèò ñðåäíåå ðàññòîÿíèå ìåæäó âåêòîðàìè va1[i], va2[i], i=1..n
vec_type dist_av(Vector_3 *va1,Vector_3 *va2,int n);
//e finds the average difference norm between two vector sets of the same length
/*e optionally gives the indexes for maximal and minimal difference
va2 can be NULL, then the norm of va1 is used */
//r Íàõîäèò ñðåäíåå ðàññòîÿíèå ìåæäó va1[i] è va2[i], à òàêæå, ïî æåëàíèþ, èíäåêñû, íà êîòîðûõ äîñòèãàåòñÿ min è max ðàññòîÿíèå
vec_type diff_av(Vector_3 *va1,Vector_3 *va2,int n, int *minind=0, int *maxind=0);
//e finds suitable perpendicular to a vector
//r Íàõîäèò ïåðïåíäèêóëÿð ê âåêòîðó vAB
Vector_3 FindPerp(const Vector_3 &vAB);
//e Returns the average (center) vector of the vector array
//e and cooordinates of a minimal box in which it is contained
Vector_3 GetScope(const Vector_3 *varr,long n,Vector_3* box_min,Vector_3* box_max);
//e the same with long index array
Vector_3 GetIScope(const Vector_3 *varr,long *indarr,long n,Vector_3* box_min,Vector_3* box_max);
//e the same with int index array
Vector_3 GetIScopei(const Vector_3 *varr,int *indarr,int n,Vector_3* box_min,Vector_3* box_max);
// neue Funktionen
//e clears vector array with optional integer index
//r Î÷èñòêà ìàññèâà âåêòîðîâ, ñ ïîääåðæêîé èíäåêñèðîâàíèÿ
/*r
 äàííîì Vector_3 vec[] îáíóëÿåò n êîîðäèíàò. Åñëè ind==NULL, òî
î÷èùàåò ïåðâûå n ýëåìåíòîâ. Åñëè ind!=NULL, òî äëÿ i=0..n-1
î÷èùàåò vec[ind[i]]
Ñì. @ref indexed_calculations.
*/
void clear_vecarri(int n,Vector_3 *vec, int *ind=0);
//e reflects the vector ini+dir*t+0.5*force*t^2 to be inside a box limited by 0 and box sizes
//e changes dir according to the final state
//e fills crossed dir with bit flags corresponding directions along which the walls were crossed
Vector_3 Reflect(Vector_3& ini, double t,Vector_3 &dir, double *box, int flag=0x7, const Vector_3 &force=Vector_3());
inline vec_type vec_area(const Vector_2 &vect1, const Vector_2 &vect2) {
return fabs(vect1[0]*vect2[1]-vect1[1]*vect2[0])/2;
};
inline vec_type vec_area(const Vector_3 &vect1, const Vector_3 &vect2) {
return (vect1%vect2).norm()/2;
};
// remake for vec_type!
template <class num_t, class denum_t, class val_t>
denum_t acccomp(const num_t x, const denum_t y, const val_t val) {
num_t eps_num=numeric_limits<num_t>::epsilon();
denum_t eps_denum=numeric_limits<denum_t>::epsilon();
return (eps_num>=eps_denum) ? acccomp(x, (num_t)y, (num_t)val) : acccomp((denum_t)x, y, (denum_t)val);
}
template <class num_t, class denum_t>
denum_t acccomp(const num_t x, const denum_t y) {
return acccomp(x, y, num_t(1));
}
template<class T>
bool acccomp(const T x, const T y, const T val) {
T eps=numeric_limits<T>::epsilon();
int iexp;
frexp(val,&iexp);
T mult=ldexp(.5, iexp+1);
T err=T(256)*mult*eps;
return fabs(x-y)<=err;
}
template<class T>
bool acccomp(const T x, const T y) {
return acccomp(x, y, T(1));
}
template <class num_t, class denum_t>
denum_t accdiv(const num_t x, const denum_t y) {
num_t eps_num=numeric_limits<num_t>::epsilon();
denum_t eps_denum=numeric_limits<denum_t>::epsilon();
return (eps_num>=eps_denum) ? accdiv1(x, (num_t)y) : accdiv1((denum_t)x, y);
}
template <class T>
T accdiv1(T x, T y) {
T result;
T eps=numeric_limits<T>::epsilon();
T fr=x/y;
T ifr=floor(fr+T(.5));
// T err=64*eps*(ifr!=0 ? fabs(ifr) : 1);
int mult;
if (ifr<=512)
mult=512;
else {
int iexp;
frexp(ifr,&iexp);
mult=int(ldexp(.5, iexp+1));
}
T err=mult*eps;
if (fabs(fr-ifr)<=err)
result=ifr;
else
result=fr;
return result;
}
template <class num_t, class denum_t, class P>
denum_t accdiv_rmd(const num_t x, const denum_t y, P *remainder) {
num_t eps_num=numeric_limits<num_t>::epsilon();
denum_t eps_denum=numeric_limits<denum_t>::epsilon();
return (eps_num>=eps_denum) ? accdiv_rmd(x, (num_t)y, remainder) : accdiv_rmd((denum_t)x, y, remainder);
}
template <class T, class P>
T accdiv_rmd(const T x, const T y, P *remainder) {
T result=accdiv(x, y);
T iresult=floor(result);
if (result-iresult>0)
*remainder=x-iresult*y;
else
*remainder=0;
return result;
}
//e returns random unit vector uniformely distributed in space (?? check this)
inline Vector_3 randdir(){
vec_type xi1=2*((vec_type)rand())/RAND_MAX-1.;
vec_type xi2=((vec_type)rand())/RAND_MAX;
vec_type r1=sqrt(1.-xi1*xi1);
return Vector_3(r1*cos(2*M_PI*xi2),r1*sin(2*M_PI*xi2),xi1);
}
///\en Calculates extent of the vector container.
/// \return the center of the vector set, optionally
/// (if arguments are not NULL) fills the bounding box in \a box_min, \a box_max.
template<class vec_inp_it>
Vector_3 get_extent(vec_inp_it beg,vec_inp_it end, Vector_3* box_min=NULL,Vector_3* box_max=NULL){
if(beg==end)
return Vector_3();
Vector_3 center(*beg++);
Vector_3 cube1(center), cube2(center);
size_t n=1;
for(;beg!=end;++beg){
Vector_3 vec=*beg;
center+=vec;
for(size_t j=0;j<3;j++){
if(cube1[j]>vec[j])
cube1[j]=vec[j];
if(cube2[j]<vec[j])
cube2[j]=vec[j];
}
n++;
}
if(box_min)
*box_min=cube1;
if(box_max)
*box_max=cube2;
return center/n;
}
///\en Returns \a true if absolute value of \a a is at least \a factor times less than
/// the absolute value of \a b.
template<class T>
bool much_less(const T& a, const T& b, const T &factor){
if(fabs(a)<fabs(b))
return fabs(a*factor/b)<1 ? true : false;
else
return false;
}
# endif // __VECTOR_3_H

View File

@ -0,0 +1,242 @@
# ifndef WAVEPACKET_H
# define WAVEPACKET_H
# ifndef _USE_MATH_DEFINES
# define _USE_MATH_DEFINES
# endif
# include <cmath>
# include <complex>
# include <functional>
# include "cvector_3.h"
using namespace std;
/** @file wpmd.h
@brief Classes to handle Gaussian Wave Packets. */
// Constants
const double MIN_EXP_ARG = -15.; // Minimum noticeable argument for exp function
class WavePacket;
///\en Template for v=der operation in \ref Wavepacket::int2phys_der()
template<class Type>
struct eq_second : public binary_function <Type, Type, Type> {
Type operator()(const Type& _Left, const Type& _Right) const{
return _Right;
}
};
///\en Template for v=-der operation in \ref Wavepacket::int2phys_der()
template<class Type>
struct eq_minus_second : public binary_function <Type, Type, Type> {
Type operator()(const Type& _Left, const Type& _Right) const{
return -_Right;
}
};
///\en Compares complex numbers on a per component basis.
/// \return \retval 0 if all component differences are 0 within tolerance \a tol (EQUAL),
/// \retval -1 for LESS
/// \retval 2 for GREATER
template< class CT >
int compare_compl(const CT &a, const CT& b, double tol=0.){
double dd=real(a)-real(b);
if(dd<-tol)
return -1;
if(dd>tol)
return 1;
dd=imag(a)-imag(b);
if(dd<-tol)
return -1;
if(dd>tol)
return 1;
return 0;
}
///\en Compares vectors on a per component basis.
/// \return \retval 0 if all component differences are 0 within tolerance \a tol (EQUAL),
/// \retval -1 for LESS
/// \retval 2 for GREATER
inline int compare_vec(const Vector_3 &a, const Vector_3& b, double tol=0.){
for(int i=0;i<3;i++){
double dd=a[i]-b[i];
if(dd<-tol)
return -1;
if(dd>tol)
return 1;
}
return 0;
}
/// wavepacket is w(x)=exp(-a*x^2+b*x+lz)
class WavePacket{
/// constructs a conjugate packet
friend WavePacket conj(const WavePacket &wp);
public:
cdouble a;
cVector_3 b;
cdouble lz;
WavePacket(const cdouble &sa=cdouble(1.,0.),const cVector_3 &sb=cVector_3(0.,0.), const cdouble &slz=0.): a(sa), b(sb), lz(slz){
}
WavePacket operator*(const WavePacket& other) const {
return WavePacket(a+other.a,b+other.b,lz+other.lz);
}
/// returns the integral of w(x) over 3D space
cdouble integral() const {
cdouble z = lz + b.norm2()/(4.*a);
if(real(z) < MIN_EXP_ARG) return 0.;
return pow(M_PI/a,3./2.)*exp(z);
}
/// init normalized packet with physical parameters: r0, p0, width, pw
/// w(x)=(3/2pi width^(3/4)exp[-(3/(4 width^2)-i pw/(2*width) )(x-r)^2+i p (x-r)]
void init(const double width=1., const Vector_3 &r=0., const Vector_3 &p=0., const double pw=0.){
a = (3./(2.*width) - cdouble(0.,1.)*pw)/(2.*width);
b = (2.*a)*r + cdouble(0.,1.)*p;
lz = log(3./(2.*M_PI*width*width))*(3./4.) + (-a*r.norm2() - cdouble(0.,1.)*(p*r));
}
/// init normalized packet with complex parameters a and b
/// w(x)=(3/2pi width^(3/4)exp[-(3/(4 width^2)-i pw/(2*width) )(x-r)^2+i p (x-r)]
void init(const cdouble &a_, const cVector_3 &b_){
a = a_;
b = b_;
Vector_3 r = get_r();
double r2 = r.norm2();
lz = cdouble( log( real(a)*(2./M_PI) )*(3./4.) - r2*real(a), r2*imag(a) - r*imag(b) );
}
cdouble operator()(const Vector_3 &x) const {
return exp(lz - a*x.norm2() + b*x);
}
/// ajusts lz so that Integral[w*(conj(w))] is 1 after this operation
WavePacket& normalize(){
//lz=0.;
//lz=overlap(conj(*this));
//lz=(-1./2)*log(lz);
Vector_3 r = get_r();
double r2 = r.norm2();
lz = cdouble( log( real(a)*(2./M_PI) )*(3./4.) - r2*real(a), r2*imag(a) - r*imag(b) );
return *this;
}
/// computes 3D overlap of wavepackets Inegral[w*other]
cdouble overlap(const WavePacket &other) const{
WavePacket wp=(*this)*other;
return wp.integral();
}
/// returns translated packet to the position of r'=r+dr
WavePacket translate(const Vector_3 &dr) const {
WavePacket wp(a,b,lz);
wp.b+=2*dr*a;
Vector_3 r=get_r();
double dr2=(r+dr).norm2()-r.norm2();
wp.lz+=-a*dr2-cdouble(0.,(get_p()*dr));
return wp;
}
/// width
double get_width() const{
return sqrt(3./4./real(a));
}
/// width momentum
double get_pwidth() const{
return -imag(a)*sqrt(3./real(a));
}
/// both width and width momentum
pair<double,double> get_width_pars() const{
double c=sqrt(3./2./real(a));
return make_pair(c/2,-imag(a)*c);
}
/// position
Vector_3 get_r() const {
return real(b)/(2*real(a));
}
/// momentum
Vector_3 get_p() const {
return imag(b) - real(b)*(imag(a)/real(a));
}
///\en Transforms derivatives of a function whith respect to WP parameters
/// from internal into physical representation, i. e.:\n
/// from df/d{are,aim,b0re,b0im,b1re,b1im,b2re,b2im} (8 values accessed by input iterator d_it in the given order)\n
/// to df/d{x0,x1,x2}, df/d{p0,p1,p2}, df/dw, df/dpw
/// The supplied inputs (val) are modified by op: val=op(val,phys_der).
/// Use operation=eq_second for the supplied inputs to be replaced by new physical derivative values.
/// The inpput and output locations may coinside, an internal buffer is used for transformation.
template<template<class A> class operation, class d_it, class dfdx_it, class dfdp_it, class dfdw_it, class dfdpw_it>
void int2phys_der(d_it dfdi_,dfdx_it dfdx, dfdp_it dfdp, dfdw_it dfdw, dfdpw_it dfdpw, double h_p=h_plank) const {
operation<double> op;
double dfdi[8], dfn[8];// internal buffer
for(int i=0;i<8;i++)
dfdi[i]=*dfdi_++;
double w=get_width();
Vector_3 r=get_r();
double t=3/(2*w*w*w);
dfn[6]= -t*dfdi[0]-imag(a)*dfdi[1]/w; //dw
dfn[7]=-dfdi[1]/(2*w*h_p); // dpw
for(int i=0;i<3;i++){
dfn[i]= 2*real(a)*dfdi[2+2*i]+2*imag(a)*dfdi[2+2*i+1];
dfn[3+i]= dfdi[2+2*i+1]*(/*m_electron*/1./h_p) ; //*(h_plank/m_electron);
dfn[7]+=-(r[i]*dfdi[2+2*i+1]/w)/h_p;
dfn[6]+=-2*r[i]*(t*dfdi[2+2*i]+imag(a)*dfdi[2+2*i+1]/w);
}
int i=0;
for(int k=0;k<3;k++)
*dfdx++=op(*dfdx,dfn[i++]);
for(int k=0;k<3;k++)
*dfdp++=op(*dfdp,dfn[i++]);
*dfdw=op(*dfdw,dfn[i++]);
*dfdpw=op(*dfdpw,dfn[i++]);
}
///\en Compares the wave packet to another on a per component basis.
/// \return \retval 0 if all component differences are 0 within tolerance \a tol (EQUAL),
/// \retval -1 for LESS
/// \retval 2 for GREATER
int compare(const WavePacket &other, double tol=0.) const {
int res=compare_compl(a,other.a, tol);
if(res)
return res;
for(int i=0;i<3;i++){
res=compare_compl(b[i],other.b[i]);
if(res)
return res;
}
return 0;
}
};
/*double w=wk.get_width();
Vector_3 r=wk.get_r();
double t=3/(2*w*w*w);
fe_w[ic1+k1]+= t*E_der[s1][indw1+8*k1]+imag(wk.a)*E_der[s1][indw1+8*k1+1]/w;
fe_pw[ic1+k1]+=E_der[s1][indw1+8*k1+1]/(2*w*h_plank);
for(int i=0;i<3;i++){
fe_x[ic1+k1][i]+= -2*real(wk.a)*E_der[s1][indw1+8*k1+2+2*i]-2*imag(wk.a)*E_der[s1][indw1+8*k1+2+2*i+1];
fe_p[ic1+k1][i]+= (-E_der[s1][indw1+8*k1+2+2*i+1])*(m_electron/h_plank); //*(h_plank/m_electron);
fe_pw[ic1+k1]+=(r[i]*E_der[s1][indw1+8*k1+2+2*i+1]/w)/h_plank;
fe_w[ic1+k1]+=2*r[i]*(t*E_der[s1][indw1+8*k1+2+2*i]+imag(wk.a)*E_der[s1][indw1+8*k1+2+2*i+1]/w);
}*/
/// constructs a conjugate packet
inline WavePacket conj(const WavePacket &wp){
return WavePacket(conj(wp.a),conj(wp.b),conj(wp.lz));
}
# endif // WAVEPACKET_H

View File

@ -0,0 +1,25 @@
//# ifdef USE_STDAFX
//# include "stdafx.h"
//# endif
# include "logexc.h"
message_logger std_log;
message_logger &message_logger::global(){
if(!glogp){
std_log.set_global(true);
}
return *glogp;
}
message_logger *message_logger::glogp=NULL;
stdfile_logger default_log("",0,stdout,stderr,vblALLBAD|vblMESS1,vblFATAL,1);
const char *fmt(const char *format,...){
va_list args;
va_start(args,format);
static char buff[1024];
vsnprintf(buff,1024,format,args);
return buff;
}

340
lib/awpmd/license/COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -0,0 +1,8 @@
AWPMD library license, Version 1
Copyright (c) 1992-2011 Ilya Valuev
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
AWPMD library is free software, you can redistribute and modify it under the
terms of WXWINDOWS LIBRARY LICENSE, Version 3 (www.wxwidgets.org)

View File

@ -0,0 +1,53 @@
wxWindows Library Licence, Version 3
====================================
Copyright (c) 1998 Julian Smart, Robert Roebling et al
Everyone is permitted to copy and distribute verbatim copies
of this licence document, but changing it is not allowed.
WXWINDOWS LIBRARY LICENCE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public Licence as published by
the Free Software Foundation; either version 2 of the Licence, or (at
your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
General Public Licence for more details.
You should have received a copy of the GNU Library General Public Licence
along with this software, usually in a file named COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA.
EXCEPTION NOTICE
1. As a special exception, the copyright holders of this library give
permission for additional uses of the text contained in this release of
the library as licenced under the wxWindows Library Licence, applying
either version 3 of the Licence, or (at your option) any later version of
the Licence as published by the copyright holders of version 3 of the
Licence document.
2. The exception is that you may use, copy, link, modify and distribute
under the user's own terms, binary object code versions of works based
on the Library.
3. If you copy code from files distributed under the terms of the GNU
General Public Licence or the GNU Library General Public Licence into a
copy of this library, as this licence permits, the exception does not
apply to the code that you add in this way. To avoid misleading anyone as
to the status of such modified files, you must delete this exception
notice from such code and/or adjust the licensing conditions notice
accordingly.
4. If you write modifications of your own for this library, it is your
choice whether to permit this exception to apply to your modifications.
If you do not wish that, you must delete the exception notice from such
code and/or adjust the licensing conditions notice accordingly.

View File

@ -0,0 +1,17 @@
# ifndef _TCPDEFS_H
# define _TCPDEFS_H
//Constants
const double sqr_2_over_3 = 0.816496580927726;
const double two_over_sqr_pi = 1.12837916709551;
# ifndef PLASMA_UNITS // using GridMD units: A, eV, m_proton=1
const double h_plank=0.06442021524615668;
const double h_sq=h_plank*h_plank;
const double m_electron=1./1836.1527556560675;
const double m_proton=1.;
const double coul_pref=14.39965172693122; // e^2/(4*pi*eps0), eV*A
const double eV_to_K=11604.447517053462; // Temperature in K correspondent to 1eV
# endif
# endif

View File

@ -0,0 +1,890 @@
# include "wpmd.h"
// Calculates derivative overlap matrix IDD
void OverlapDeriv::calc_der_overlap(bool self, cdouble cc1, cdouble c2){
cVector_3 I3 = I1 * ((bb_4a + 2.5) / w12.a);
cdouble I4 = I0 * ( bb_4a *(bb_4a + 5.) + 3.75 ) / w12.a / w12.a;
// calculate derivatives <(phi_k)'_q_k | (phi_l)'_q_l>:
IDD.set(0, 0, I4 - (d1.l + d2.l)*I2 + d1.l*d2.l*I0 ); // over a_k_re and a_l_re
IDD.set(0, 1, i_unit*( I4 - (d1.l + d2.m)*I2 + d1.l*d2.m*I0 ) ); // over a_k_re and a_l_im
if(!self)
IDD.set(1, 0, i_unit1*( I4 + (d1.m - d2.l)*I2 - d1.m*d2.l*I0 ) ); // over a_k_im and a_l_re
else
IDD.set(1,0, conj(IDD(0,1)));
IDD.set(1, 1, I4 + (d1.m - d2.m)*I2 - d1.m*d2.m*I0 ); // over a_k_im and a_l_im
for(int i=0;i<3;i++){
IDD.set(0, (i+1)*2, -I3[i] + d1.l*I1[i] + d2.u[i]*(d1.l*I0 - I2) ); // over a_k_re and b_l_re
IDD.set(0, (i+1)*2+1, i_unit1*( I3[i] - d1.l*I1[i] + d2.v[i]*(I2 - d1.l*I0) ) ); // over a_k_re and b_l_im
IDD.set(1, (i+1)*2, i_unit *( I3[i] + d1.m*I1[i] + d2.u[i]*(I2 + d1.m*I0) ) ); // over a_k_im and b_l_re
IDD.set(1, (i+1)*2+1, -I3[i] - d1.m*I1[i] - d2.v[i]*(d1.m*I0 + I2) ); // over a_k_im and b_l_im
if(!self) {
IDD.set((i+1)*2, 0, -I3[i] + d2.l*I1[i] + d1.u[i]*(d2.l*I0 - I2) ); // over b_k_re and a_l_re
IDD.set((i+1)*2+1, 0, i_unit *( I3[i] - d2.l*I1[i] - d1.v[i]*(I2 - d2.l*I0) ) ); // over b_k_im and a_l_re
IDD.set((i+1)*2, 1, i_unit1*( I3[i] - d2.m*I1[i] + d1.u[i]*(I2 - d2.m*I0) ) ); // over b_k_re and a_l_im
IDD.set((i+1)*2+1, 1, -I3[i] + d2.m*I1[i] - d1.v[i]*(d2.m*I0 - I2) ); // over b_k_im and a_l_im
}
else{
IDD.set((i+1)*2, 0, conj(IDD(0,(i+1)*2)) ); // over b_k_re and a_l_re
IDD.set((i+1)*2+1, 0, conj(IDD(0,(i+1)*2+1)) ); // over b_k_im and a_l_re
IDD.set((i+1)*2, 1, conj(IDD(1,(i+1)*2)) ); // over b_k_re and a_l_im
IDD.set((i+1)*2+1, 1, conj(IDD(1,(i+1)*2+1)) ); // over b_k_im and a_l_im
}
for(int j=0;j<3;j++){
if(!self || j>=i){
cdouble I2ij = I0 / w12.a *
(i==j ? w12.b[i]*w12.b[i] / w12.a / 4 + 0.5
: w12.b[i]*w12.b[j] / w12.a / 4);
// over b_k_re and b_l_re
IDD.set((j+1)*2, (i+1)*2, I2ij + d1.u[i]*I1[j] + d2.u[j]*(I1[i] + d1.u[i]*I0) );
// over b_k_re and b_l_im
IDD.set((j+1)*2, (i+1)*2+1, i_unit *( I2ij + d1.u[i]*I1[j] + d2.v[j]*(I1[i] + d1.u[i]*I0) ) );
// over b_k_im and b_l_re
if(!self || i!=j)
IDD.set((j+1)*2+1, (i+1)*2, i_unit1*( I2ij - d1.v[i]*I1[j] + d2.u[j]*(I1[i] - d1.v[i]*I0) ) );
else
IDD.set((j+1)*2+1, (i+1)*2, conj(IDD((i+1)*2,(j+1)*2+1)));
// over b_k_im and b_l_im
IDD.set((j+1)*2+1,(i+1)*2+1, I2ij - d1.v[i]*I1[j] + d2.v[j]*(I1[i] - d1.v[i]*I0) );
}
else{ // self && j<i
// over b_k_re and b_l_re
IDD.set((j+1)*2, (i+1)*2, conj(IDD((i+1)*2, (j+1)*2)) );
// over b_k_re and b_l_im
IDD.set((j+1)*2, (i+1)*2+1, conj(IDD((i+1)*2+1,(j+1)*2)) );
// over b_k_im and b_l_re
IDD.set((j+1)*2+1, (i+1)*2, conj(IDD((i+1)*2,(j+1)*2+1)) );
// over b_k_im and b_l_im
IDD.set((j+1)*2+1,(i+1)*2+1, conj(IDD((i+1)*2+1,(j+1)*2+1 )) );
}
} // j
} // i
if(real(cc1)){ // adding terms for split-packet
IDD.set(8, 0, c2*da2_re() ); // over c_1_re and a_2_re
IDD.set(8, 1, c2*da2_im() ); // over c_1_re and a_2_im
IDD.set(9, 0, -i_unit*c2*da2_re() ); // over c_1_im and a_2_re
IDD.set(9, 1, -i_unit*c2*da2_im() ); // over c_1_im and a_2_im
IDD.set(0, 8, cc1*da1_re() ); // over c_2_re and a_1_re
IDD.set(1, 8, cc1*da1_im() ); // over c_2_re and a_1_im
IDD.set(0, 9, i_unit*cc1*da1_re() ); // over c_2_im and a_1_re
IDD.set(1, 9, i_unit*cc1*da1_im() ); // over c_2_im and a_1_im
for(int i=0;i<3;i++){
IDD.set(8, 2+2*i, c2*db2_re(i) ); // over c_1_re and b_2_re
IDD.set(8, 2+2*i+1, c2*db2_im(i) ); // over c_1_re and b_2_im
IDD.set(9, 2+2*i, -i_unit*c2*db2_re(i) ); // over c_1_im and b_2_re
IDD.set(9, 2+2*i+1, -i_unit*c2*db2_im(i) ); // over c_1_im and b_2_im
IDD.set(2+2*i, 8, cc1*db1_re(i) ); // over c_2_re and b_1_re
IDD.set(2+2*i+1, 8, cc1*db1_im(i) ); // over c_2_re and b_1_im
IDD.set(2+2*i, 9, i_unit*cc1*db1_re(i) ); // over c_2_im and i_1_re
IDD.set(2+2*i+1, 9, i_unit*cc1*db1_im(i) ); // over c_2_im and a_1_im
}
IDD.set(8, 8, I0 ); // over c_1_re and c_2_re
IDD.set(8, 9, i_unit*I0 ); // over c_1_re and c_2_im
IDD.set(9, 8, -i_unit*I0 ); // over c_1_im and c_2_re
IDD.set(9, 9, I0 ); // over c_1_im and c_2_im
}
}
WavePacket AWPMD::create_wp(Vector_3 &x, Vector_3 &v, double &w, double &pw, double mass){
if(mass<0)
mass=me;
if(constraint==FIX){
if(w0>0)
w=w0;
pw=0.;
}
double rw;
if(Lextra>0){ // width PBC, keeping the width are within [0,Lextra]
w=fmod(w,Lextra);
if(w<0) w+=Lextra;
rw=w; // WP width for energy evaluation is within [0, L/2]
if(rw > Lextra/2) rw = Lextra - rw;
}
else
rw=w;
WavePacket wp;
wp.init(rw,x,v*mass*one_h,pw*one_h);
return wp;
}
void AWPMD::resize(int flag){
for(int s=0;s<2;s++){
//0. resizing matrices
Y[s].init(ne[s],1);
O[s].init(ne[s],1);
Oflg[s].init(ne[s],1);
//Te[s].init(nel,1);
//Tei[s].init(nel,1);
Eep[s].assign((size_t)nwp[s],0);
Eeip[s].assign((size_t)nwp[s],0);
Eeep[s].assign((size_t)nwp[s],0);
Ewp[s].assign((size_t)nwp[s],0);
if(flag&(0x8|0x4) && approx!=HARTREE){ //electron forces, L and M are needed
M[s].init(ne[s],nvar[s]);
L[s].init(ne[s],nvar[s]);
}
}
Eiep.assign((size_t)ni,0);
Eiip.assign((size_t)ni,0);
}
//e sets Periodic Boundary Conditions
//e using bit flags: 0x1 -- PBC along X
//e 0x2 -- PBC along Y
//e 0x4 -- PBC along Z
//e cell specifies the lengths of the simulation box in all directions
//e if PBCs are used, the corresponding coordinates of electrons and ions
//e in periodic directions must be within a range [0, cell[per_dir])
//e @returns 1 if OK
int AWPMD::set_pbc(const Vector_3P pcell, int pbc_){
if(!pcell)
pbc=0;
else{
pbc=pbc_;
cell=*pcell;
}
return 1;
}
//e setup elctrons: forms internal wave packet representations
//e if PBCs are used the coords must be within a range [0, cell)
int AWPMD::set_electrons(int s, int n, Vector_3P x, Vector_3P v, double* w, double* pw, double mass, double *q)
{
if(s < 0 || s > 1)
return LOGERR(-1,fmt("AWPMD.set_electrons: invaid s setting (%d)!",s),LINFO);
norm_matrix_state[s] = NORM_UNDEFINED;
nwp[s]=ne[s]=n;
nvar[s]=8*n;
wp[s].resize(n);
partition1[s].clear();
for(int i=0;i<n;i++){
wp[s][i]=create_wp(x[i],v[i],w[i],pw[i], mass);
// assign default partition
partition1[s].push_back(i+1);
}
// assign electronic charge
if(q)
qe[s].assign(q,q+nwp[s]);
else
qe[s].assign(nwp[s],-1);
return 1;
}
//e setup ion charges and coordinates
//e if PBCs are used the coords must be within a range [0, cell)
int AWPMD::set_ions(int n, double* q, Vector_3P x)
{
ni = n;
qi.resize(n);
xi.resize(n);
partition1[2].clear();
for(int i=0;i<n;i++){
qi[i] = q[i], xi[i] = x[i];
// assign default partition for ions
partition1[2].push_back(i+1);
}
return 1;
}
//e same as interaction, but using Hartee factorization (no antisymmetrization)
int AWPMD::interaction_hartree(int flag, Vector_3P fi, Vector_3P fe_x,
Vector_3P fe_p, double *fe_w, double *fe_pw, Vector_2P fe_c){
// 0. resizing the arrays if needed
enum APPROX tmp=HARTREE;
swap(tmp,approx); // do not neeed large matrices
resize(flag);
swap(tmp,approx);
//1. clearing forces
clear_forces(flag,fi,fe_x,fe_p,fe_w,fe_pw,fe_c);
Eee = Ew = 0.;
for(int s1=0;s1<2;s1++){
Ee[s1]=0.;
Eei[s1]=0.;
for(int c1=0;c1<ne[s1];c1++){
// width part
double w1=wp[s1][c1].get_width();
/*double sgn1=1;
if(Lextra>0){ // width PBC
if(w1>Lextra-w1){
w1=-(Lextra-w1); // '-' is to change derivative sign
sgn1=-1;
}
}*/
Vector_3 r1=wp[s1][c1].get_r();
Vector_3 p=wp[s1][c1].get_p()*h_plank;
Vector_3 pw=wp[s1][c1].get_pwidth()*h_plank;
// energy contribution
Ee[s1] += (p.norm2()+pw.norm2())/(2*me);
Ew += h2_me*9./(8.*w1*w1);
if(constraint == HARM) Ew += harm_w0_4 * w1*w1;
// width force contribution
//double dE=2*Epot/w;
//if(d->fw1)d->fw1[c1]+=dE;
//if(fw2 && fw2!=fw1)fw2[c1]+=dE;
// e-e interaction
for(int s2=s1;s2<2;s2++){
for(int c2=(s1==s2 ? c1+1 : 0) ;c2<ne[s2];c2++){
double w2=wp[s2][c2].get_width();
Vector_3 v12=wp[s2][c2].get_r()-r1;
// position PBC
v12=v12.rcell1(cell,pbc);
double r12=v12.normalize();
/*double sgn2=1; // signs
if(Lextra>0){ // width PBC
if(w2>Lextra-w2){
w2=-(Lextra-w2); // '-' is to change derivative sign
sgn2=-1;
}
}*/
double wsq=w1*w1+w2*w2;
double argw=sqrt((2./3.)*wsq);
//double arg=r12/argw;
//double erfa=erf(arg);
double Epot=coul_pref*erf_div(r12,1./argw); //erfa/r12;
Eee+=Epot;
// force contribution
/*double dEw=coul_pref*two_over_sqr_pi*exp(-arg*arg)/argw;
double dEpot=(Epot-dEw)/r12;
if(!d->fixw){
dEw/=wsq;
if(d->fw1 && c1>=0){
d->fw1[c1]+=sgn1*dEw*w1;
}
if(d->fw2){
d->fw2[c2]+=sgn2*dEw*w2;
}
}*/
}
}
// e-i interaction
double wsq1=w1*w1;
double argw=sqr_2_over_3*w1;
for(int i=0;i<ni;i++){
Vector_3 v12=xi[i]-r1;
// position PBC
v12=v12.rcell1(cell,pbc);
double r12=v12.normalize();
//double arg=r12/argw;
//double erfa=erf(arg);
double cel=-coul_pref*qi[i]; // electron charge is always -1
double Epot=cel*erf_div(r12,1./argw); //erfa/r12;
Eei[s1]+=Epot;
//printf("(%g %g %g)- (%g %g %g)\n",r1[0],r1[1],r1[2],xi[i][0],xi[i][1],xi[i][2]);
//printf("awp(%d,%d:%d)[%g]: %g\n",i,s1,c1,r12,Epot);
// force contribution
if(flag&0x3){
double arg=r12/argw;
double dEw=cel*two_over_sqr_pi*exp(-arg*arg)/argw;
double dEpot=(Epot-dEw)/r12;
fi[i]+=v12*dEpot; // ionic force
}
// electron force
/*if(!d->fixw){
dEw/=wsq;
if(d->fw1 && c1>=0){
d->fw1[c1]+=sgn1*dEw*w1;
}
}*/
}
}
}
if(calc_ii)
interaction_ii(flag,fi);
return 1;
}
//e initializes internal buffers for calculations (set_electrons must be called first)
//int init(){}
//e calculates interaction in the system of ni ions + electrons
//e the electonic subsystem must be previously setup by set_electrons, ionic by set_ions
//e the iterators are describing ionic system only
// 0x1 -- give back ion forces
// 0x2 -- add ion forces to the existing set
// 0x4 -- calculate derivatives for electronic time step (NOT IMPLEMENTED)
//e if PBCs are used the coords must be within a range [0, cell)
int AWPMD::interaction(int flag, Vector_3P fi, Vector_3P fe_x,
Vector_3P fe_p, double *fe_w, double *fe_pw, Vector_2P fe_c){
if(approx==HARTREE)
return interaction_hartree(flag,fi,fe_x,fe_p,fe_w,fe_pw,fe_c);
// 0. resizing the arrays if needed
resize(flag);
// 1. clearing forces
clear_forces(flag,fi,fe_x,fe_p,fe_w,fe_pw,fe_c);
//2. calculating overlap matrix
for(int s=0;s<2;s++){
int nes = ne[s];
if(nes == 0) continue;
for(int k=0;k<nes;k++){
Y[s].set(k,k,1.); // Diagonal elements (=1)
Oflg[s](k,k) = 1;
for(int l=k+1;l<nes;l++){
cdouble I0kl = pbc_mul(wp[s][l],wp[s][k]).integral(); // Non-diagonal elements
Y[s].set(k,l,I0kl);
Oflg[s](k,l) = (norm(I0kl) > ovl_tolerance);
}
}
O[s] = Y[s]; // save overlap matrix
//3. inverting the overlap matrix
int info=0;
if(nes){
/*FILE *f1=fopen(fmt("matrO_%d.d",s),"wt");
fileout(f1,Y[s],"%15g");
fclose(f1);8*/
ZPPTRF("L",&nes,Y[s].arr,&info);
// analyze return code here
if(info<0)
return LOGERR(info,fmt("AWPMD.interacton: call to ZPTRF failed (exitcode %d)!",info),LINFO);
ZPPTRI("L",&nes,Y[s].arr,&info);
if(info<0)
return LOGERR(info,fmt("AWPMD.interacton: call to ZPTRI failed (exitcode %d)!",info),LINFO);
/*f1=fopen(fmt("matrY_%d.d",s),"wt");
fileout(f1,Y[s],"%15g");
fclose(f1);*/
}
// Clearing matrices for electronic forces
if(flag&0x4){
Te[s].Set(0.);
Tei[s].Set(0.);
}
}
Vector_3 ndr;
// calculating single particle contribution
for(int s=0;s<2;s++){
Ee[s]=Eei[s]=0.;
for(int k=0;k<ne[s];k++){
for(int l=k;l<ne[s];l++){
if( !Oflg[s](k,l) ) continue; // non-overlapping WPs
// electrons kinetic energy
WavePacket wk=wp[s][k];
WavePacket& wl=wp[s][l];
if(pbc)
ndr=move_to_image(wl,wk);
WavePacket wkl=wl*conj(wk);
//Vector_3 rrkl=wkl.get_r();
cVector_3 v1=wl.b*conj(wk.a)-conj(wk.b)*wl.a;
cdouble v=(v1*v1)/wkl.a;
v-=6.*conj(wk.a)*wl.a;
v/=wkl.a;
cdouble I0kl = O[s](k,l);
cdouble dE=-h2_me*I0kl*v/2;
if(flag&0x4) // matrix needed only for electronic forces
Te[s].set(k,l,dE);
// energy component (trace)
dE*=Y[s](l,k);
Ee[s]+=(l==k ? 1. : 2.)*real(dE);
cVector_3 dkl=wkl.b/(2.*wkl.a);
// e-i energy
cdouble sum(0.,0.);
for(int i=0;i<ni;i++){ // ions loop
cVector_3 gkli=dkl - cVector_3(xi[i]);
if(pbc) // correcting the real part (distance) according to PBC
gkli=rcell1(gkli,cell,pbc);
//-Igor- gkli=cVector_3(real(gkli).rcell1(cell,pbc),imag(gkli));
cdouble ngkli=gkli.norm();
cdouble c=sqrt(wkl.a);
//cdouble ttt = cerf_div(ngkli,c);
dE=-coul_pref*(qi[i])*I0kl*cerf_div(ngkli,c);
sum+=dE;
if(flag&0x3){// calculate forces on ions
if(fabs(real(ngkli))+fabs(imag(ngkli))>1e-10){
cdouble arg=ngkli*c;
cdouble dEw=-coul_pref*qi[i]*I0kl*two_over_sqr_pi*exp(-arg*arg)*c;
dE=(dE-dEw)/ngkli;
dE*=Y[s](l,k);
Vector_3 dir=-real(gkli);
dir.normalize();
fi[i]+=(l==k ? 1. : 2.)*real(dE)*dir;
}
}
}
dE=sum;
if(flag&0x4) // matrix needed only for electronic forces
Tei[s].set(k,l,dE);
// energy component (trace)
dE*=Y[s](l,k);
Eei[s]+=(l==k ? 1. : 2.)*real(dE);
}
}
}
// calculating e-e interaction
Eee = Ew = 0.;
// same spin
for(int s=0;s<2;s++){ // spin
for(int k=0;k<ne[s];k++){ //c1
for(int l=k+1;l<ne[s];l++){ //c3
for(int m=k;m<ne[s];m++){ //c2
if( Oflg[s](k,m) ) {
WavePacket wkm=pbc_mul(wp[s][m],wp[s][k]);
cVector_3 dkm=wkm.b/(2*wkm.a);
cdouble I0km=O[s](k,m);
// kl-mn
for(int n=l;n<ne[s];n++){ //c4
if(n<=m || !Oflg[s](l,n)) continue;
WavePacket wln=pbc_mul(wp[s][n],wp[s][l]);
if(pbc) // reducing the pair to elementary cell
ndr=move_to_image(wkm,wln); // mind the derivative: wln.b+=wln.a*ndr, wln.lz+=-wln.a*ndr^2-i*wln.old_p*ndr;
//Vector_3 rln=wln.get_r();
cVector_3 dln=wln.b/(2*wln.a);
cdouble dd=(dkm-dln).norm();
cdouble c=1./sqrt(1./wln.a+1./wkm.a);
cdouble Vklmn=coul_pref*I0km*O[s](l,n)*cerf_div(dd,c);
//cdouble arge=dkm*dkm*wkm.a+dln*dln*wln.a+wkm.lz+wln.lz;
//cdouble Vklmn=0.5*coul_pref*M_PI*M_PI*M_PI*exp(arge)*cerf_div(dd,c)/pow(wln.a*wkm.a,3./2.);
cdouble dE=Vklmn*(Y[s](m,k)*Y[s](n,l)-Y[s](m,l)*Y[s](n,k));
double rdE=real(dE);
if(m!=k || n!=l) // not the same pair
rdE*=2;
Eee+=rdE;
}//n
}
if( Oflg[s](l,m) ) {
WavePacket wlm=pbc_mul(wp[s][m],wp[s][l]);
cVector_3 dlm=wlm.b/(2*wlm.a);
cdouble I0lm=O[s](l,m);
// kl-nm
for(int n=l;n<ne[s];n++){
if(n<=m || !Oflg[s](k,n)) continue;
WavePacket wkn=pbc_mul(wp[s][n],wp[s][k]);
if(pbc) // reducing the pair to elementary cell
ndr=move_to_image(wlm,wkn); // mind the derivative: wln.b+=wln.a*ndr, wln.lz+=-wln.a*ndr^2-i*wln.old_p*ndr;
cVector_3 dkn=wkn.b/(2*wkn.a);
cdouble dd=(dkn-dlm).norm();
cdouble c=1./sqrt(1./wkn.a+1./wlm.a);
cdouble Vklnm=coul_pref*I0lm*O[s](k,n)*cerf_div(dd,c);
cdouble dE=Vklnm*(Y[s](n,k)*Y[s](m,l)-Y[s](n,l)*Y[s](m,k));
double rdE=real(dE);
if(m!=k || n!=l) // not the same pair
rdE*=2;
Eee+=rdE;
}//n
}
}// m
}// l
}// k
}// s
// different spin
for(int k=0;k<ne[0];k++){ // skm=0 //c1
for(int l=0;l<ne[1];l++){ // sln=1 //c3
for(int m=k;m<ne[0];m++){ //c2
if( Oflg[0](k,m) ) {
WavePacket wkm=pbc_mul(wp[0][m],wp[0][k]);
cVector_3 dkm=wkm.b/(2*wkm.a);
cdouble I0km=O[0](k,m);
for(int n=l;n<ne[1];n++){ // km-ln //c4
if( Oflg[1](n,l) ) {
WavePacket wln=pbc_mul(wp[1][l],wp[1][n]);
if(pbc) // reducing the pair to elementary cell
ndr=move_to_image(wkm,wln); // mind the derivative: wln.b+=wln.a*ndr, wln.lz+=-wln.a*ndr^2-i*wln.old_p*ndr;
//Vector_3 rln=wln.get_r();
cVector_3 dln=wln.b/(2*wln.a);
cdouble dd=(dkm-dln).norm();
cdouble c=1./sqrt(1./wln.a+1./wkm.a);
cdouble Vklmn=coul_pref*I0km*wln.integral()*cerf_div(dd,c);
cdouble dE=Vklmn*Y[0](m,k)*Y[1](n,l);
int Mkm=(m==k ? 1: 2);
int Mln=(n==l ? 1: 2);
double rdE=Mkm*Mln*real(dE); //!!!
Eee+=rdE;
} //if
} // n
} //if
} // m
}// l
}// k
if(calc_ii)
interaction_ii(flag,fi);
return 1;
}
//e Calculates Norm matrix and performs LU-factorization
//e The result is saved in AWPMD::Norm[s]
void AWPMD::norm_matrix(int s){
// Internal variables
int k, l, i, j, qi, qj;
int nes = ne[s], nes8 = nes*8, nnes8 = nes*nes8;
if(!nes) return;
// References for frequently used arrays
sqmatrix<double>& Norms = Norm[s];
chmatrix& Ys = Y[s];
smatrix<unsigned char>& Oflgs = Oflg[s];
// Allocate of vectors and matrices
Norms.init(nes8,1);
IDD.init(nes8,1);
if(ID.size() != nnes8)
ID.resize(nnes8), IDYs.resize(nnes8), ipiv.resize(nes8);
// Calculate first and second derivatives
for(k=0;k<nes;k++){
int k8 = k*8;
WavePacket& wk = wp[s][k];
NormDeriv dk(wk);
dk = conj(dk); // conjugate: mu -> -mu, v -> -v !!!
for(l=0;l<nes;l++){
if( !Oflgs(k,l) ) continue; // non-overlapping WPs
int l8 = l*8;
WavePacket wl = wp[s][l];
if(pbc) move_to_image(wk,wl);
WavePacket wkl=conj(wk)*wl;
NormDeriv dl(wl);
cdouble I0 = O[s](k,l);
cVector_3 I1 = wkl.b * (I0 / wkl.a / 2);
cdouble bb_4a = wkl.b.norm2() / wkl.a / 4;
cdouble I2 = I0 * (bb_4a + 1.5) / wkl.a;
// calculate derivatives <phi_k | (phi_l)'_q_l>:
int idx = k + l*nes8;
if(k != l) {
ID[idx] = dl.l*I0 - I2; // over a_l_re
ID[idx+nes] = i_unit*(dl.m*I0 - I2); // over a_l_im
for(i=0;i<3;i++){
ID[idx+((i+1)*2)*nes] = dl.u[i]*I0 + I1[i]; // over b_l_re
ID[idx+((i+1)*2+1)*nes] = i_unit*(dl.v[i]*I0 + I1[i]); // over b_l_im
}
} else { // k == l
ID[idx] = i_unit*imag(dl.l); // over a_l_re
ID[idx+nes] = i_unit*(dl.m - I2); // over a_l_im
for(i=0;i<3;i++){
ID[idx+((i+1)*2)*nes] = dl.u[i] + I1[i]; // over b_l_re
ID[idx+((i+1)*2+1)*nes] = 0.; // over b_l_im
}
}
if(k <= l) {
cVector_3 I3 = I1 * ((bb_4a + 2.5) / wkl.a);
cdouble I4 = I0 * ( bb_4a *(bb_4a + 5.) + 3.75 ) / wkl.a / wkl.a;
// calculate derivatives <(phi_k)'_q_k | (phi_l)'_q_l>:
IDD.set(k8, l8, I4 - (dk.l + dl.l)*I2 + dk.l*dl.l*I0 ); // over a_k_re and a_l_re
IDD.set(k8, l8+1, i_unit*( I4 - (dk.l + dl.m)*I2 + dk.l*dl.m*I0 ) ); // over a_k_re and a_l_im
if(k != l) IDD.set(k8+1, l8, i_unit1*( I4 + (dk.m - dl.l)*I2 - dk.m*dl.l*I0 ) ); // over a_k_im and a_l_re
IDD.set(k8+1, l8+1, I4 + (dk.m - dl.m)*I2 - dk.m*dl.m*I0 ); // over a_k_im and a_l_im
for(i=0;i<3;i++){
IDD.set(k8, l8+(i+1)*2, -I3[i] + dk.l*I1[i] + dl.u[i]*(dk.l*I0 - I2) ); // over a_k_re and b_l_re
IDD.set(k8, l8+(i+1)*2+1, i_unit1*( I3[i] - dk.l*I1[i] + dl.v[i]*(I2 - dk.l*I0) ) ); // over a_k_re and b_l_im
IDD.set(k8+1, l8+(i+1)*2, i_unit *( I3[i] + dk.m*I1[i] + dl.u[i]*(I2 + dk.m*I0) ) ); // over a_k_im and b_l_re
IDD.set(k8+1, l8+(i+1)*2+1, -I3[i] - dk.m*I1[i] - dl.v[i]*(dk.m*I0 + I2) ); // over a_k_im and b_l_im
if(k != l) {
IDD.set(k8+(i+1)*2, l8, -I3[i] + dl.l*I1[i] + dk.u[i]*(dl.l*I0 - I2) ); // over b_k_re and a_l_re
IDD.set(k8+(i+1)*2+1, l8, i_unit *( I3[i] - dl.l*I1[i] - dk.v[i]*(I2 - dl.l*I0) ) ); // over b_k_im and a_l_re
IDD.set(k8+(i+1)*2, l8+1, i_unit1*( I3[i] - dl.m*I1[i] + dk.u[i]*(I2 - dl.m*I0) ) ); // over b_k_re and a_l_im
IDD.set(k8+(i+1)*2+1, l8+1, -I3[i] + dl.m*I1[i] - dk.v[i]*(dl.m*I0 - I2) ); // over b_k_im and a_l_im
}
for(j=0;j<3;j++){
cdouble I2ij = I0 / wkl.a *
(i==j ? wkl.b[i]*wkl.b[i] / wkl.a / 4 + 0.5
: wkl.b[i]*wkl.b[j] / wkl.a / 4);
// over b_k_re and b_l_re
IDD.set(k8+(j+1)*2, l8+(i+1)*2, I2ij + dk.u[i]*I1[j] + dl.u[j]*(I1[i] + dk.u[i]*I0) );
// over b_k_re and b_l_im
IDD.set(k8+(j+1)*2, l8+(i+1)*2+1, i_unit *( I2ij + dk.u[i]*I1[j] + dl.v[j]*(I1[i] + dk.u[i]*I0) ) );
// over b_k_im and b_l_re
if(k != l) IDD.set(k8+(j+1)*2+1, l8+(i+1)*2, i_unit1*( I2ij - dk.v[i]*I1[j] + dl.u[j]*(I1[i] - dk.v[i]*I0) ) );
// over b_k_im and b_l_im
IDD.set(k8+(j+1)*2+1, l8+(i+1)*2+1, I2ij - dk.v[i]*I1[j] + dl.v[j]*(I1[i] - dk.v[i]*I0) );
} // j
} // i
} // if(k <= l)
} // k
} // l
// Calculate matrix product IDYs_(k,q_j) = Ys_(k,l) * <phi_l | (phi_j)'_q_j>
for(qj=0; qj<nes8; qj++){
j = qj / 8;
int idx = qj*nes;
for(k=0;k<nes;k++) {
cdouble sum = 0.;
for(l=0;l<nes;l++)
if( Oflgs(l,j) ) sum += ID[idx+l] * Ys(k,l);
IDYs[idx+k] = sum;
}
}
// Calculate Norm-matrix
for(qi=0; qi<nes8; qi++){
i = qi / 8;
int idxqi = qi*nes;
Norms(qi,qi) = 0.; // zero diagonal elements
for(qj=qi+1; qj<nes8; qj++){
j = qj / 8;
int idxqj = qj*nes;
// Calculate matrix product sum = <(phi_i)'_q_i | phi_k> * IDYs_(k,q_j)
cdouble sum = 0.;
for(k=0;k<nes;k++)
if( Oflgs(i,k) )
sum += IDYs[idxqj+k] * conj(ID[idxqi+k]);
// Update norm-matrix taking into account its anti-symmetry
double a = Oflgs(i,j) ? // IDD = 0 for non-overlapping WPs
h_plank2 * imag( (sum - IDD(qi,qj))*Ys(j,i) ) :
h_plank2 * imag( sum*Ys(j,i) );
Norms(qi,qj) = a;
Norms(qj,qi) = -a;
} // qj
} // qi
# if 1
// transform norm matrix to the physical variables
for(i=0;i<nes;i++){
WavePacket wi=wp[s][i];
for(k=0;k<8;k++){
// iterator to list all N(8*i+k,*) with fixed 8*i+k
sqmatrix<double>::iterator mi=Norms.fix_first(8*i+k,0);
for(j=i ;j<nes;j++){ // TO DO: run this loop from i+1 and take simplectic form for (i,i) block
WavePacket wj=wp[s][j];
wj.int2phys_der< eq_second >(mi+8*j,mi+8*j,mi+8*j+3,mi+8*j+6,mi+8*j+7);
}
}// finished line of blocks from right
for(k= 8*i;k<nes8;k++){ // TO DO: run this loop from 8*i+8 and take simplectic form for (i,i) block
// iterator to list all N(8i+*,k) by fixed k
sqmatrix<double>::iterator mi=Norms.fix_second(8*i,k);
wi.int2phys_der< eq_second >(mi,mi,mi+3,mi+6,mi+7);
}// finished line of blocks from left
for(k=0;k<8;k++){ // filling the lower triangle according to antisymmetry
for(j=8*i+8;j<nes8;j++)
Norms(j,8*i+k)=-Norms(8*i+k,j);
}
}
# endif
# if 0
// transform norm matrix to the physical variables
for(i=0;i<nes;i++){
WavePacket wi=wp[s][i];
for(j=i;j<nes;j++){
WavePacket wj=wp[s][j];
for(k=0;k<8;k++){
// iterator to list all N(8*i+k,*) with fixed 8*i+k
sqmatrix<double>::iterator mi=Norms.fix_first(8*i+k,8*j);
wj.int2phys_der< eq_second >(mi,mi,mi+3,mi+6,mi+7);
}
for(k=0;k<8;k++){
// iterator to list all N(8*i+k,*) with fixed 8*i+k
sqmatrix<double>::iterator mi=Norms.fix_second(8*i,8*j+k);
wi.int2phys_der< eq_second >(mi,mi,mi+3,mi+6,mi+7);
}
if(i!=j){
for(int k1=0;k1<8;k1++){
for(int k2=0;k2<8;k2++)
Norms(8*j+k1,8*i+k2)=-Norms(8*i+k2,8*j+k1);
}
}
}
}
# endif
norm_matrix_state[s] = NORM_CALCULATED;
}
//e Norm matrix LU-factorization
void AWPMD::norm_factorize(int s) {
if( norm_matrix_state[s] != NORM_CALCULATED) norm_matrix(s);
int nes8 = ne[s]*8, info;
DGETRF(&nes8, &nes8, Norm[s].arr, &nes8, &ipiv[0], &info);
if(info < 0)
LOGERR(info,fmt("AWPMD.norm_factorize: call to DGETRF failed (exitcode %d)!",info),LINFO);
norm_matrix_state[s] = NORM_FACTORIZED;
}
//e Norm matrix inversion
void AWPMD::norm_invert(int s) {
if( norm_matrix_state[s] != NORM_FACTORIZED) norm_factorize(s);
int nes8 = ne[s]*8, info;
int IDD_size = (int)IDD.get_datasize(nes8);
DGETRI(&nes8, Norm[s].arr, &nes8, &ipiv[0], (double*)IDD.arr, &IDD_size, &info); // use IDD for work storage
if(info < 0)
LOGERR(info,fmt("AWPMD.norm_invert: call to DGETRI failed (exitcode %d)!",info),LINFO);
norm_matrix_state[s] = NORM_INVERTED;
}
//e Get the determinant of the norm-matrix for the particles with spin s
double AWPMD::norm_matrix_det(int s) {
double det = 1.;
int nes8 = ne[s]*8;
if(!nes8) return det;
if(norm_matrix_state[s] != NORM_FACTORIZED) norm_factorize(s);
sqmatrix<double>& Norms = Norm[s];
for(int i=0; i<nes8; i++)
det *= Norms(i, i); // product of the diagonal elements
return det;
}
//e Get the determinant logarithm of the norm-matrix for the particles with spin s
double AWPMD::norm_matrix_detl(int s) {
double detl = 0.;
int nes8 = ne[s]*8;
if(!nes8) return detl;
if(norm_matrix_state[s] != NORM_FACTORIZED) norm_factorize(s);
sqmatrix<double>& Norms = Norm[s];
for(int i=0; i<nes8; i++)
detl += log(fabs( Norms(i, i) )); // product of the diagonal elements
return detl;
}
double AWPMD::get_energy(){
double res=Eee + Ew;
for(int s=0;s<2;s++)
res+=Eei[s]+Ee[s];
if(calc_ii)
res+=Eii;
return res;
}
//e makes timestep of electronic component (NOT IMPLEMENTED)
int AWPMD::step(double dt){
return -1;
}
//e gets current electronic coordinates
int AWPMD::get_electrons(int spin, Vector_3P x, Vector_3P v, double* w, double* pw, double mass){
if(spin<0 || spin >1)
return -1; // invalid spin: return LOGERR(-1,fmt("AWPMD.get_electrons: invaid spin setting (%d)!",spin),LINFO);
if(mass<0)
mass=me;
for(int i=0;i<ni;i++){
w[i]=sqrt(3./(4*real(wp[spin][i].a)));
pw[i]=-2*w[i]*imag(wp[spin][i].a)/one_h; //pw[i]=-h_plank2*w[i]*imag(wp[spin][i].a);
x[i]=real(wp[spin][i].b)/(2*real(wp[spin][i].a));
v[i]=(pw[i]*x[i]/w[i] + imag(wp[spin][i].b)/one_h)/mass; //v[i]=(pw[i]*x[i]/w[i] + h_plank*imag(wp[spin][i].b))/m_electron;
}
return 1;
}
void AWPMD::clear_forces(int flag,Vector_3P fi, Vector_3P fe_x,
Vector_3P fe_p, double *fe_w, double *fe_pw, Vector_2P fe_c){
if(flag&0x1){
for(int i=0;i<ni;i++)
fi[i]=Vector_3(0.);
}
if(flag&0x4 && !(flag&0x10)){ // electron forces requested in physical representation
for(int s1=0;s1<2;s1++){ // clearing forces
for(int c1=0;c1<ne[s1];c1++){
fe_x[c1]=Vector_3(0,0,0);
fe_p[c1]=Vector_3(0,0,0);
fe_w[c1]=0;
fe_pw[c1]=0;
}
}
}
}
int AWPMD::interaction_ii(int flag,Vector_3P fi){
Eii=0.;
for(int i=0;i<ni;i++){
for(int j=i+1;j<ni;j++){
double M12e, M12f;
_mytie(M12e,M12f)=check_part1ii(i,j);
if(M12f){
Vector_3 rij=xi[i]-xi[j];
double r=rij.norm();
double dE=coul_pref*qi[i]*qi[j]/r;
Eii+=M12e*dE;
Eiip[i]+=0.5*M12e*dE;
Eiip[j]+=0.5*M12e*dE;
if(flag&0x3){ // ion forces needed
Vector_3 df=-M12f*dE*rij/(r*r);
fi[i]+=df;
fi[j]-=df;
}
}
}
}
return 1;
}

View File

@ -0,0 +1,658 @@
/*s***************************************************************************
*
* Copyright (c), Ilya Valuev 2005 All Rights Reserved.
*
* Author : Ilya Valuev, MIPT, Moscow, Russia
*
* Project : GridMD, ivutils
*
*****************************************************************************/
/*s****************************************************************************
* $Log: wpmd.h,v $
* Revision 1.4 2011/06/11 16:53:55 valuev
* sync with LAMMPS
*
* Revision 1.3 2011/06/11 16:45:23 morozov
* Fixed erf.c for Windows and Unix
*
* Revision 1.2 2011/06/10 19:25:17 morozov
* *** empty log message ***
*
* Revision 1.43 2011/06/10 19:20:53 valuev
* fixes
*
* Revision 1.42 2011/06/09 22:55:08 valuev
* norm matrices
*
* Revision 1.41 2011/06/07 19:58:42 valuev
* corrected partitions
*
* Revision 1.40 2011/06/07 17:43:00 valuev
* added Y derivatives
*
* Revision 1.39 2011/06/03 08:13:33 valuev
* added partitions to account for ghost atoms
*
* Revision 1.38 2011/06/02 22:11:17 morozov
* Compatibility with LAPACK library
*
* Revision 1.37 2011/06/01 23:45:35 valuev
* modified for LAMMPS compatibility
*
* Revision 1.36 2011/05/28 17:16:22 valuev
* fixed template<>, some fixes to UHF
*
* Revision 1.35 2011/05/25 21:30:48 morozov
* Compatibility with ICC 11.1
*
* Revision 1.34 2011/05/25 05:23:43 valuev
* fixed variable transformation for norm matrix
*
* Revision 1.33 2011/05/24 19:54:32 valuev
* fixed sqmatrix::iterator
*
* Revision 1.32 2011/05/21 23:06:49 valuev
* Norm matrix transform to pysical variables
*
* Revision 1.31 2011/05/20 21:39:49 valuev
* separated norm calculation
*
* Revision 1.30 2011/05/14 18:56:19 valuev
* derivative for ee split interactions
*
* Revision 1.29 2011/05/05 08:56:02 valuev
* working split wp version
*
* Revision 1.28 2011/05/04 16:48:52 valuev
* fixed syntax
*
* Revision 1.27 2011/05/04 09:04:48 valuev
* completed wp_split (except for ee forces)
*
* Revision 1.26 2011/04/29 03:07:20 valuev
* new split wp features
*
* Revision 1.25 2011/04/22 09:52:49 valuev
* working on split WP
*
* Revision 1.24 2011/04/20 08:43:09 valuev
* started adding split packet WPMD
*
* Revision 1.23 2010/09/03 12:17:48 morozov
* The order of parameters in Norm matrix is changed to mimic the order of the single WP parameter storage
*
* Revision 1.22 2009/08/27 00:01:36 morozov
* First working MPI equilibration
*
* Revision 1.21 2009/04/14 14:44:10 valuev
* fixed momentum calculation in hartree model, added "fix" constraint and model="hartree"
* to parameters
*
* Revision 1.20 2009/04/13 17:00:45 morozov
* Fixed norm-matrix ratio in AWPMC algorithm
*
* Revision 1.19 2009/04/06 17:00:28 morozov
* Fixed Hartree version of WPMC
*
* Revision 1.18 2009/04/01 10:06:37 valuev
* added Hartee factorization to AWPMD
*
* Revision 1.17 2009/03/24 16:10:05 morozov
* Fixed errors in Norm-matrix calculation related to PBC
*
* Revision 1.16 2009/03/17 11:40:04 morozov
* The prefactor of NormMatrix is corrected
*
* Revision 1.15 2008/07/23 16:42:12 valuev
* Added AWPMD Monte-Carlo
*
* Revision 1.14 2008/07/23 15:58:32 valuev
* *** empty log message ***
*
* Revision 1.13 2008/07/21 02:23:22 morozov
* *** empty log message ***
*
* Revision 1.12 2008/07/18 18:15:31 morozov
* *** empty log message ***
*
* Revision 1.11 2008/05/29 13:33:05 valuev
* VASP band structure
*
* Revision 1.10 2008/05/14 17:17:26 morozov
* Passed 2- and 3-electron test. Added Norm matrix.
*
* Revision 1.9 2008/05/05 17:29:32 morozov
* Fixed errors with Hermitian matrix indeces. Redesigned cVector_3 operations.
*
* Revision 1.8 2008/04/28 22:16:45 valuev
* restructured coulomb term
*
* Revision 1.7 2008/04/28 09:54:13 valuev
* corrected summation for Eee part
*
*******************************************************************************/
# ifndef WPMD_H
# define WPMD_H
/** @file wpmd.h
@brief Classes for Wave Packet Molecular Dynamics of two component plasma. */
# ifndef _USE_MATH_DEFINES
# define _USE_MATH_DEFINES
# endif
# include <complex>
# include <vector>
# include <cmath>
# include "logexc.h"
# include "cvector_3.h"
# include "pairhash.h"
# include "TCP/tcpdefs.h"
# include "wavepacket.h"
# include "erf.h"
# include "cerf.h"
using namespace std;
# include "lapack_inter.h"
typedef hmatrix<cdouble> chmatrix;
const cdouble i_unit = cdouble(0.,1.), i_unit1 = -i_unit;
const double h_plank2 = h_plank * 2.;
//cdouble ccerf(const cdouble &a);
//e calculates cerf(c*z)/z
inline cdouble cerf_div(const cdouble &z, const cdouble &c=i_unit){
if((fabs(real(z))+fabs(imag(z)))<1e-8)
return c*two_over_sqr_pi;
else
return cerf(z*c)/z;
}
//e calculates erf(c*z)/z
inline double erf_div(const double &z, double c=1){
if(fabs(z)<1e-8)
return c*two_over_sqr_pi;
else
return erf(z*c)/z;
}
template<class T1, class T2>
struct _myrefpair{
T1& first;
T2& second;
_myrefpair(T1& a, T2 &b):first(a),second(b){}
_myrefpair operator=(const pair<T1,T2> &other){
first=other.first;
second=other.second;
return *this;
}
};
template< class T1, class T2>
_myrefpair<T1,T2> _mytie(T1& var1, T2 &var2){
return _myrefpair<T1,T2>(var1, var2);
}
inline pair<double,double> operator*(const pair<double,double> &right, double left){
return make_pair(right.first*left,right.second*left);
}
// Auxilary class to handle the normalizing term derivatives
class NormDeriv
{
public:
cdouble l; // lambda = (f over a_re)
double m; // mu = (f over a_im) / i
cVector_3 u; // u = (f over b_re)
Vector_3 v; // v = (f over b_im) / i
NormDeriv() {}
NormDeriv(const WavePacket& wp) { set(wp); }
//e Create NormDeriv object and calculate the derivatived for the given WP
void set(const WavePacket& wp){
Vector_3 br = real(wp.b), bi = imag(wp.b);
double ar = real(wp.a), ai = imag(wp.a);
double i_2ar = 0.5 / ar, ai_ar = ai / ar;
v = (-i_2ar) * br;
m = v.norm2();
u = v * (i_unit1 * ai_ar) - wp.b * i_2ar;
l = (1.5*i_2ar + m) + cdouble(0.,2.) * ( (br*bi)*i_2ar*i_2ar - m*ai_ar );
}
};
inline NormDeriv conj(const NormDeriv& src){
NormDeriv dst;
dst.l = conj(src.l);
dst.m = -src.m;
dst.u = conj(src.u);
dst.v = - src.v;
return dst;
}
///\en Auxilary class to handle derivatives of overlaps
class OverlapDeriv{
public:
WavePacket w1, w2, w12;
NormDeriv d1, d2;
cdouble I0, I2;
cVector_3 I1;
cdouble bb_4a;
sqmatrix<cdouble> IDD;
OverlapDeriv():I0(0),I1(0),IDD(10){}
void set1(const WavePacket& w1_) {
w1=w1_;
d1.set(w1);
d1=conj(d1);
}
//e Create NormDeriv object and calculate the derivatived for the given WP
void set2(const WavePacket& w2_, const cdouble *I0_=NULL){
w2=w2_;
d2.set(w2);
w12=conj(w1)*w2;
if(!I0_)
I0 = w12.integral();
else
I0=*I0_;
I1 = w12.b * (I0 / w12.a / 2);
bb_4a = w12.b.norm2() / w12.a / 4;
I2 = I0 * (bb_4a + 1.5) / w12.a;
}
cdouble da2_re() const {
return (d2.l*I0 - I2);
}
cdouble da2_im() const {
return i_unit*(d2.m*I0 - I2);
}
cdouble da1_re() const {
return (d1.l*I0 - I2);
}
cdouble da1_im() const {
return -i_unit*(d1.m*I0 - I2);
}
cdouble db2_re(int i) const {
return d2.u[i]*I0 + I1[i];
}
cdouble db2_im(int i) const {
return i_unit*(d2.v[i]*I0 + I1[i]);
}
cdouble db1_re(int i) const {
return d1.u[i]*I0 + I1[i];
}
cdouble db1_im(int i) const {
return -i_unit*(d1.v[i]*I0 + I1[i]);
}
///\en Calculates derivative overlap matrix IDD
void calc_der_overlap(bool self=false, cdouble cc1=0., cdouble c2=0.);
};
class AWPMD {
//protected:
public:
int ne[2], ni;
int nwp[2]; ///<\en number of wavepackets (same as ne for unsplit version)
int nvar[2]; ///<\en full number of dynamic variables for each spin
chmatrix O[2], Y[2], Te[2], Tei[2];
smatrix<unsigned char> Oflg[2]; ///<\en equals 0 for non-overlaping packets
sqmatrix<double> Norm[2]; ///<\en Norm matrix
vector<WavePacket> wp[2]; ///<\en wave packets for electrons (spin up =0 and down =1)
vector<double> qe[2]; ///<\en electron charges
vector<double> qi; ///<\en ion charges
vector<Vector_3> xi; ///<\en ion coordinates
int pbc; ///<\en pbc flag
Vector_3 cell; ///<\en cell coordinates (L1,L2,L3)
double Lextra; ///<\en width PBC, unset if negative
double harm_w0_4;
double w0;
int calc_ii; ///<\en flag indicating whether to calculate ion-ion interaction
int norm_needed; ///<\en flag indicating whether to prepare norm matrix data in interaction function
enum {NORM_UNDEFINED, NORM_CALCULATED, NORM_FACTORIZED, NORM_INVERTED};
int norm_matrix_state[2];
// Arrays for temporal data
chmatrix IDD; // Second derivatives of the overlap integral (used in Norm matrix)
vector<cdouble> ID, IDYs; // First derivatives of the overlap integral (used in Norm matrix)
vector<int> ipiv; // The pivot indices array
recmatrix<cdouble> L[2]; ///<\en overlap derivative matrix for each spin
recmatrix<cdouble> M[2]; ///<\en 'normalized' overlap derivative matrix for each spin: M=YL
public:
enum {NONE=0, HARM, FIX, RELAX} constraint;
///\em Sets approximation level for quantum problem: \n
/// HARTREE Hartree product (no antisymmetrization) \n
/// DPRODUCT product of det0*det1 of antisymmetrized functions for spins 0, 1 \n
/// UHF unrestricted Hartree-Fock
enum APPROX {HARTREE, DPRODUCT, UHF } approx;
///\em Sets overlap matrix element to zero if the overlap norm is less than this value
double ovl_tolerance;
double Ee[2]; ///<\en electron kinetic energy for each spin
double Eei[2]; ///<\en electron-ion energy for each spin
double Eee, Ew; ///<\en electron-electron energy
double Eii; ///<\en ion-ion energy
double Edk; ///<\en sum of diagonal kinetic energy terms
double Edc; ///<\en sum of diagonal Coulomb energy terms
vector<double> Eep[2]; ///<\en per particle electron kinetic energy for each spin
vector<double> Eeip[2]; ///<\en per particle electron-ion energy for each spin
vector<double> Eeep[2]; ///<\en per particle electron-electron energy for each spin
vector<double> Ewp[2]; ///<\en per particle restrain energy for each spin
vector<double> Eiep; ///<\en per particle ion-electron energy
vector<double> Eiip; ///<\en per particle ion-ion energy
///\en \{ Conversion constants that depend on the unit system used (for LAMMPS compatibility).
/// Default is GRIDMD units. Change them according to your unit system.
double me; ///<\en electron mass (LAMMPS: me in the appropriate unit system)
double one_h; ///<\en inverse of Plancks constant (LAMMPS: conversion [(m*v)/h] to [distance] )
double h2_me; ///<\en Plancks constant squared divided by electron mass (LAMMPS: conversion [h^2/(m*r^2)] to [Energy] )
double coul_pref; ///<\en Coulomb prefactor (e2 for GRIDMD) (LAMMPS: conversion [q^2/r] to [Energy] )
/// \}
///\en 0 -- indicates that the inter-partition force should be full, and energy half,\n
/// 1 -- inter-partition force and energy counts one half (LAMMPS compatibility)
int newton_pair;
//int myid; ///<\en id for partitions
///\en Partition arrays storing the tags of particles. The initial tags should be >0.
/// If the tag stored is <0, then the particle is ghost with -tag.
/// partition1[2] is for ions, 0, 1 for each electron spin
vector<int> partition1[3];
//vector<int> partition2[3]; ///<\en 2 for ions
int tag_index(int i, int j){
return i==j ? -1 : (i>j ? (i-2)*(i-1)/2+j : (j-2)*(j-1)/2+i );
}
///\en 1 -- all my, -1 all other, 2 -- my mixed term, -2 -- other mixed term
int check_ee(int s1,int icj1,int ick2){
//printf(" (%d %d) ",partition1[s1][icj1],partition1[s1][ick2]);
int c1=(int)(partition1[s1][icj1]>0);
int c2=(int)(partition1[s1][ick2]>0);
int res;
if(c1!=c2){ // mixed
int tag1=abs(partition1[s1][icj1]);
int tag2=abs(partition1[s1][ick2]);
int num=tag_index(tag1-1,tag2-1);
if(num<0){ // compare wave packets
int cmp= s1<2 ?
wp[s1][icj1].compare(wp[s1][ick2],1e-15) :
compare_vec(xi[icj1],xi[ick2],1e-15);
if((cmp>0 && c1) || (cmp<0 && c2))
res= 2; // my mixed term
else
res= -2; // not my term
}
else // parity check
res=num%2 ? 2 : -2;
}
else if(c1)
res=1; // all my
else
res=-1; // all other
return res;
}
///\en Returns electron-electron inter-partition multipliers for energy (first) and force (second)
/// for a 4- and 2- electron additive terms (all inter-partition interactions are
/// calculated only once based on particle tags)
/// If force multiplier is zero, then the term may be omitted (energy will also be zero).
/// NOW ASSIGNS BASED ON THE FIRST PAIR ONLY
pair<double, double> check_part1(int s1,int icj1,int ick2, int s2=-1,int icj3=-1,int ick4=-1){
int res=check_ee(s1,icj1,ick2);
if(res==1){ // my term
//printf(" *\n");
return make_pair(1.,1.); // all at my partition
}
else if(res==-1){
//printf(" \n");
return make_pair(0.,0.); // all at other partition
}
else if(res==2){
//printf(" *\n");
return make_pair(1.,1.); // my inter-partition
}
else if(res==-2){
//printf(" \n");
return make_pair(0., newton_pair ? 0.0 : 1. ); // other inter-partition: must add force if newton comm is off
}
return make_pair(0.,0.); // nonsense
}
///\en Returns elctron-ion inter-partition multipliers for energy (first) and force (second)
/// for ion-electron additive terms (all inter-partition interactions are
/// calculated only once based on particle tags)
/// If force multiplier is zero, then the term may be omitted (energy will also be zero).
/// BASED ON ION ATTACHMENT
pair<double,double> check_part1ei(int s1,int icj1,int ick2, int ion){
//printf("%d ",partition1[2][ion]);
int ci=(int)(partition1[2][ion]>0);
if(!newton_pair){ // care about mixed terms
int cee=check_ee(s1,icj1,ick2);
if((cee==2 || cee==-2) || (ci && cee==-1) || (!ci && cee==1)) // all mixed variants
make_pair(0., 1. ); // other inter-partition: must add force if newton comm is off
}
if(ci){
//printf(" *\n");
return make_pair(1.,1.); // my term
}
else{
//printf(" \n");
return make_pair(0.,0.); // all at other partition
}
}
///\en Returns ion-ion inter-partition multipliers for energy (first) and force (second)
/// for ion-electron additive terms (all inter-partition interactions are
/// calculated only once based on particle tags)
/// If force multiplier is zero, then the term may be omitted (energy will also be zero).
pair<double,double> check_part1ii(int ion1, int ion2){
return check_part1(2,ion1,ion2);
}
AWPMD():pbc(0),Lextra(-1),constraint(NONE),newton_pair(1) {
nvar[0]=nvar[1]=ne[0]=ne[1]=ni=0;
norm_matrix_state[0] = norm_matrix_state[1] = NORM_UNDEFINED;
ovl_tolerance=0.;
approx = DPRODUCT;
me=m_electron;
one_h=1./h_plank;
h2_me=h_sq/me;
coul_pref=::coul_pref;
calc_ii=0;
norm_needed=0;
}
protected:
//e translates wp2 to the nearest image postion relative to wp1
//e gets the translation vector
Vector_3 move_to_image(const WavePacket &wp1, WavePacket &wp2) const {
Vector_3 r1=wp1.get_r();
Vector_3 r2=wp2.get_r();
Vector_3 dr=r2-r1;
Vector_3 ndr=dr.rcell(cell,pbc); // [0,L)
ndr=ndr.rcell1(cell,pbc); // [-L/2,L/2)
ndr-=dr;
wp2=wp2.translate(ndr); // wln.b=wln.b+ndr.a
return ndr;
}
//e gets the overlap packet taking PBC into account
WavePacket pbc_mul(const WavePacket &wp1, const WavePacket &wp2) const {
if(!pbc)
return wp1*conj(wp2);
Vector_3 r1=wp1.get_r();
Vector_3 r2=wp2.get_r();
Vector_3 dr=r2-r1; // distance
Vector_3 drn=dr.rcell1(cell,pbc); // distance within PBC
Vector_3 rtrans=drn-dr; // new location of wp2 according to PBC (nearest image)
WavePacket wpn=wp2.translate(rtrans);
wpn=wp1*(conj(wpn));
// reducing the result to elementary cell
//r1=wpn.get_r();
//r2=r1.rcell(cell,pbc);
//dr=r2-r1;
//wpn=wpn.translate(dr);
return wpn;
}
///\en resizes all internal arrays according to new electrons added
virtual void resize(int flag);
public:
///\en Prepares to setup a new system of particles using \ref add_ion() and add_electron().
/// There is no need to call this function when using
/// \ref set_electrons() and \ref set_ions() to setup particles.
virtual void reset(){
for(int s=0;s<2;s++){
nwp[s]=ne[s]=nvar[s]=0;
wp[s].clear();
qe[s].clear();
partition1[s].clear();
//partition2[s].clear();
}
partition1[2].clear();
ni=0;
xi.clear();
qi.clear();
}
//e sets Periodic Boundary Conditions
//e using bit flags: 0x1 -- PBC along X
//e 0x2 -- PBC along Y
//e 0x4 -- PBC along Z
//e cell specifies the lengths of the simulation box in all directions
//e if PBCs are used, the corresponding coordinates of electrons and ions
//e in periodic directions must be within the range [0, cell[per_dir])
//e @returns 1 if OK
int set_pbc(const Vector_3P pcell=NULL, int pbc_=0x7);
///\en Setup electrons: forms internal wave packet representations.
/// If PBCs are used the coords must be within a range [0, cell).
/// Default electron mass is AWPMD::me.
/// Default (q=NULL )electron charges are -1.
int set_electrons(int spin, int n, Vector_3P x, Vector_3P v, double* w, double* pw, double mass=-1, double *q=NULL);
//e setup ion charges and coordinates
//e if PBCs are used the coords must be within a range [0, cell)
int set_ions(int n, double* q, Vector_3P x);
///\en Adds an ion with charge q and position x,
/// \return id of the ion starting from 0
/// The tags must be nonzero, >0 for the local particle, <0 for ghost particle.
/// Unique particle id is abs(tag).
/// Default tag (0) means inserting the current particle id as local particle.
int add_ion(double q, const Vector_3 &x, int tag=0){
qi.push_back(q);
xi.push_back(x);
ni=(int)xi.size();
if(tag==0)
tag=ni;
partition1[2].push_back(tag);
return ni-1;
}
//e calculates interaction in the system of ni ions + electrons
//e the electonic subsystem must be previously setup by set_electrons, ionic by set_ions
//e the iterators are describing ionic system only
// 0x1 -- give back ion forces
// 0x2 -- add ion forces to the existing set
// 0x4 -- calculate derivatives for electronic time step (NOT IMPLEMENTED)
//e if PBCs are used the coords must be within a range [0, cell)
virtual int interaction(int flag=0, Vector_3P fi=NULL, Vector_3P fe_x=NULL,
Vector_3P fe_p=NULL, double *fe_w=NULL, double *fe_pw=NULL, Vector_2P fe_c=NULL);
//e same as interaction, but using Hartee factorization (no antisymmetrization)
virtual int interaction_hartree(int flag=0, Vector_3P fi=NULL, Vector_3P fe_x=NULL,
Vector_3P fe_p=NULL, double *fe_w=NULL, double *fe_pw=NULL, Vector_2P fe_c=NULL);
///\en Calculates ion-ion interactions and updates Eii and ion forces if requested. This function
/// is called form intaraction() and interaction_hartree if calc_ii is set.
virtual int interaction_ii(int flag,Vector_3P fi=NULL);
//e Calculates Norm matrix
//e The result is saved in AWPMD::Norm[s]
void norm_matrix(int s);
//e Performs LU-factorization of the Norm matrix
//e AWPMD::Norm[s] is replaced by the LU matrix
void norm_factorize(int s);
//e Invert Norm matrix
//e AWPMD::Norm[s] is replaced by the inverted matrix
void norm_invert(int s);
//e Get the determinant of the norm-matrix for the particles with spin s
double norm_matrix_det(int s);
//e Get the determinant logarithm of the norm-matrix for the particles with spin s
double norm_matrix_detl(int s);
double get_energy();
//e makes timestep of electronic component (NOT IMPLEMENTED)
int step(double dt);
///\en Gets current electronic coordinates.
/// Transforms the momenta to velocity v according to mass setting (-1 means me)
int get_electrons(int spin, Vector_3P x, Vector_3P v, double* w, double* pw, double mass=-1);
void set_harm_constr(double w0) {
constraint = HARM;
harm_w0_4 = h_sq*9./(8.*m_electron)/(w0*w0*w0*w0);
}
void set_fix_constr(double w0_) {
constraint = FIX;
w0 = w0_;
}
///\en Prepares force arrays according to \a flag setting for interaction()
virtual void clear_forces(int flagi,Vector_3P fi, Vector_3P fe_x,
Vector_3P fe_p, double *fe_w, double *fe_pw, Vector_2P fe_c=NULL);
///\en Creates wave packet acording to the given physical parameters.
/// The function may change its arguments by applying existing constraints!
/// Default mass (-1) is the electron mass AWPMD::me.
WavePacket create_wp(Vector_3 &x, Vector_3 &v, double &w, double &pw, double mass=-1);
};
# endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,204 @@
# ifndef WPMD_SPLIT_H
# define WPMD_SPLIT_H
/** @file wpmd.h
@brief Representation of electrons by multiple wave packets within WPMD */
/*s****************************************************************************
* $Log: wpmd_split.h,v $
* Revision 1.2 2011/06/11 16:53:55 valuev
* sync with LAMMPS
*
* Revision 1.1 2011/06/10 17:15:07 morozov
* First Windows project with the correct directory structure
*
* Revision 1.17 2011/06/09 22:55:08 valuev
* norm matrices
*
* Revision 1.16 2011/06/07 19:58:42 valuev
* corrected partitions
*
* Revision 1.15 2011/06/07 17:43:00 valuev
* added Y derivatives
*
* Revision 1.14 2011/06/03 08:13:33 valuev
* added partitions to account for ghost atoms
*
* Revision 1.13 2011/06/01 23:45:35 valuev
* modified for LAMMPS compatibility
*
* Revision 1.12 2011/05/28 17:16:22 valuev
* fixed template<>, some fixes to UHF
*
* Revision 1.11 2011/05/27 08:43:52 valuev
* fixed split packet antisymmetrized version
*
* Revision 1.10 2011/05/25 05:23:43 valuev
* fixed variable transformation for norm matrix
*
* Revision 1.9 2011/05/24 19:54:32 valuev
* fixed sqmatrix::iterator
*
* Revision 1.8 2011/05/20 21:39:49 valuev
* separated norm calculation
*
* Revision 1.7 2011/05/14 18:56:19 valuev
* derivative for ee split interactions
*
* Revision 1.6 2011/05/05 08:56:02 valuev
* working split wp version
*
* Revision 1.5 2011/05/04 16:48:52 valuev
* fixed syntax
*
* Revision 1.4 2011/05/04 09:04:48 valuev
* completed wp_split (except for ee forces)
*
* Revision 1.3 2011/04/22 09:54:24 valuev
* working on split WP
*
* Revision 1.1 2011/04/20 08:43:09 valuev
* started adding split packet WPMD
*
*******************************************************************************/
#include "wpmd.h"
class AWPMD_split: public AWPMD {
protected:
int s_add, spl_add;
public:
vector<Vector_2> split_c[2]; ///<\en split coefficients for electrons (c_re, c_im) or (psi,phi) depending on the norm mode
vector<int> nspl[2]; ///<\en number of wave packets for each electron (size is ne[i])
vector<double> wf_norm[2]; ///<\en norms for each electron
vector<double> wf_norm_der[2]; ///<\en norm derivative
vector<cdouble> ovl_der[2]; ///<\en overlap derivative: \<psi|psi'\>
vector<double> E_der[2]; ///<\en energy derivative with respect to {a,b} coordinates
vector< cdouble > Lh[2]; ///<\en Substitute for L in Hartree case: block matrices 1x(10*nspl[i])
vector< sqmatrix<double> > Normh[2]; ///<\en Substitute for Norm in Hartree case: block matrices
///\en resizes all internal arrays according to new electrons (wavepackets) added
virtual void resize(int flag);
public:
AWPMD_split():s_add(0),spl_add(0){}
///\en Prepares to setup a new system of particles using \ref add_ion(),
/// \ref add_electron() and \ref add_split().
/// There is no need to call this function when using
/// \ref set_electrons() and \ref set_ions() to setup particles.
virtual void reset(){
for(int s=0;s<2;s++){
split_c[s].clear();
nspl[s].clear();
}
s_add=0;
spl_add=0;
AWPMD::reset();
}
///\en Setup electrons: forms internal wave packet representations.
/// If PBCs are used the coords must be within the range [0, cell)
/// the \a splits array defines the number of wavepackets required for each electron
/// the data for splits should be placed in the corresponding data arrays
/// \a c array contains the splits mixing coefficints
/// \a n is the number of electrons of a given spin component
/// Electron velocity v is multiplied by mass to obtain momentum.
/// Default mass (-1) means me.
/// Electronic charges q are -1 by default (when q=NULL), otherwise the charges are assigned for each split
int set_electrons(int s, int nel, Vector_3P x, Vector_3P v, double* w, double* pw, Vector_2 *c, int *splits, double mass=-1, double *q=NULL);
///\en Starts adding new electron: continue with \ref add_split functions.
int add_electron(int s){
if(s < 0 || s > 1)
return LOGERR(-1,fmt("AWPMD_split.add_electron: invaid spin setting (%d)!",s),LINFO);
s_add=s;
spl_add=0;
return ne[s_add];
}
///\en Adds a new split to current electron.
/// May change the arguments according to the constraints set.
/// \return global id of the wavepacket (starting from 0 for each spin s)
/// Electron velocity v is multiplied by mass to obtain momentum.
/// Default mass (-1) means me.
/// The tags must be nonzero, >0 for the local particle, <0 for ghost particle.
/// Unique particle id is abs(tag).
/// Default tag (0) means inserting the current particle id as local particle.
int add_split(Vector_3 &x, Vector_3 &v, double &w, double &pw, Vector_2 &c, double mass=-1, double q=-1., int tag=0);
///\en gets current electronic coordinates, and (optionally) number of wave packets for each electron
int get_electrons(int spin, Vector_3P x, Vector_3P v, double* w, double* pw, cdouble *c, int *splits=NULL, double mass=-1);
void eterm_deriv(int ic1,int s1, int c1,int k1,int ic2,int s2, int c2,int j2,cdouble pref,
const OverlapDeriv &o,cdouble v,cdouble dv_aj_conj,
cdouble dv_ak,cVector_3 dv_bj_conj, cVector_3 dv_bk);
///\en adds the derivatives of Y for the term v*Y[s](c2,c1)
void y_deriv(cdouble v,int s, int c2, int c1);
///\en Calculates block norms an derivatives
void calc_norms(int flag);
///\en Prepares force arrays according to \a flag setting for interaction()
virtual void clear_forces(int flagi,Vector_3P fi, Vector_3P fe_x,
Vector_3P fe_p, double *fe_w, double *fe_pw, Vector_2P fe_c);
///\en Calcualtes the overlap between two electrons taking all split WPs into account.
/// Norms must be pre-calculated.
cdouble overlap(int ic1, int s1, int c1,int ic2, int s2, int c2);
//e same as interaction, but using Hartee factorization (no antisymmetrization)
int interaction_hartree(int flag=0, Vector_3P fi=NULL, Vector_3P fe_x=NULL,
Vector_3P fe_p=NULL, double *fe_w=NULL, double *fe_pw=NULL, Vector_2P fe_c=NULL);
///\en Calculates interaction in the system of ni ions + electrons
/// the electonic subsystem must be previously setup by set_electrons, ionic by set_ions
/// 0x1 -- give back ion forces \n
/// 0x2 -- add ion forces to the existing set \n
/// 0x4 -- calculate electronic forces \n
/// 0x8 -- add electronic forces to the existing arrays \n
/// 0x10 -- calculate internal electronic derivatives only: \n
/// will not update electronic force arrays, which may be NULL, \n
/// the forces may be obtained then using \ref get_el_forces() for all WPs \n
/// or separately for each WP using \ref get_wp_force()
/// if PBCs are used the coords must be within a range [0, cell)
int interaction(int flag=0, Vector_3P fi=NULL, Vector_3P fe_x=NULL,
Vector_3P fe_p=NULL, double *fe_w=NULL, double *fe_pw=NULL, Vector_2P fe_c=NULL);
///\en Get electronic forcess in the arrays provided, using calculated internal representation
/// Valid flag settings are:\n
/// 0x4 -- overwrite existing forces \n
/// 0x8 -- add electronic forces to the existing arrays \n
void get_el_forces(int flag, Vector_3P fe_x,
Vector_3P fe_p, double *fe_w, double *fe_pw, Vector_2P fe_c);
void get_wp_force(int s, int ispl, Vector_3P fe_x, Vector_3P fe_p, double *fe_w, double *fe_pw, Vector_2P fe_c){
WavePacket wk=wp[s][ispl];
int indw1=8*ispl;
int indn1=(nvar[s]/10)*8+2*ispl;
wk.int2phys_der< eq_minus_second >(E_der[s].begin()+indw1,(double *)fe_x,(double *)fe_p,fe_w,fe_pw,1./one_h);
*fe_c=-Vector_2(E_der[s][indn1],E_der[s][indn1+1]);
}
};
# endif