Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions source/source_estate/module_charge/charge.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ class Charge

void save_rho_before_sum_band();

/// @brief whether allocate() has already claimed the density buffers
/// @return true once allocate() has run; allocate() is idempotent and
/// returns early when this is already true
bool get_allocate_rho() const { return allocate_rho; }

// mohan add 2021-02-20
int nrxx=0; // number of r vectors in this processor
int nxyz = 0; // total number of r vectors
Expand Down
25 changes: 25 additions & 0 deletions source/source_estate/module_charge/chg_mix.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,36 @@ class Charge_Mixing
*/
Base_Mixing::Mixing_Data& get_dmr_mdata() {return dmr_mdata;}

/**
* @brief mutable access to the charge-density mixing history
*
* Same ownership story as get_dmr_mdata(): the buffer belongs to
* Charge_Mixing but is driven through Base_Mixing::Mixing, so callers
* that reset or inspect the history need a handle on it.
*/
Base_Mixing::Mixing_Data& get_rho_mdata() {return rho_mdata;}

/**
* @brief mutable access to the kinetic-energy-density mixing history
*/
Base_Mixing::Mixing_Data& get_tau_mdata() {return tau_mdata;}

/**
* @brief read-only access to the aggregated mixing config set by set_mixing()
*/
const MixingConfig& get_mixing_config() const {return cfg_;}

/**
* @brief replace the aggregated mixing config without re-running set_mixing()
*
* set_mixing() both stores the config and rebuilds the mixing objects. This
* setter is for callers that need to update the snapshot alone - typically
* because a derived runtime global (nspin, domag, ...) changed after the
* mixing objects were already built - and must not disturb the mixing
* history. Pair it with get_mixing_config() to amend individual fields.
*/
void set_mixing_config(const MixingConfig& cfg) {cfg_ = cfg;}

// for mixing restart
/// which step to restart mixing during SCF
int mixing_restart_step = 0;
Expand Down
121 changes: 58 additions & 63 deletions source/source_estate/module_charge/unittests/test_charge.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
#include "gtest/gtest.h"
#include "gmock/gmock.h"

#define private public
#define protected public
#include "source_cell/unitcell.h"
#include "source_estate/module_charge/charge.h"
#include "source_estate/module_charge/chg_tools.h"
#include "source_hamilt/module_xc/xc_functional.h"
#include "source_io/module_parameter/parameter.h"
#include "prepare_unitcell.h"
// mock functions for UnitCell

Expand All @@ -21,18 +18,15 @@ Magnetism::~Magnetism()
}

// mock functions for Charge
// xc_functional.cpp is not linked into this target, so the private statics
// need a definition here. Defining them out of line does not require access
// to the class, only changing them does - that goes through the setters.
int XC_Functional::func_type = 1;
bool XC_Functional::ked_flag = false;
namespace elecstate
{
double tmp_ucell_omega = 500.0;
double tmp_gridecut = 80.0;
void Set_GlobalV_Default()
{
PARAM.input.nspin = 1;
PARAM.input.test_charge = 0;
PARAM.input.nelec = 8;
}
} // namespace elecstate

