Skip to content

Commit

Permalink
Reflactor: new json array support and add json tree of abacus-output (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
grysgreat authored Mar 22, 2024
1 parent bdee87e commit 0c42fb9
Show file tree
Hide file tree
Showing 15 changed files with 475 additions and 64 deletions.
1 change: 1 addition & 0 deletions source/Makefile.Objects
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ OBJS_IO=input.o\
general_info.o\
init_info.o\
readin_info.o\
output_info.o\

OBJS_IO_LCAO=cal_r_overlap_R.o\
write_orb_info.o\
Expand Down
41 changes: 33 additions & 8 deletions source/module_esolver/esolver_ks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "module_base/parallel_common.h"
#endif

#include "module_io/json_output/output_info.h"

namespace ModuleESolver
{

Expand Down Expand Up @@ -448,12 +450,26 @@ namespace ModuleESolver
/*
SCF print: G1 -3.435545e+03 0.000000e+00 3.607e-01 2.862e-01
*/

double dkin = 0.0; // for meta-GGA
if (XC_Functional::get_func_type() == 3 || XC_Functional::get_func_type() == 5)
{
dkin = p_chgmix->get_dkin(pelec->charge, GlobalV::nelec);
}
printiter(iter, drho, dkin, duration, diag_ethr);

#ifdef __RAPIDJSON
//add Json of scf mag
Json::add_output_scf_mag(
GlobalC::ucell.magnet.tot_magnetization, GlobalC::ucell.magnet.abs_magnetization,
this->pelec->f_en.etot * ModuleBase::Ry_to_eV,
(this->pelec->f_en.etot - this->pelec->f_en.etot_old) * ModuleBase::Ry_to_eV,
drho,
duration
);
#endif //__RAPIDJSON


if (this->conv_elec)
{
this->niter = iter;
Expand All @@ -465,17 +481,26 @@ namespace ModuleESolver
{
std::cout<<"SCF restart after this step!"<<std::endl;
}

}
#ifdef __RAPIDJSON
//add Json of efermi energy converge
Json::add_output_efermi_energy_converge(
this->pelec->eferm.ef * ModuleBase::Ry_to_eV,
this->pelec->f_en.etot * ModuleBase::Ry_to_eV,
this->conv_elec
);
#endif //__RAPIDJSON
afterscf(istep);

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
}

#ifdef __RAPIDJSON
// add nkstot,nkstot_ibz to output json
int Jnkstot = this->pelec->klist->nkstot;
int Jnkstot_ibz = this->pelec->klist->nkstot_ibz;
Json::add_nkstot(Jnkstot,Jnkstot_ibz);
#endif //__RAPIDJSON
return;
};

Expand Down
1 change: 1 addition & 0 deletions source/module_io/json_output/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ list(APPEND objects_json
general_info.cpp
init_info.cpp
readin_info.cpp
output_info.cpp
)

