Skip to content

Commit 83709c9

Browse files
authored
Feature: Implement Xu-Wang-Ma KEDF (#6359)
* Feature: Implement Xu-Wang-Ma KEDF * Test: Add two integrate tests for XWM KEDF * Doc: Update document of XWM KEDF. * Fix: update kedf_manager.h
1 parent 3bb2226 commit 83709c9

File tree

22 files changed

+654
-23
lines changed

22 files changed

+654
-23
lines changed

docs/advanced/input_files/input-main.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@
215215
- [of\_wt\_rho0](#of_wt_rho0)
216216
- [of\_hold\_rho0](#of_hold_rho0)
217217
- [of\_lkt\_a](#of_lkt_a)
218+
- [of\_xwm\_rho\_ref](#of_xwm_rho_ref)
219+
- [of\_xwm\_kappa](#of_xwm_kappa)
218220
- [of\_read\_kernel](#of_read_kernel)
219221
- [of\_kernel\_file](#of_kernel_file)
220222
- [of\_full\_pw](#of_full_pw)
@@ -2277,6 +2279,7 @@ Warning: this function is not robust enough for the current version. Please try
22772279
- **vw**: von Weizsäcker.
22782280
- **tf+**: TF $\rm{\lambda}$ vW, the parameter $\rm{\lambda}$ can be set by `of_vw_weight`.
22792281
- **lkt**: Luo-Karasiev-Trickey.
2282+
- **xwm**: Xu-Wang-Ma
22802283

22812284
Machine learning (ML) based functionals:
22822285
- **ml**: ML-based KEDF allows for greater flexibility, enabling users to set related ML model parameters themselves. see [ML-KEDF: machine learning based kinetic energy density functional for OFDFT](#ml-kedf-machine-learning-based-kinetic-energy-density-functional-for-ofdft).
@@ -2323,14 +2326,14 @@ Warning: this function is not robust enough for the current version. Please try
23232326
### of_tf_weight
23242327

23252328
- **Type**: Real
2326-
- **Availability**: OFDFT with `of_kinetic=tf, tf+, wt`
2329+
- **Availability**: OFDFT with `of_kinetic=tf, tf+, wt, xwm`
23272330
- **Description**: Weight of TF KEDF (kinetic energy density functional).
23282331
- **Default**: 1.0
23292332

23302333
### of_vw_weight
23312334

23322335
- **Type**: Real
2333-
- **Availability**: OFDFT with `of_kinetic=vw, tf+, wt, lkt`
2336+
- **Availability**: OFDFT with `of_kinetic=vw, tf+, wt, lkt, xwm`
23342337
- **Description**: Weight of vW KEDF (kinetic energy density functional).
23352338
- **Default**: 1.0
23362339

@@ -2372,6 +2375,20 @@ Warning: this function is not robust enough for the current version. Please try
23722375
- **Description**: Parameter a of LKT KEDF (kinetic energy density functional).
23732376
- **Default**: 1.3
23742377

2378+
### of_xwm_rho_ref
2379+
2380+
- **Type**: Real
2381+
- **Availability**: OFDFT with `of_kinetic=xwm`
2382+
- **Description**: Reference charge density for XWM kinetic energy functional. If set to 0, the program will use average charge density.
2383+
- **Default**: 0.0
2384+
2385+
### of_xwm_kappa
2386+
2387+
- **Type**: Real
2388+
- **Availability**: OFDFT with `of_kinetic=xwm`
2389+
- **Description**: Parameter $\kappa$ for XWM kinetic energy functional. See PHYSICAL REVIEW B 100, 205132 (2019) for optimal values.
2390+
- **Default**: 0.0
2391+
23752392
### of_read_kernel
23762393

23772394
- **Type**: Boolean

source/Makefile.Objects

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ OBJS_HAMILT=hamilt_pw.o\
345345
OBJS_HAMILT_OF=kedf_tf.o\
346346
kedf_vw.o\
347347
kedf_wt.o\
348+
kedf_xwm.o\
348349
kedf_lkt.o\
349350
kedf_manager.o\
350351

source/module_parameter/input_parameter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ struct Input_para
206206
///< filled from file of_kernel_file, not from
207207
///< formula. Only usable for WT KEDF.
208208
std::string of_kernel_file = "WTkernel.txt"; ///< The name of WT kernel file.
209+
double of_xwm_kappa = 0.0; ///< The parameter kappa of XWM KEDF
210+
double of_xwm_rho_ref = 0.0; ///< The reference density of XWM KEDF
209211

210212
// ML KEDF, sunliang added on 2022-11-07
211213
bool of_ml_gene_data = false; ///< Generate training data or not

source/source_io/read_input_item_ofdft.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ void ReadInput::item_ofdft()
1818
}
1919
#endif
2020
if (para.input.of_kinetic != "tf" && para.input.of_kinetic != "vw" && para.input.of_kinetic != "wt"
21-
&& para.input.of_kinetic != "lkt" && para.input.of_kinetic != "tf+"
21+
&& para.input.of_kinetic != "xwm" && para.input.of_kinetic != "lkt" && para.input.of_kinetic != "tf+"
2222
&& para.input.of_kinetic != "ml" && para.input.of_kinetic != "mpn" && para.input.of_kinetic != "cpn5")
2323
{
24-
ModuleBase::WARNING_QUIT("ReadInput", "of_kinetic must be tf, vw, tf+, wt, lkt, ml, mpn, or cpn5");
24+
ModuleBase::WARNING_QUIT("ReadInput", "of_kinetic must be tf, vw, tf+, wt, xwm, lkt, ml, mpn, or cpn5");
2525
}
2626
};
2727
item.reset_value = [](const Input_Item& item, Parameter& para) {
@@ -209,6 +209,18 @@ void ReadInput::item_ofdft()
209209
read_sync_string(input.of_kernel_file);
210210
this->add_item(item);
211211
}
212+
{
213+
Input_Item item("of_xwm_kappa");
214+
item.annotation = "The parameter kappa of XWM KEDF";
215+
read_sync_double(input.of_xwm_kappa);
216+
this->add_item(item);
217+
}
218+
{
219+
Input_Item item("of_xwm_rho_ref");
220+
item.annotation = "The reference density of XWM KEDF";
221+
read_sync_double(input.of_xwm_rho_ref);
222+
this->add_item(item);
223+
}
212224
{
213225
Input_Item item("of_ml_gene_data");
214226
item.annotation = "Generate training data or not";

source/source_io/test/read_input_ptest.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,8 @@ TEST_F(InputParaTest, ParaRead)
366366
EXPECT_EQ(param.inp.of_full_pw_dim, 0);
367367
EXPECT_FALSE(param.inp.of_read_kernel);
368368
EXPECT_EQ(param.inp.of_kernel_file, "WTkernel.txt");
369+
EXPECT_DOUBLE_EQ(param.inp.of_xwm_kappa, 1.);
370+
EXPECT_DOUBLE_EQ(param.inp.of_xwm_rho_ref, 1.);
369371
EXPECT_EQ(param.inp.device, "cpu");
370372
EXPECT_NEAR(param.inp.force_thr_ev, 0.025711245953622324, 1e-8);
371373
EXPECT_DOUBLE_EQ(param.globalv.hubbard_u[0], 0);

source/source_io/test/support/INPUT

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ of_full_pw 0 #If set to 1, ecut will be ignored when collect
370370
of_full_pw_dim 0 #If of_full_pw = true, dimention of FFT is testricted to be (0) either odd or even; (1) odd only; (2) even only
371371
of_read_kernel 0 #If set to 1, the kernel of WT KEDF will be filled from file of_kernel_file, not from formula. Only usable for WT KEDF
372372
of_kernel_file WTkernel.txt #The name of WT kernel file.
373+
of_xwm_kappa 1 #The parameter kappa of XWM KEDF
374+
of_xwm_rho_ref 1 #The reference density of XWM KEDF
373375

374376
#Parameters (20.dft+u)
375377
dft_plus_u 0 #true:DFT+U correction; false: standard DFT calcullation(default)

source/source_pw/module_ofdft/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ list(APPEND hamilt_ofdft_srcs
22
kedf_tf.cpp
33
kedf_vw.cpp
44
kedf_wt.cpp
5+
kedf_xwm.cpp
56
kedf_lkt.cpp
67
kedf_manager.cpp
78
of_stress_pw.cpp

source/source_pw/module_ofdft/kedf_manager.cpp

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ void KEDF_Manager::init(
1818
{
1919
this->of_kinetic_ = inp.of_kinetic;
2020

21-
//! Thomas-Fermi (TF) KEDF, TF+ KEDF, and Want-Teter (WT) KEDF
21+
//! Thomas-Fermi (TF) KEDF, TF+ KEDF, Want-Teter (WT) KEDF, and XWM KEDF
2222
if (this->of_kinetic_ == "tf"
2323
|| this->of_kinetic_ == "tf+"
2424
|| this->of_kinetic_ == "wt"
25-
|| this->of_kinetic_ == "ml")
25+
|| this->of_kinetic_ == "ml"
26+
|| this->of_kinetic_ == "xwm")
2627
{
2728
if (this->tf_ == nullptr)
2829
{
@@ -31,9 +32,9 @@ void KEDF_Manager::init(
3132
this->tf_->set_para(pw_rho->nrxx, dV, inp.of_tf_weight);
3233
}
3334

34-
//! vW, TF+, WT, and LKT KEDFs
35+
//! vW, TF+, WT, XWM, and LKT KEDFs
3536
if (this->of_kinetic_ == "vw" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt"
36-
|| this->of_kinetic_ == "lkt" || this->of_kinetic_ == "ml")
37+
|| this->of_kinetic_ == "xwm" || this->of_kinetic_ == "lkt" || this->of_kinetic_ == "ml")
3738
{
3839
if (this->vw_ == nullptr)
3940
{
@@ -62,6 +63,17 @@ void KEDF_Manager::init(
6263
pw_rho);
6364
}
6465

66+
//! Xu-Wang-Ma KEDF
67+
if (this->of_kinetic_ == "xwm")
68+
{
69+
if (this->xwm_ == nullptr)
70+
{
71+
this->xwm_ = new KEDF_XWM();
72+
}
73+
this->xwm_->set_para(dV, inp.of_xwm_rho_ref, inp.of_xwm_kappa, nelec,
74+
inp.of_tf_weight, inp.of_vw_weight, pw_rho);
75+
}
76+
6577
//! LKT KEDF
6678
if (this->of_kinetic_ == "lkt")
6779
{
@@ -108,14 +120,18 @@ void KEDF_Manager::get_potential(
108120
if (PARAM.inp.of_ml_local_test) this->ml_->localTest(prho, pw_rho);
109121
#endif
110122

111-
if (this->of_kinetic_ == "tf" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt")
123+
if (this->of_kinetic_ == "tf" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt" || this->of_kinetic_ == "xwm")
112124
{
113125
this->tf_->tf_potential(prho, rpot);
114126
}
115127
if (this->of_kinetic_ == "wt")
116128
{
117129
this->wt_->wt_potential(prho, pw_rho, rpot);
118130
}
131+
if (this->of_kinetic_ == "xwm")
132+
{
133+
this->xwm_->xwm_potential(prho, pw_rho, rpot);
134+
}
119135
if (this->of_kinetic_ == "lkt")
120136
{
121137
this->lkt_->lkt_potential(prho, pw_rho, rpot);
@@ -138,7 +154,7 @@ void KEDF_Manager::get_potential(
138154
}
139155

140156
if (this->of_kinetic_ == "vw" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt"
141-
|| this->of_kinetic_ == "lkt" || this->of_kinetic_ == "ml")
157+
|| this->of_kinetic_ == "xwm" || this->of_kinetic_ == "lkt" || this->of_kinetic_ == "ml")
142158
{
143159
this->vw_->vw_potential(pphi, pw_rho, rpot);
144160
}
@@ -154,13 +170,13 @@ double KEDF_Manager::get_energy()
154170
{
155171
double kinetic_energy = 0.0;
156172

157-
if (this->of_kinetic_ == "tf" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt")
173+
if (this->of_kinetic_ == "tf" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt"|| this->of_kinetic_ == "xwm")
158174
{
159175
kinetic_energy += this->tf_->tf_energy;
160176
}
161177

162178
if (this->of_kinetic_ == "vw" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt"
163-
|| this->of_kinetic_ == "lkt" || this->of_kinetic_ == "ml")
179+
|| this->of_kinetic_ == "xwm" || this->of_kinetic_ == "lkt" || this->of_kinetic_ == "ml")
164180
{
165181
kinetic_energy += this->vw_->vw_energy;
166182
}
@@ -170,6 +186,11 @@ double KEDF_Manager::get_energy()
170186
kinetic_energy += this->wt_->wt_energy;
171187
}
172188

189+
if (this->of_kinetic_ == "xwm")
190+
{
191+
kinetic_energy += this->xwm_->xwm_energy;
192+
}
193+
173194
if (this->of_kinetic_ == "lkt")
174195
{
175196
kinetic_energy += this->lkt_->lkt_energy;
@@ -210,19 +231,23 @@ void KEDF_Manager::get_energy_density(
210231
rtau[0][ir] = 0.0;
211232
}
212233

213-
if (this->of_kinetic_ == "tf" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt")
234+
if (this->of_kinetic_ == "tf" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt" || this->of_kinetic_ == "xwm")
214235
{
215236
this->tf_->tau_tf(prho, rtau[0]);
216237
}
217238
if (this->of_kinetic_ == "vw" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt"
218-
|| this->of_kinetic_ == "lkt")
239+
|| this->of_kinetic_ == "xwm" || this->of_kinetic_ == "lkt")
219240
{
220241
this->vw_->tau_vw(pphi, pw_rho, rtau[0]);
221242
}
222243
if (this->of_kinetic_ == "wt")
223244
{
224245
this->wt_->tau_wt(prho, pw_rho, rtau[0]);
225246
}
247+
if (this->of_kinetic_ == "xwm")
248+
{
249+
this->xwm_->tau_xwm(prho, pw_rho, rtau[0]);
250+
}
226251
if (this->of_kinetic_ == "lkt")
227252
{
228253
this->lkt_->tau_lkt(prho, pw_rho, rtau[0]);
@@ -255,14 +280,14 @@ void KEDF_Manager::get_stress(
255280
}
256281
}
257282

258-
if (this->of_kinetic_ == "tf" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt")
283+
if (this->of_kinetic_ == "tf" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt" || this->of_kinetic_ == "xwm")
259284
{
260285
this->tf_->get_stress(omega);
261286
kinetic_stress_ += this->tf_->stress;
262287
}
263288

264289
if (this->of_kinetic_ == "vw" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt"
265-
|| this->of_kinetic_ == "lkt")
290+
|| this->of_kinetic_ == "xwm" || this->of_kinetic_ == "lkt")
266291
{
267292
this->vw_->get_stress(pphi, pw_rho);
268293
kinetic_stress_ += this->vw_->stress;
@@ -274,6 +299,12 @@ void KEDF_Manager::get_stress(
274299
kinetic_stress_ += this->wt_->stress;
275300
}
276301

302+
if (this->of_kinetic_ == "xwm")
303+
{
304+
this->xwm_->get_stress(prho, pw_rho, PARAM.inp.of_vw_weight);
305+
kinetic_stress_ += this->xwm_->stress;
306+
}
307+
277308
if (this->of_kinetic_ == "lkt")
278309
{
279310
this->lkt_->get_stress(prho, pw_rho);
@@ -290,13 +321,13 @@ void KEDF_Manager::record_energy(
290321
std::vector<double> &energies_Ry
291322
)
292323
{
293-
if (this->of_kinetic_ == "tf" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt")
324+
if (this->of_kinetic_ == "tf" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt" || this->of_kinetic_ == "xwm")
294325
{
295326
titles.push_back("TF KEDF");
296327
energies_Ry.push_back(this->tf_->tf_energy);
297328
}
298329
if (this->of_kinetic_ == "vw" || this->of_kinetic_ == "tf+" || this->of_kinetic_ == "wt"
299-
|| this->of_kinetic_ == "lkt" || this->of_kinetic_ == "ml")
330+
|| this->of_kinetic_ == "xwm" || this->of_kinetic_ == "lkt" || this->of_kinetic_ == "ml")
300331
{
301332
titles.push_back("vW KEDF");
302333
energies_Ry.push_back(this->vw_->vw_energy);
@@ -306,6 +337,11 @@ void KEDF_Manager::record_energy(
306337
titles.push_back("WT KEDF");
307338
energies_Ry.push_back(this->wt_->wt_energy);
308339
}
340+
if (this->of_kinetic_ == "xwm")
341+
{
342+
titles.push_back("XWM KEDF");
343+
energies_Ry.push_back(this->xwm_->xwm_energy);
344+
}
309345
if (this->of_kinetic_ == "lkt")
310346
{
311347
titles.push_back("LKT KEDF");

source/source_pw/module_ofdft/kedf_manager.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
#include "module_parameter/parameter.h"
55
#include "source_basis/module_pw/pw_basis.h"
66
#include "source_estate/elecstate.h"
7-
#include "source_pw/module_ofdft/kedf_lkt.h"
8-
#include "source_pw/module_ofdft/kedf_tf.h"
9-
#include "source_pw/module_ofdft/kedf_vw.h"
10-
#include "source_pw/module_ofdft/kedf_wt.h"
11-
#include "source_pw/module_ofdft/kedf_ml.h"
7+
#include "kedf_lkt.h"
8+
#include "kedf_tf.h"
9+
#include "kedf_vw.h"
10+
#include "kedf_wt.h"
11+
#include "kedf_xwm.h"
12+
#include "kedf_ml.h"
1213

1314
class KEDF_Manager
1415
{
@@ -74,6 +75,7 @@ class KEDF_Manager
7475
KEDF_TF* tf_ = nullptr; // Thomas-Fermi KEDF
7576
KEDF_vW* vw_ = nullptr; // von Weizsäcker KEDF
7677
KEDF_WT* wt_ = nullptr; // Wang-Teter KEDF
78+
KEDF_XWM* xwm_ = nullptr; // Xu-Wang-Ma KEDF
7779
#ifdef __MLALGO
7880
KEDF_ML* ml_ = nullptr; // Machine Learning KEDF
7981
#endif

0 commit comments

Comments
 (0)