From c9c0c7a12731b1126a5dca0c39b326da967a87c6 Mon Sep 17 00:00:00 2001 From: GRYS <57103981+grysgreat@users.noreply.github.com> Date: Fri, 23 Feb 2024 14:23:03 +0800 Subject: [PATCH] Feature: Added json array support. Implement init json (#3612) --- .gitignore | 3 +- source/Makefile.Objects | 1 + source/driver.cpp | 3 +- source/module_esolver/esolver_ks.cpp | 9 +- source/module_io/json_output/CMakeLists.txt | 2 +- source/module_io/json_output/abacusjson.h | 39 ++++- source/module_io/json_output/general_info.cpp | 16 +- source/module_io/json_output/general_info.h | 3 +- source/module_io/json_output/init_info.cpp | 58 +++++++ source/module_io/json_output/init_info.h | 17 ++ .../module_io/json_output/test/CMakeLists.txt | 5 +- .../json_output/test/para_json_test.cpp | 153 +++++++++++++++++- source/module_io/para_json.cpp | 21 ++- source/module_io/para_json.h | 8 + 14 files changed, 309 insertions(+), 29 deletions(-) create mode 100644 source/module_io/json_output/init_info.cpp create mode 100644 source/module_io/json_output/init_info.h diff --git a/.gitignore b/.gitignore index c61a9d7a85..3a2b006d3b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,5 @@ dist toolchain.tar.gz time.json *.pyc -__pycache__ \ No newline at end of file +__pycache__ +abacus.json \ No newline at end of file diff --git a/source/Makefile.Objects b/source/Makefile.Objects index 5818dd0ada..47172623ee 100644 --- a/source/Makefile.Objects +++ b/source/Makefile.Objects @@ -452,6 +452,7 @@ OBJS_IO=input.o\ para_json.o\ abacusjson.o\ general_info.o\ + init_info.o\ OBJS_IO_LCAO=cal_r_overlap_R.o\ diff --git a/source/driver.cpp b/source/driver.cpp index 8998b432f7..95d976a500 100644 --- a/source/driver.cpp +++ b/source/driver.cpp @@ -42,7 +42,8 @@ void Driver::init() INPUT.close_log(); // (5) output the json file - Json::json_output(); + //Json::create_Json(&GlobalC::ucell.symm,GlobalC::ucell.atoms,&INPUT); + Json::create_Json(&GlobalC::ucell,&INPUT); return; } diff --git a/source/module_esolver/esolver_ks.cpp b/source/module_esolver/esolver_ks.cpp index fab63ce864..54f430c5b0 100644 --- a/source/module_esolver/esolver_ks.cpp +++ b/source/module_esolver/esolver_ks.cpp @@ -12,6 +12,8 @@ #include "module_io/print_info.h" #include "module_base/timer.h" #include "module_io/input.h" +#include "module_io/json_output/init_info.h" + //--------------Temporary---------------- #include "module_base/global_variable.h" @@ -475,7 +477,12 @@ namespace ModuleESolver ModuleBase::timer::tick(this->classname, "Run"); } - + // add nkstot,nkstot_ibz to output json + #ifdef __RAPIDJSON + int Jnkstot = this->pelec->klist->nkstot; + int Jnkstot_ibz = this->pelec->klist->nkstot_ibz; + Json::add_nkstot(Jnkstot,Jnkstot_ibz); + #endif //__RAPIDJSON return; }; diff --git a/source/module_io/json_output/CMakeLists.txt b/source/module_io/json_output/CMakeLists.txt index 628303d086..7dea34b51b 100644 --- a/source/module_io/json_output/CMakeLists.txt +++ b/source/module_io/json_output/CMakeLists.txt @@ -1,7 +1,7 @@ list(APPEND objects_json abacusjson.cpp general_info.cpp - + init_info.cpp ) add_library( diff --git a/source/module_io/json_output/abacusjson.h b/source/module_io/json_output/abacusjson.h index a358753040..ab1c350fdb 100644 --- a/source/module_io/json_output/abacusjson.h +++ b/source/module_io/json_output/abacusjson.h @@ -1,3 +1,6 @@ +#ifndef ABACUS_JSON_H +#define ABACUS_JSON_H + #include #include #include @@ -8,15 +11,40 @@ #include "rapidjson/prettywriter.h" #include "rapidjson/stringbuffer.h" -//define of AbacusJson +/** +* @brief Define of AbacusJson:These macro definitions simplify the complex parameters +* required to add objects in rapidjson, making it easy to use. +* @usage: 1. create the json value by Type: eg. +* Json::jsonValue object(JobjectType); +* Json::jsonValue array(JarrayType); +* 2 - object. add the parameter by using correct function. If the constructed object contains +* type std::string, select the correct macro definition function in the key +* or value position based on std::string. +* eg. key is std::string, using: object.JaddStringK(str,val) +* eg. val is std::string, using: object.JaddStringV (str,val) +* eg. both key,val is std::string, using: object.JaddStringKV(str,val) +* eg. none of key,val is std::string, using: object.JaddNormal(str,val) +* +* 2 - array. using: array.JPushBack(val) +* or : JPushBackString(val) +*/ + #define JobjectType rapidjson::kObjectType #define JarrayType rapidjson::kArrayType #define Get_Jallocator Json::AbacusJson::allocator() #define Set_JString(str) Json::jsonValue().SetString(str.c_str(),str.length(),Get_Jallocator) -#define JaddString(str,val) AddMember(str, Set_JString(val), Get_Jallocator) + + +#define JaddStringV(str,val) AddMember(str, Set_JString(val), Get_Jallocator) +#define JaddStringK(str,val) AddMember(Set_JString(str), val, Get_Jallocator) +#define JaddStringKV(str,val) AddMember(Set_JString(str), Set_JString(val), Get_Jallocator) #define JaddNormal(str,val) AddMember(str, val, Get_Jallocator) #define JPushBack(val) PushBack(val, Get_Jallocator) - +#define JPushBackString(val) PushBack(Set_JString(val), Get_Jallocator) +/** +* @brief The json processing module in abacus contains basic meta-operations such as +* adding, modifying, and checking json. +*/ namespace Json { @@ -26,7 +54,7 @@ using jsonValue = rapidjson::Value; class AbacusJson { public: - // Add a key value pair to the json + // The template specialization method adds a key-val object to the doc tree template static void add_json(std::vector keys, const T& value,bool IsArray) { @@ -38,6 +66,7 @@ class AbacusJson add_nested_member(keys.begin(), keys.end(), val, doc, doc.GetAllocator(),IsArray); } + // Output the json to a file static void write_to_json(std::string filename); @@ -66,4 +95,6 @@ void AbacusJson::add_json(std::vector keys, const rapidjson::Value& } // namespace Json +#endif + #endif \ No newline at end of file diff --git a/source/module_io/json_output/general_info.cpp b/source/module_io/json_output/general_info.cpp index 3b5d035e37..1ac054f34b 100644 --- a/source/module_io/json_output/general_info.cpp +++ b/source/module_io/json_output/general_info.cpp @@ -5,11 +5,13 @@ #include "module_base/parallel_global.h" #include "module_io/input.h" #include "version.h" + +//Add json objects to gener_info namespace Json { #ifdef __RAPIDJSON -void gen_general_info() +void gen_general_info(Input *input) { #ifdef VERSION @@ -24,7 +26,7 @@ void gen_general_info() #endif // start_time - std::time_t start_time = INPUT.get_start_time(); + std::time_t start_time = input->get_start_time(); std::string start_time_str; convert_time(start_time, start_time_str); @@ -43,13 +45,13 @@ void gen_general_info() AbacusJson::add_json({"general_info", "version"}, version,false); AbacusJson::add_json({"general_info", "commit"}, commit,false); - AbacusJson::add_json({"general_info", "device"}, INPUT.device,false); + AbacusJson::add_json({"general_info", "device"}, input->device,false); AbacusJson::add_json({"general_info", "mpi_num"}, mpi_num,false); AbacusJson::add_json({"general_info", "omp_num"}, omp_num,false); - AbacusJson::add_json({"general_info", "pseudo_dir"}, INPUT.pseudo_dir,false); - AbacusJson::add_json({"general_info", "orbital_dir"}, INPUT.orbital_dir,false); - AbacusJson::add_json({"general_info", "stru_file"}, INPUT.stru_file,false); - AbacusJson::add_json({"general_info", "kpt_file"}, INPUT.kpoint_file,false); + AbacusJson::add_json({"general_info", "pseudo_dir"}, input->pseudo_dir,false); + AbacusJson::add_json({"general_info", "orbital_dir"}, input->orbital_dir,false); + AbacusJson::add_json({"general_info", "stru_file"}, input->stru_file,false); + AbacusJson::add_json({"general_info", "kpt_file"}, input->kpoint_file,false); AbacusJson::add_json({"general_info", "start_time"}, start_time_str,false); AbacusJson::add_json({"general_info", "end_time"}, end_time_str,false); } diff --git a/source/module_io/json_output/general_info.h b/source/module_io/json_output/general_info.h index e91a3154f8..afed718a06 100644 --- a/source/module_io/json_output/general_info.h +++ b/source/module_io/json_output/general_info.h @@ -1,8 +1,9 @@ #include "module_io/input.h" +//Add json objects to gener_info namespace Json { #ifdef __RAPIDJSON -void gen_general_info(); +void gen_general_info(Input *input); #endif } \ No newline at end of file diff --git a/source/module_io/json_output/init_info.cpp b/source/module_io/json_output/init_info.cpp new file mode 100644 index 0000000000..ff2e7107f5 --- /dev/null +++ b/source/module_io/json_output/init_info.cpp @@ -0,0 +1,58 @@ +#include "init_info.h" +#include "module_io/input.h" +#include "../para_json.h" +#include "abacusjson.h" + + +//Add json objects to init +namespace Json +{ + +#ifdef __RAPIDJSON + + +// void gen_init(ModuleSymmetry::Symmetry *symm,Atom *atoms){ +// std::string pgname = symm->pgname; +// std::string spgname = symm->spgname; +// AbacusJson::add_json({"init", "pgname"}, pgname,false); +// AbacusJson::add_json({"init", "spgname"}, spgname,false); + + +// int numAtoms = atoms->na; +// AbacusJson::add_json({"init", "natom"}, numAtoms,false); +// AbacusJson::add_json({"init", "nband"}, INPUT.nbands,false); + + +// } + +void gen_init(UnitCell *ucell){ + std::string pgname = ucell->symm.pgname; + std::string spgname = ucell->symm.spgname; + AbacusJson::add_json({"init", "point_group"}, pgname,false); + AbacusJson::add_json({"init", "point_group_in_space"}, spgname,false); + + + int numAtoms = ucell->atoms->na; + AbacusJson::add_json({"init", "natom"}, numAtoms,false); + AbacusJson::add_json({"init", "nband"}, GlobalV::NBANDS,false); + + int ntype = ucell->ntype; + AbacusJson::add_json({"init", "nelectron"}, ntype,false); + + for (int it = 0; it < ntype; it++) + { + std::string label = ucell->atoms[it].label; + int number = ucell->atoms[it].ncpp.zv; + AbacusJson::add_json({"init", "nelectron_each_type",label}, number,false); + } + +} + + +void add_nkstot(int nkstot,int nkstot_ibz){ + Json::AbacusJson::add_json({"init", "nkstot"}, nkstot,false); + Json::AbacusJson::add_json({"init", "nkstot_ibz"}, nkstot_ibz,false); +} + +#endif +} // namespace Json \ No newline at end of file diff --git a/source/module_io/json_output/init_info.h b/source/module_io/json_output/init_info.h new file mode 100644 index 0000000000..90e6b62e59 --- /dev/null +++ b/source/module_io/json_output/init_info.h @@ -0,0 +1,17 @@ +#include "module_cell/module_symmetry/symmetry.h" +#include "module_cell/atom_spec.h" +#include "module_cell/unitcell.h" + + +//Add json objects to init +namespace Json +{ +#ifdef __RAPIDJSON +// void gen_init(ModuleSymmetry::Symmetry *symm,Atom *atoms); +void gen_init(UnitCell *ucell); + +void add_nkstot(int nkstot,int nkstot_ibz); + + +#endif +} \ No newline at end of file diff --git a/source/module_io/json_output/test/CMakeLists.txt b/source/module_io/json_output/test/CMakeLists.txt index 7c7070f37c..ec09db3965 100644 --- a/source/module_io/json_output/test/CMakeLists.txt +++ b/source/module_io/json_output/test/CMakeLists.txt @@ -6,6 +6,7 @@ remove_definitions(-DUSE_PAW) AddTest( TARGET io_json_output_json - LIBS ${math_libs} base device - SOURCES para_json_test.cpp ../general_info.cpp ../../para_json.cpp ../abacusjson.cpp ../../input.cpp + LIBS ${math_libs} base device cell_info + SOURCES para_json_test.cpp ../general_info.cpp ../init_info.cpp + ../../para_json.cpp ../abacusjson.cpp ../../input.cpp ../../output.cpp ) \ No newline at end of file diff --git a/source/module_io/json_output/test/para_json_test.cpp b/source/module_io/json_output/test/para_json_test.cpp index 6be02794d9..c3baefd4cd 100644 --- a/source/module_io/json_output/test/para_json_test.cpp +++ b/source/module_io/json_output/test/para_json_test.cpp @@ -4,7 +4,26 @@ #include "../abacusjson.h" #include "module_io/input.h" #include "module_io/para_json.h" +#include "../init_info.h" +#include "../general_info.h" #include "version.h" + +/************************************************ + * unit test of json output module + ************************************************ +/** + * - Tested Functions: + * - AddJson() + * - Verify the normal addition of json structure parameters in the json function. + * - OutputJson() + * - Verify the correctness of the json output. + * - GeneralInfo() + * - Test the correctness of the json output of the General Info module. + * - InitInfo() + * - Test the correctness of the json output of the Init info module. + */ + + TEST(AbacusJsonTest, AddJson) { Json::AbacusJson::doc.SetObject(); @@ -58,23 +77,45 @@ TEST(AbacusJsonTest, AddJson) for(int i=0;i<3;i++){ Json::jsonValue object(JobjectType); object.JaddNormal("int",i); - std::string str = std::to_string(i*100); - object.JaddString("string", str); + + std::string str = std::to_string(i*100); + std::string str2 = "Kstring"; + + object.JaddStringV("string", str); + object.JaddStringK(str, "string"); + object.JaddStringKV(str2, str); object.JaddNormal("double", 0.01*i); Json::AbacusJson::add_json({"array"}, object,true); } + + // Validate json parameters in doc objects ASSERT_EQ(Json::AbacusJson::doc["array"][0]["int"].GetInt(), 0); ASSERT_STREQ(Json::AbacusJson::doc["array"][0]["string"].GetString(), "0"); + ASSERT_STREQ(Json::AbacusJson::doc["array"][0]["0"].GetString(), "string"); + ASSERT_STREQ(Json::AbacusJson::doc["array"][0]["Kstring"].GetString(), "0"); + ASSERT_EQ(Json::AbacusJson::doc["array"][0]["double"].GetDouble(), 0.0); ASSERT_EQ(Json::AbacusJson::doc["array"][1]["int"].GetInt(), 1); ASSERT_STREQ(Json::AbacusJson::doc["array"][1]["string"].GetString(), "100"); + + ASSERT_STREQ(Json::AbacusJson::doc["array"][1]["100"].GetString(), "string"); + ASSERT_STREQ(Json::AbacusJson::doc["array"][1]["Kstring"].GetString(), "100"); + ASSERT_EQ(Json::AbacusJson::doc["array"][1]["double"].GetDouble(), 0.01); ASSERT_EQ(Json::AbacusJson::doc["array"][2]["int"].GetInt(), 2); ASSERT_STREQ(Json::AbacusJson::doc["array"][2]["string"].GetString(), "200"); + + ASSERT_STREQ(Json::AbacusJson::doc["array"][2]["200"].GetString(), "string"); + ASSERT_STREQ(Json::AbacusJson::doc["array"][2]["Kstring"].GetString(), "200"); ASSERT_EQ(Json::AbacusJson::doc["array"][2]["double"].GetDouble(), 0.02); + + + + + // add array in array Json::jsonValue object0(JarrayType); @@ -84,20 +125,50 @@ TEST(AbacusJsonTest, AddJson) Json::jsonValue object1(JarrayType); - object1.JPushBack(2); - object1.JPushBack(3); - object1.JPushBack(4); + + object1.JPushBack(2.1); + object1.JPushBack(3.1); + object1.JPushBack(4.1); + + Json::jsonValue object2(JarrayType); + + object2.JPushBack("str1"); + object2.JPushBack("str2"); + object2.JPushBack("str3"); + + Json::jsonValue object3(JarrayType); + + std::string astr1 = "string1"; + std::string astr2 = "string2"; + std::string astr3 = "string3"; + object3.JPushBackString(astr1); + object3.JPushBackString(astr2); + object3.JPushBackString(astr3); + Json::AbacusJson::add_json({"Darray"}, object0,true); Json::AbacusJson::add_json({"Darray"}, object1,true); + Json::AbacusJson::add_json({"Darray"}, object2,true); + Json::AbacusJson::add_json({"Darray"}, object3,true); ASSERT_EQ(Json::AbacusJson::doc["Darray"][0][0].GetInt(), 1); ASSERT_EQ(Json::AbacusJson::doc["Darray"][0][1].GetInt(), 2); ASSERT_EQ(Json::AbacusJson::doc["Darray"][0][2].GetInt(), 3); - ASSERT_EQ(Json::AbacusJson::doc["Darray"][1][0].GetInt(), 2); - ASSERT_EQ(Json::AbacusJson::doc["Darray"][1][1].GetInt(), 3); - ASSERT_EQ(Json::AbacusJson::doc["Darray"][1][2].GetInt(), 4); + + ASSERT_EQ(Json::AbacusJson::doc["Darray"][1][0].GetDouble(), 2.1); + ASSERT_EQ(Json::AbacusJson::doc["Darray"][1][1].GetDouble(), 3.1); + ASSERT_EQ(Json::AbacusJson::doc["Darray"][1][2].GetDouble(), 4.1); + + ASSERT_STREQ(Json::AbacusJson::doc["Darray"][2][0].GetString(), "str1"); + ASSERT_STREQ(Json::AbacusJson::doc["Darray"][2][1].GetString(), "str2"); + ASSERT_STREQ(Json::AbacusJson::doc["Darray"][2][2].GetString(), "str3"); + + + ASSERT_STREQ(Json::AbacusJson::doc["Darray"][3][0].GetString(), "string1"); + ASSERT_STREQ(Json::AbacusJson::doc["Darray"][3][1].GetString(), "string2"); + ASSERT_STREQ(Json::AbacusJson::doc["Darray"][3][2].GetString(), "string3"); + } TEST(AbacusJsonTest, OutputJson) @@ -130,6 +201,7 @@ TEST(AbacusJsonTest, OutputJson) ASSERT_NE(content.find("\"key5\": true"), std::string::npos); file.close(); + } TEST(AbacusJsonTest, GeneralInfo) @@ -146,6 +218,7 @@ TEST(AbacusJsonTest, GeneralInfo) INPUT.kpoint_file = "./abacus/test/kpoint_file"; // output the json file Json::AbacusJson::doc.Parse("{}"); + Json::gen_general_info(&INPUT); Json::json_output(); std::string filename = "abacus.json"; @@ -164,3 +237,67 @@ TEST(AbacusJsonTest, GeneralInfo) ASSERT_NE(content.find("\"kpt_file\": \"./abacus/test/kpoint_file\","), std::string::npos); ASSERT_NE(content.find(start_time_str), std::string::npos); } + + + +#ifdef __LCAO +#include "module_basis/module_ao/ORB_read.h" +InfoNonlocal::InfoNonlocal(){} +InfoNonlocal::~InfoNonlocal(){} +LCAO_Orbitals::LCAO_Orbitals(){} +LCAO_Orbitals::~LCAO_Orbitals(){} +#endif +Magnetism::Magnetism() +{ + this->tot_magnetization = 0.0; + this->abs_magnetization = 0.0; + this->start_magnetization = nullptr; +} +Magnetism::~Magnetism() +{ + delete[] this->start_magnetization; +} + +TEST(AbacusJsonTest, InitInfo) +{ + UnitCell ucell; + Atom atomlist[3]; + + + ucell.symm.pgname = "T_d"; + ucell.symm.spgname = "O_h"; + ucell.atoms =atomlist; + ucell.atoms->na = 100; + ucell.ntype = 3; + GlobalV::NBANDS = 10; + + for(int i=0;i<3;i++){ + ucell.atoms[i].label = std::to_string(i); + ucell.atoms[i].ncpp.zv = i*3; + } + + + // init the doc allocator + Json::AbacusJson::doc.Parse("{}"); + int Jnkstot=1,Jnkstot_ibz = 2; + + Json::add_nkstot(Jnkstot,Jnkstot_ibz); + Json::gen_init(&ucell); + + + ASSERT_TRUE(Json::AbacusJson::doc.HasMember("init")); + ASSERT_EQ(Json::AbacusJson::doc["init"]["nkstot"].GetInt(), 1); + ASSERT_EQ(Json::AbacusJson::doc["init"]["nkstot_ibz"].GetInt(), 2); + + ASSERT_EQ(Json::AbacusJson::doc["init"]["natom"].GetInt(), 100); + ASSERT_EQ(Json::AbacusJson::doc["init"]["nband"].GetInt(), 10); + + + ASSERT_STREQ(Json::AbacusJson::doc["init"]["point_group"].GetString(), "T_d"); + ASSERT_STREQ(Json::AbacusJson::doc["init"]["point_group_in_space"].GetString(), "O_h"); + + ASSERT_EQ(Json::AbacusJson::doc["init"]["nelectron_each_type"]["0"].GetInt(), 0); + ASSERT_EQ(Json::AbacusJson::doc["init"]["nelectron_each_type"]["1"].GetInt(), 3); + ASSERT_EQ(Json::AbacusJson::doc["init"]["nelectron_each_type"]["2"].GetInt(), 6); + +} diff --git a/source/module_io/para_json.cpp b/source/module_io/para_json.cpp index f661448c2d..5e79431069 100644 --- a/source/module_io/para_json.cpp +++ b/source/module_io/para_json.cpp @@ -10,25 +10,40 @@ #ifdef __RAPIDJSON #include "json_output/abacusjson.h" #include "json_output/general_info.h" -#include "module_io/input.h" +#include "json_output/init_info.h" + #endif // __RAPIDJSON namespace Json { + +// void create_Json(ModuleSymmetry::Symmetry *symm,Atom *atoms,Input *input){ +// #ifdef __RAPIDJSON +// gen_general_info(input); +// gen_init(symm,atoms); +// #endif +// } + void json_output() { #ifdef __RAPIDJSON - gen_general_info(); #ifdef __MPI if (GlobalV::MY_RANK == 0) AbacusJson::write_to_json("abacus.json"); #elif AbacusJson::write_to_json("abacus.json"); #endif - #endif // __RAPIDJSON } +void create_Json(UnitCell *ucell,Input *input){ +#ifdef __RAPIDJSON + gen_general_info(input); + gen_init(ucell); +#endif + json_output(); +} + void convert_time(std::time_t time_now, std::string& time_str) { std::tm* tm = std::localtime(&time_now); diff --git a/source/module_io/para_json.h b/source/module_io/para_json.h index 3580fff710..bba5d075c3 100644 --- a/source/module_io/para_json.h +++ b/source/module_io/para_json.h @@ -1,9 +1,17 @@ #include #include +#include "module_cell/module_symmetry/symmetry.h" +#include "module_cell/atom_spec.h" +#include "module_io/input.h" +#include "module_cell/unitcell.h" namespace Json { +// void create_Json(ModuleSymmetry::Symmetry *symm,Atom *atoms,Input *input); + +void create_Json(UnitCell *ucell,Input *input); + // Output the json to abacus.json file void json_output();