-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathiprof.cpp
More file actions
193 lines (156 loc) · 3.78 KB
/
iprof.cpp
File metadata and controls
193 lines (156 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include "cellFile.h"
#include "input.h"
#include "iprof.h"
#include "math.h"
void Iprofile::Routine()
{
TITLE("Iprof","Routine");
// cel_in : input geometry file
CellFile cel_in;
cel_in.file_name = INPUT.geo_in;
CellFile::ReadGeometry( cel_in );
// the original method
// cal( cel_in );
// new method to calcultae the ionic density profile
// 2014-03-09
cal_gauss( cel_in );
return;
}
void Iprofile::cal_gauss( const Cell &cel)
{
TITLE("Iprofile","cal_gauss");
// natom / v_liquid
double norm1 = cel.a1.norm();
double norm2 = cel.a2.norm();
double norm3 = cel.a3.norm();
assert(INPUT.iprof_nr>0);
// assume 'a3' is the longest axis
const int nr = INPUT.iprof_nr;
double dr = norm3/(double)nr;
// allocate iprof
double* r = new double[nr];
double* iprof = new double[nr];
double* iprof_unit = new double[nr];
for(int ir=0; ir<nr; ++ir)
{
r[ir] = (ir+1)*dr;
iprof[ir] = 0.0;
iprof_unit[ir] = 0.0;
}
// search for each atom
assert( INPUT.iprof_b > 0.0 );
double b = INPUT.iprof_b; // coefficient
cout << " coefficeint for gaussian broadening is " << b << endl;
double b2 = b * b;
double a = 1.0/sqrt(3.1415926)/b;
int iat=0;
for(int it=0; it<INPUT.ntype; ++it)
{
for(int ia=0; ia<cel.atom[it].na; ++ia)
{
double posz = cel.atom[it].pos[ia].z;
while( posz >= norm3 )
{
posz -= norm3;
}
while( posz < 0 )
{
posz += norm3;
}
// calculate the gaussian distribution
for(int ir=0; ir<nr; ++ir)
{
double dz = posz - r[ir];
double dz2 = dz * dz;
double Gauss = exp( -dz2/b2 ) * a;
iprof[ir] += Gauss;
}
}
}
// unit is made for ionic density profile
double sum = 0.0;
double* rab = new double[nr];
for(int ir=0; ir<nr; ++ir)
{
rab[ir] = dr;
}
// the mesh number should be odd
if(nr%2==0)
{
Math::Simpson_Integral(nr-1, iprof, rab, sum);
}
else
{
Math::Simpson_Integral(nr, iprof, rab, sum);
}
cout << " sum from ionic density profile = " << sum << endl;
assert( sum > 0.0 );
// unit is made
for(int ir=0; ir<nr; ++ir)
{
iprof_unit[ir] = iprof[ir]/sum;
}
// print data
cout << " Print data to " << INPUT.geo_out << endl;
ofstream ofs(INPUT.geo_out.c_str());
for(int ir=0; ir<nr; ++ir)
{
ofs << r[ir] << " " << iprof[ir] << " " << iprof_unit[ir] << endl;
}
ofs.close();
// finish
delete[] iprof;
delete[] iprof_unit;
delete[] r;
delete[] rab;
return;
}
void Iprofile::cal( const Cell &cel )
{
TITLE("Iprofile","cal");
// natom / v_liquid
// ionic density
double rho0 = 0.0508791207;
double norm1 = cel.a1.norm();
double norm2 = cel.a2.norm();
double norm3 = cel.a3.norm();
assert(INPUT.iprof_nr>0);
// assume 'a3' is the longest axis
double dr = norm3/(double)INPUT.iprof_nr;
double v_each_z = norm1 * norm2 * dr;
double *nat_z = new double[INPUT.iprof_nr+1];
for(int i=0; i<INPUT.iprof_nr; ++i) nat_z[i]=0.0;
cout << " Length of Lattice Vectors : " << norm1 << " " << norm2 << " " << norm3 << endl;
cout << " dimension of nat_z along z : " << INPUT.iprof_nr << " dr = " << dr << endl;
int iat=0;
for(int it=0; it<INPUT.ntype; ++it)
{
for(int ia=0; ia<cel.atom[it].na; ++ia)
{
int which = (int)(cel.atom[it].pos[ia].z/dr);
// consider periodic boundary condition
if(which >= (INPUT.iprof_nr+1) )
{
which -= INPUT.iprof_nr;
cout << " WARNING! atom out of z range (>0)." << endl;
}
else if(which < 0)
{
which += INPUT.iprof_nr;
cout << " WARNING! atom out of z range (<0)." << endl;
}
nat_z[which]+=1.0;
++iat;
}
}
cout << " Total atom number is " << iat << endl;
cout << " Print data to " << INPUT.geo_out << endl;
ofstream ofs(INPUT.geo_out.c_str());
for(int i=0; i<INPUT.iprof_nr; ++i)
{
ofs << dr*(i+1) << " " << nat_z[i] << " " << nat_z[i]/v_each_z/rho0 << endl;
}
ofs.close();
delete[] nat_z;
return;
}