add_library(
Expand Down
64 changes: 52 additions & 12 deletions source/module_io/json_output/abacusjson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,30 @@
#include <iostream>
#include <string>
#include <vector>

#include <sstream>
namespace Json
{

#ifdef __RAPIDJSON
rapidjson::Document AbacusJson::doc;

void AbacusJson::add_nested_member(std::vector<std::string>::iterator begin,
std::vector<std::string>::iterator end,
bool isNum(std::string str)
{
std::stringstream sin;
sin<<str;
double d;
char c;
if(!(sin >> d))
return false;

if (sin >> c)
return false;
return true;
}


void AbacusJson::add_nested_member(std::vector<jsonKeyNode>::iterator begin,
std::vector<jsonKeyNode>::iterator end,
rapidjson::Value& val,
rapidjson::Value& parent,
rapidjson::Document::AllocatorType& allocator,
Expand All @@ -21,19 +36,33 @@ void AbacusJson::add_nested_member(std::vector<std::string>::iterator begin,
{
if (begin != end)
{
rapidjson::Value key((*begin).c_str(), allocator);
jsonKeyNode keyNode = *begin;
rapidjson::Value key((*begin).key.c_str(), allocator);


if (begin + 1 == end)
{

if( keyNode.key.empty() && parent.IsArray()){
int index = keyNode.i;
if(index>=0){
parent[index] = val;
}
else {
int arr_size = parent.Size();
parent[arr_size+index] = val;
}
}
// if key exists, then overwrite it
if (parent.HasMember(key))
else if (parent.HasMember(key))
{
if(parent[key].IsArray()){
parent[key].PushBack(val, allocator);
}else{
// if key is an object, then warn the user
if (parent[key].IsObject())
{
std::cout << "Warning: write to json, key " << *begin
std::cout << "Warning: write to json, key " << (*begin).key
<< " exist and is an object, and abacus will overwrite it with a value." << std::endl;
}
parent[key] = val;
Expand All @@ -52,14 +81,25 @@ void AbacusJson::add_nested_member(std::vector<std::string>::iterator begin,
}
else
{
if( keyNode.key.empty()&&parent.IsArray()){
int index = keyNode.i;

if(index>=0){
add_nested_member(begin + 1, end, val, parent[index], allocator,IsArray);
}
else {
int arr_size = parent.Size();
add_nested_member(begin + 1, end, val, parent[arr_size+index], allocator,IsArray);
}
}
// need to check if the key exists
if (parent.HasMember(key))
else if (parent.HasMember(key))
{
// this key should be an object
if (!parent[key].IsObject())
if (!parent[key].IsObject()&&!parent[key].IsArray())
{
std::cout << "Warning: write to json, key " << *begin
<< " exist and is not an object, and abacus will add it as a middle node." << std::endl;
std::cout << "Warning: write to json, key " << (*begin).key
<< " exist and is not an object or array, and abacus will add it as a middle node." << std::endl;
}
add_nested_member(begin + 1, end, val, parent[key], allocator,IsArray);
}
Expand All @@ -84,7 +124,7 @@ void AbacusJson::write_to_json(std::string filename)
ofs.close();
};
template <>
void AbacusJson::add_json(std::vector<std::string> keys, const std::string& value,bool IsArray)
void AbacusJson::add_json(std::vector<jsonKeyNode> keys, const std::string& value,bool IsArray)
{
if (!doc.IsObject())
{
Expand All @@ -97,7 +137,7 @@ void AbacusJson::write_to_json(std::string filename)

// Overloaded template functions for json class objects
template <>
void AbacusJson::add_json(std::vector<std::string> keys, const rapidjson::Value& value,bool IsArray)
void AbacusJson::add_json(std::vector<jsonKeyNode> keys, const rapidjson::Value& value,bool IsArray)
{

if (!doc.IsObject())
Expand Down
70 changes: 51 additions & 19 deletions source/module_io/json_output/abacusjson.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <iostream>
#include <string>
#include <vector>
#include "json_node.h"


#ifdef __RAPIDJSON
#include "rapidjson/document.h"
Expand Down Expand Up @@ -54,9 +56,45 @@ using jsonValue = rapidjson::Value;
class AbacusJson
{
public:
// The template specialization method adds a key-val object to the doc tree



// Output the json to a file
static void write_to_json(std::string filename);

static rapidjson::Document::AllocatorType& allocator(){
return doc.GetAllocator();
}

/**
* @brief: The template specialization method adds value to the doc tree
*
* @param: 'keys' is a vector string, represents the path to be added to the json tree.
*
* 'value' is the value that needs to be added to the json tree, which type can be
* Json::jsonValue or other common value type(such as int, double ,bool ,std::string).
*
* 'IsArray' is a bool value, means the whether the root node to which 'value' is added is an array.
*
* @usage: 1. Add/Modify a double val to object json node (key2 is a object node):
* Json::AbacusJson::add_json({"key1","key2"}, 3.1415,false);
*
* 2. Pushback a double val to array json node (key2 is a array node):
* Json::AbacusJson::add_json({"key1","key2"}, 3.1415,true);
*
* 3. Modify a doble val to array json node (key2 is a array node), when use this method,
* The index number of the array starts at 0, if it's negative, it's going from back to front.
* eg. If the index is -1, it means that the last element of the array is modified:
* If we have a json array: {"key":[1,2,3]}
* i). Json::AbacusJson::add_json({"key",0}, 4,true); => {"key":[4,2,3]}
* ii). Json::AbacusJson::add_json({"key",-1}, 4,true); => {"key":[1,2,4]}
* iii). Json::AbacusJson::add_json({"key",1}, 4,true); => {"key":[1,4,3]}
* iv). Json::AbacusJson::add_json({"key",2}, 4,true); => {"key":[1,2,4]}
* iv). Json::AbacusJson::add_json({"key",3}, 4,true); => error!, The array element corresponding
* to the index has no value.
*/
template <typename T>
static void add_json(std::vector<std::string> keys, const T& value,bool IsArray)
static void add_json(std::vector<jsonKeyNode> keys, const T& value,bool IsArray)
{
if (!doc.IsObject())
{
Expand All @@ -67,31 +105,25 @@ class AbacusJson
}


// Output the json to a file
static void write_to_json(std::string filename);

static rapidjson::Document::AllocatorType& allocator(){
return doc.GetAllocator();
}



private:
static rapidjson::Document doc;

static void add_nested_member(std::vector<std::string>::iterator begin,
std::vector<std::string>::iterator end,
rapidjson::Value& val,
rapidjson::Value& parent,
rapidjson::Document::AllocatorType& allocator,
bool IsArray = false
);
};
static void add_nested_member(std::vector<jsonKeyNode>::iterator begin,
std::vector<jsonKeyNode>::iterator end,
rapidjson::Value& val,
rapidjson::Value& parent,
rapidjson::Document::AllocatorType& allocator,
bool IsArray
);
};

template <>
void AbacusJson::add_json(std::vector<std::string> keys, const std::string& value,bool IsArray);
void AbacusJson::add_json(std::vector<jsonKeyNode> keys, const std::string& value,bool IsArray);

template <>
void AbacusJson::add_json(std::vector<std::string> keys, const rapidjson::Value& value,bool IsArray);
void AbacusJson::add_json(std::vector<jsonKeyNode> keys, const rapidjson::Value& value,bool IsArray);


} // namespace Json
Expand Down
12 changes: 12 additions & 0 deletions source/module_io/json_output/general_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ void gen_general_info(Input *input)
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);

// AbacusJson::add_Json(version,false,"general_info", "version");
// AbacusJson::add_Json(commit,false,"general_info", "commit");
// AbacusJson::add_Json(input->device,false,"general_info", "device");
// AbacusJson::add_Json(mpi_num,false,"general_info", "mpi_num");
// AbacusJson::add_Json(omp_num,false,"general_info", "omp_num");
// AbacusJson::add_Json(input->pseudo_dir,false,"general_info", "pseudo_dir");
// AbacusJson::add_Json(input->orbital_dir,false,"general_info", "orbital_dir");
// AbacusJson::add_Json(input->stru_file,false,"general_info", "stru_file");
// AbacusJson::add_Json(input->kpoint_file,false,"general_info", "kpt_file");
// AbacusJson::add_Json(start_time_str,false,"general_info", "start_time");
// AbacusJson::add_Json(end_time_str,false,"general_info", "end_time");
}
#endif
} // namespace Json
5 changes: 4 additions & 1 deletion source/module_io/json_output/general_info.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#ifndef GENERAL_INFO_H
#define GENERAL_INFO_H
#include "module_io/input.h"

/**
Expand All @@ -8,4 +10,5 @@ namespace Json
#ifdef __RAPIDJSON
void gen_general_info(Input *input);
#endif
}
}
#endif
Loading

0 comments on commit 0c42fb9

Please sign in to comment.