/************************************************
Expand All @@ -45,7 +39,7 @@ void Set_GlobalV_Default()
* - this is a trivial test
* - Allocate: Charge::set_rhopw(), Charge::allocate(), Charge::destroy()
* - allocate rho, rhog, rho_save, rhog_save, kin_r, kin_r_save
* - using rhopw and PARAM.input.nspin
* - using rhopw and the nspin passed in
* - SumRho: Charge::sum_rho()
* - calculate \sum_{is}^nspin \sum_{ir}^nrxx rho[is][ir]
* - RenormalizeRho: Charge::renormalize_rho()
Expand All @@ -64,16 +58,23 @@ class ChargeTest : public ::testing::Test
Charge* charge;
ModulePW::PW_Basis* rhopw;
std::string output;
/// Charge::allocate() and Charge::renormalize_rho() take these explicitly,
/// so the fixture owns them instead of writing the global parameter
/// singleton. The values mirror the Input_para defaults the test relied on.
int nspin = 1;
int test_charge = 0;
double nelec = 8;
bool out_elf_on = false;
void SetUp() override
{
elecstate::Set_GlobalV_Default();
ucell = utp.SetUcellInfo();
charge = new Charge;
rhopw = new ModulePW::PW_Basis;
rhopw->initgrids(ucell->lat0, ucell->latvec, elecstate::tmp_gridecut);
rhopw->distribute_r();
rhopw->initparameters(false, elecstate::tmp_gridecut);
rhopw->distribute_g();
// setuptransform() runs distribute_r() then distribute_g(), both of
// which are protected; this is the public route to the same state.
rhopw->setuptransform();
}
void TearDown() override
{
Expand All @@ -84,7 +85,7 @@ class ChargeTest : public ::testing::Test

TEST_F(ChargeTest, Constructor)
{
EXPECT_FALSE(charge->allocate_rho);
EXPECT_FALSE(charge->get_allocate_rho());
}

TEST_F(ChargeTest, Allocate)
Expand All @@ -101,79 +102,75 @@ TEST_F(ChargeTest, Allocate)
EXPECT_EQ(rhopw->npw, 3143);
EXPECT_EQ(rhopw->npwtot, 3143);
// call Charge::allocate()
PARAM.input.test_charge = 2;
XC_Functional::func_type = 3;
XC_Functional::ked_flag = true;
test_charge = 2;
XC_Functional::set_func_type(3);
XC_Functional::set_ked_flag(true);
charge->set_rhopw(rhopw);
EXPECT_FALSE(charge->allocate_rho);
const bool kin_den = XC_Functional::get_ked_flag() || (PARAM.input.out_elf[0] > 0);
charge->allocate(PARAM.input.nspin, kin_den, XC_Functional::get_ked_flag(),
PARAM.input.test_charge);
EXPECT_TRUE(charge->allocate_rho);
EXPECT_FALSE(charge->get_allocate_rho());
const bool kin_den = XC_Functional::get_ked_flag() || out_elf_on;
charge->allocate(nspin, kin_den, XC_Functional::get_ked_flag(), test_charge);
EXPECT_TRUE(charge->get_allocate_rho());
// test if Charge::allocate() be called twice
EXPECT_NO_THROW(charge->allocate(PARAM.input.nspin, kin_den, XC_Functional::get_ked_flag(),
PARAM.input.test_charge));
EXPECT_TRUE(charge->allocate_rho);
EXPECT_NO_THROW(charge->allocate(nspin, kin_den, XC_Functional::get_ked_flag(),
test_charge));
EXPECT_TRUE(charge->get_allocate_rho());
}

TEST_F(ChargeTest, SumRho)
{
charge->set_rhopw(rhopw);
EXPECT_FALSE(charge->allocate_rho);
const bool kin_den = XC_Functional::get_ked_flag() || (PARAM.input.out_elf[0] > 0);
charge->allocate(PARAM.input.nspin, kin_den, XC_Functional::get_ked_flag(),
PARAM.input.test_charge);
EXPECT_TRUE(charge->allocate_rho);
int nspin = (PARAM.input.nspin == 2) ? 2 : 1;
for (int is = 0; is < nspin; is++)
EXPECT_FALSE(charge->get_allocate_rho());
const bool kin_den = XC_Functional::get_ked_flag() || out_elf_on;
charge->allocate(nspin, kin_den, XC_Functional::get_ked_flag(), test_charge);
EXPECT_TRUE(charge->get_allocate_rho());
int nspin_rho = (nspin == 2) ? 2 : 1;
for (int is = 0; is < nspin_rho; is++)
{
for (int ir = 0; ir < rhopw->nrxx; ir++)
{
charge->rho[is][ir] = 0.1;
}
}
EXPECT_NEAR(charge->sum_rho(ucell->omega), 0.1 * nspin * rhopw->nrxx * ucell->omega / rhopw->nxyz, 1E-10);
EXPECT_NEAR(charge->sum_rho(ucell->omega), 0.1 * nspin_rho * rhopw->nrxx * ucell->omega / rhopw->nxyz, 1E-10);
}

TEST_F(ChargeTest, RenormalizeRho)
{
charge->set_rhopw(rhopw);
EXPECT_FALSE(charge->allocate_rho);
const bool kin_den = XC_Functional::get_ked_flag() || (PARAM.input.out_elf[0] > 0);
charge->allocate(PARAM.input.nspin, kin_den, XC_Functional::get_ked_flag(),
PARAM.input.test_charge);
EXPECT_TRUE(charge->allocate_rho);
int nspin = (PARAM.input.nspin == 2) ? 2 : 1;
for (int is = 0; is < nspin; is++)
EXPECT_FALSE(charge->get_allocate_rho());
const bool kin_den = XC_Functional::get_ked_flag() || out_elf_on;
charge->allocate(nspin, kin_den, XC_Functional::get_ked_flag(), test_charge);
EXPECT_TRUE(charge->get_allocate_rho());
int nspin_rho = (nspin == 2) ? 2 : 1;
for (int is = 0; is < nspin_rho; is++)
{
for (int ir = 0; ir < rhopw->nrxx; ir++)
{
charge->rho[is][ir] = 0.1;
}
}
EXPECT_EQ(PARAM.input.nelec, 8);
charge->renormalize_rho(PARAM.input.nelec, ucell->omega);
EXPECT_EQ(nelec, 8);
charge->renormalize_rho(nelec, ucell->omega);
EXPECT_NEAR(charge->sum_rho(ucell->omega), 8.0, 1e-10);
}

TEST_F(ChargeTest, CheckNe)
{
charge->set_rhopw(rhopw);
EXPECT_FALSE(charge->allocate_rho);
const bool kin_den = XC_Functional::get_ked_flag() || (PARAM.input.out_elf[0] > 0);
charge->allocate(PARAM.input.nspin, kin_den, XC_Functional::get_ked_flag(),
PARAM.input.test_charge);
EXPECT_TRUE(charge->allocate_rho);
int nspin = (PARAM.input.nspin == 2) ? 2 : 1;
for (int is = 0; is < nspin; is++)
EXPECT_FALSE(charge->get_allocate_rho());
const bool kin_den = XC_Functional::get_ked_flag() || out_elf_on;
charge->allocate(nspin, kin_den, XC_Functional::get_ked_flag(), test_charge);
EXPECT_TRUE(charge->get_allocate_rho());
int nspin_rho = (nspin == 2) ? 2 : 1;
for (int is = 0; is < nspin_rho; is++)
{
for (int ir = 0; ir < rhopw->nrxx; ir++)
{
charge->rho[is][ir] = 0.1;
}
}
EXPECT_EQ(PARAM.input.nelec, 8);
charge->renormalize_rho(PARAM.input.nelec, ucell->omega);
EXPECT_EQ(nelec, 8);
charge->renormalize_rho(nelec, ucell->omega);
EXPECT_NEAR(charge->sum_rho(ucell->omega), 8.0, 1e-10);
EXPECT_NEAR(module_charge::cal_rho2ne(charge->rho[0], rhopw->nrxx, ucell->omega, rhopw->nxyz),
8.0, 1e-10);
Expand All @@ -182,25 +179,23 @@ TEST_F(ChargeTest, CheckNe)
TEST_F(ChargeTest, SaveRhoBeforeSumBand)
{
charge->set_rhopw(rhopw);
EXPECT_FALSE(charge->allocate_rho);
const bool kin_den = XC_Functional::get_ked_flag() || (PARAM.input.out_elf[0] > 0);
charge->allocate(PARAM.input.nspin, kin_den, XC_Functional::get_ked_flag(),
PARAM.input.test_charge);
EXPECT_TRUE(charge->allocate_rho);
int nspin = (PARAM.input.nspin == 2) ? 2 : 1;
for (int is = 0; is < nspin; is++)
EXPECT_FALSE(charge->get_allocate_rho());
const bool kin_den = XC_Functional::get_ked_flag() || out_elf_on;
charge->allocate(nspin, kin_den, XC_Functional::get_ked_flag(), test_charge);
EXPECT_TRUE(charge->get_allocate_rho());
int nspin_rho = (nspin == 2) ? 2 : 1;
for (int is = 0; is < nspin_rho; is++)
{
for (int ir = 0; ir < rhopw->nrxx; ir++)
{
charge->rho[is][ir] = 0.1;
}
}
EXPECT_EQ(PARAM.input.nelec, 8);
XC_Functional::func_type = 3;
XC_Functional::ked_flag = true;
charge->renormalize_rho(PARAM.input.nelec, ucell->omega);
EXPECT_EQ(nelec, 8);
XC_Functional::set_func_type(3);
XC_Functional::set_ked_flag(true);
charge->renormalize_rho(nelec, ucell->omega);
charge->save_rho_before_sum_band();
EXPECT_NEAR(module_charge::cal_rho2ne(charge->rho_save[0], rhopw->nrxx, ucell->omega, rhopw->nxyz),
8.0, 1e-10);
}

Loading
Loading