File IO¶
QAR¶
|
|
|
|
|
|
Parameter controls the size of a single qar file in number of bytes. |
|
|
Return contents of file as str |
|
Return contents of file as bytes |
|
|
|
|
|
|
|
Pickle¶
|
only save from node 0 when is_sync_node mk_file_dirs_info(path) |
|
all the nodes read the same data if is_sync_node: one node read and broadcast to other nodes else: all nodes individually read the data |
|
all the nodes compute or load the same data if is_sync_node |
LatData¶
Multi-dimension array data structure for IO.
File format description¶
FILE-HEADER
BINARY-DATA
FILE-HEADER
example:
#!/usr/bin/env lat-io-glimpse
data_size
128
ndim: 3
"tsep"[4]: "0" "1" "2" "3"
"op"[2]: "0" "1"
"re-im"[2]: "re" "im"
crc32: 77A655DB
END_HEADER
BINARY-DATA
description:
Consist of the data stored in double precision (little endian) in sequential order as a standard C multidimensional array.
|
by default, return list can be used as the input argument for ld.set_info or mk_lat_data |
|
|
|
|
|
only set LatData shape if it is initially empty otherwise only set data and ignore shape completely dim_names should be a list of names for each dimension |
|
|
|
|
|
|
|
Load |
Example: examples-py/lat-io.py
#!/usr/bin/env python3
import qlat as q
import numpy as np
import os
q.begin_with_mpi()
q.qremove_all_info("results")
q.qmkdir_info("results")
rs = q.RngState("test")
info_list = [
[ "dim1", 4, ],
[ "dim2 name", 3, ],
[ "dim3", 2, [ "u", "d", ], ],
[ "dim4", 5, ],
]
ld = q.mk_lat_data(info_list)
q.displayln_info(ld.info())
rs.copy().g_rand_fill(np.asarray(ld).ravel())
arr = ld.to_numpy()
if q.get_id_node() == 0:
ld.save("results/ld.lat")
q.sync_node()
ld = q.LatData()
ld.load("results/ld.lat")
assert q.qnorm(np.asarray(ld) - arr) == 0
ld1 = q.load_lat_data("results/ld.lat")
assert q.qnorm(np.asarray(ld1) - arr) == 0
ld1 = q.mk_lat_data_real_f(info_list)
q.displayln_info(ld1.info())
ld1 @= ld
arr1 = ld1.to_numpy()
if q.get_id_node() == 0:
ld1.save("results/ld1.latf")
q.sync_node()
ld1 = q.LatDataRealF()
ld1.load("results/ld1.latf")
assert q.qnorm(np.asarray(ld1) - arr1) == 0
ld2 = q.mk_lat_data_long(info_list)
arr2 = ld2[:]
arr2.ravel()[:] = np.arange(len(arr2.ravel()))
if q.get_id_node() == 0:
ld2.save("results/ld2.latl")
q.sync_node()
ld2 = q.LatDataLong()
ld2.load("results/ld2.latl")
assert q.qnorm(ld2[:] - arr2) == 0
ld3 = q.mk_lat_data_int(info_list)
arr3 = ld3[:]
arr3.ravel()[:] = np.arange(len(arr3.ravel()))
if q.get_id_node() == 0:
ld3.save("results/ld3.latl")
q.sync_node()
ld3 = q.LatDataInt()
ld3.load("results/ld3.latl")
assert q.qnorm(ld3[:] - arr3) == 0
q.check_all_files_crc32_info("results")
q.timer_display()
q.end_with_mpi()
q.displayln_info(f"CHECK: finished successfully.")
C++ example: examples-cpp/latio/main.cpp
#include <qutils/lat-io.h>
namespace qlat
{ //
inline void demo_c()
{
const Long n_tsep = 4;
const Long n_op = 2;
LatData ld;
ld.info.push_back(lat_dim_number("tsep", 0, n_tsep - 1));
ld.info.push_back(lat_dim_number("op", 0, n_op - 1));
ld.info.push_back(lat_dim_string("type", make_array<std::string>("a", "b")));
ld.info.push_back(lat_dim_re_im());
lat_data_alloc(ld);
set_zero(ld);
for (int i = 0; i < n_tsep; ++i) {
for (int j = 0; j < n_op; ++j) {
Vector<ComplexD> v = lat_data_cget(ld, make_array<Long>(i, j));
v[0] = (ComplexD)i + ii * (ComplexD)j;
v[1] = (ComplexD)j + ii * (ComplexD)i;
}
}
ld.save("results-data-c.lat");
LatData ld1;
ld1.load("results-data-c.lat");
displayln_info(show(ld1));
}
inline void demo_r()
{
const Long n_tsep = 4;
const Long n_op = 2;
LatData ld;
ld.info.push_back(lat_dim_number("tsep", 0, n_tsep - 1));
ld.info.push_back(lat_dim_number("op", 0, n_op - 1));
ld.info.push_back(lat_dim_string("type", make_array<std::string>("a", "b")));
lat_data_alloc(ld);
set_zero(ld);
for (int i = 0; i < n_tsep; ++i) {
for (int j = 0; j < n_op; ++j) {
Vector<double> v = lat_data_get(ld, make_array<Long>(i, j));
v[0] = i;
v[1] = j;
}
}
ld.save("results-data-r.lat");
LatData ld1;
ld1.load("results-data-r.lat");
displayln_info(show(ld1));
}
} // namespace qlat
int main(int argc, char* argv[])
{
demo_c();
demo_r();
displayln_info("CHECK: finished successfully.");
return 0;
}
C++ code: qlat-utils/include/qlat-utils/lat-io.h
#pragma once
#include <qlat-utils/crc32.h>
#include <qlat-utils/mpi-auto.h>
#include <qlat-utils/qar.h>
#include <qlat-utils/show.h>
#include <qlat-utils/timer.h>
#include <qlat-utils/utils-io.h>
#include <qlat-utils/utils-vec.h>
#include <qlat-utils/utils.h>
#include <stdint.h>
#include <zlib.h>
#include <cassert>
#include <string>
#include <vector>
namespace qlat
{ //
const std::string lat_data_header = "#!/usr/bin/env lat-io-glimpse\n";
// Recommended file extension ".lat"
const std::string lat_data_int_header = "#!/usr/bin/env lat-io-int-glimpse\n";
// Recommended file extension ".lati"
const std::string lat_data_long_header = "#!/usr/bin/env lat-io-long-glimpse\n";
// Recommended file extension ".latl"
const std::string lat_data_real_f_header = "#!/usr/bin/env lat-io-real-f-glimpse\n";
// Recommended file extension ".latf"
struct API LatDim {
std::string name;
Long size; // size of this dimension
std::vector<std::string> indices; // indices names
// (default: "-1", "-2", "-3", ...)
// If indices.size() < size then example
// will be indices[0], indices[1], "-3",
// "-4", ... Won't check duplication (when
// assess, search from left to right)
//
LatDim() { size = 0; }
};
typedef std::vector<LatDim> LatInfo;
bool is_lat_info_complex(const LatInfo& info);
LatDim lat_dim_re_im();
LatDim lat_dim_number(const std::string& name, const Long start, const Long end,
const Long inc = 1);
std::string show(const LatDim& dim);
std::string show(const LatInfo& info);
LatDim read_lat_dim(const std::string& str);
LatInfo read_lat_info(const std::string& str);
inline Long lat_info_size(const LatInfo& info, const Int level = 0)
{
Long total = 1;
for (Int i = level; i < (Int)info.size(); ++i) {
total *= info[i].size;
}
return total;
}
template <class VecS>
LatDim lat_dim_string(const std::string& name, const VecS& indices)
{
LatDim dim;
dim.name = name;
dim.size = indices.size();
for (Int i = 0; i < dim.size; ++i) {
dim.indices.push_back(indices[i]);
}
return dim;
}
inline Long lat_dim_idx(const LatDim& dim, const std::string& idx)
// return the Long idx_int that dim.indices[idx_int] contains the std::string&
// idx. Will check if the idx_int is unique.
//
// For dim.indices does not cover the entire range, will require exact match or
// (- read_long(idx) - 1). Default index being -idx-1.
{
if ((Long)dim.indices.size() == 0) {
Long i = read_long(idx);
if (i >= 0) {
qassert(i < dim.size);
return i;
} else {
i = -i - 1;
qassert(i < dim.size);
return i;
}
} else if ((Long)dim.indices.size() == dim.size) {
for (Long i = 0; i < (Long)dim.indices.size(); ++i) {
if (idx == dim.indices[i]) {
return i;
}
}
std::vector<Long> possible_i_vec;
for (Long i = 0; i < (Long)dim.indices.size(); ++i) {
if (dim.indices[i].find(idx) != std::string::npos) {
possible_i_vec.push_back(i);
}
}
qassert(possible_i_vec.size() == 1);
return possible_i_vec[0];
} else {
qassert((Long)dim.indices.size() <= dim.size);
for (Long i = 0; i < (Long)dim.indices.size(); ++i) {
if (idx == dim.indices[i]) {
return i;
}
}
const Long i = -read_long(idx) - 1;
qassert((Long)dim.indices.size() <= i and i < dim.size);
return i;
}
}
inline Long lat_dim_idx(const LatDim& dim, const Long& idx)
{
qassert((Long)dim.indices.size() <= dim.size);
qassert(0 <= idx and idx < dim.size);
return idx;
}
template <class VecS>
Long lat_info_offset(const LatInfo& info, const VecS& idx)
// will return offset at the level the idx specify
// VecS can be std::vector<std::string> or std::vector<Long>
// or can be array of certain length
{
qassert((Long)idx.size() <= (Long)info.size());
Long ret = 0;
for (Int i = 0; i < (Int)idx.size(); ++i) {
const Long k = lat_dim_idx(info[i], idx[i]);
ret = ret * info[i].size + k;
}
return ret;
}
inline std::string idx_name(const LatDim& dim, const Long idx)
{
if (0 == (Long)dim.indices.size()) {
return show(idx);
} else if (idx < (Long)dim.indices.size()) {
return dim.indices[idx];
} else {
return show(-idx - 1);
}
}
inline bool operator==(const LatDim& d1, const LatDim& d2)
{
// return d1.name == d2.name and d1.size == d2.size and d1.indices ==
// d2.indices;
return d1.name == d2.name and d1.size == d2.size;
}
inline bool operator!=(const LatDim& d1, const LatDim& d2)
{
return not(d1 == d2);
}
// ------------------------------------------
template <class T>
struct API LatDataT {
LatInfo info;
std::vector<T> res;
//
LatDataT() { init(); };
//
void init()
{
clear(info);
clear(res);
res.resize(1);
res[0] = 0.0;
}
//
void load(QFile& qfile);
void load(const std::string& fn)
{
QFile qfile = qfopen(fn, "r");
load(qfile);
qfclose(qfile);
}
//
void save(QFile& qfile) const;
void save(const std::string& fn) const
{
QFile qfile = qfopen(fn + ".partial", "w");
save(qfile);
qfclose(qfile);
qrename(fn + ".partial", fn);
};
//
void load_str(std::string& content)
// Allow to destroy `content` to be more efficient.
{
QFile qfile =
qfopen(QFileType::String, "/ load LatData /", QFileMode::Read, content);
load(qfile);
qfclose(qfile);
}
std::string save_str() const
{
QFile qfile =
qfopen(QFileType::String, "/ save LatData /", QFileMode::Write);
save(qfile);
const std::string ret = qfile.content();
qfclose(qfile);
return ret;
}
//
bool is_complex() const;
Int ndim() const;
T* data() { return res.data(); }
const T* data() const { return res.data(); }
};
template <class T>
bool LatDataT<T>::is_complex() const
{
return is_lat_info_complex(info);
}
template <class T>
Int LatDataT<T>::ndim() const
{
if (is_lat_info_complex(info)) {
return info.size() - 1;
} else {
return info.size();
}
}
template <class T>
struct IsDataVectorType<LatDataT<T>> {
using DataType = T;
using BasicDataType = typename IsDataValueType<DataType>::BasicDataType;
using ElementaryType = typename IsDataValueType<DataType>::ElementaryType;
static constexpr bool value = is_data_value_type<DataType>();
};
// ------------------------------------------
template <class T>
bool is_initialized(const LatDataT<T>& ld)
{
return ld.res.size() > 0;
}
template <class T>
void clear(LatDataT<T>& ld)
{
ld.init();
}
template <class T>
Long lat_data_size(const LatDataT<T>& ld, const Int level = 0)
{
return lat_info_size(ld.info, level);
}
template <class T>
void lat_data_alloc(LatDataT<T>& ld)
{
ld.res.resize(lat_data_size(ld));
}
template <class T>
bool is_zero(const LatDataT<T>& ld)
{
if (ld.info.size() > 0) {
return false;
}
if (ld.res.size() > 1) {
return false;
}
qassert(ld.res.size() == 1);
return ld.res[0] == 0;
}
template <class T>
Vector<T> get_data(const LatDataT<T>& ld)
{
return get_data(ld.res);
}
template <class T, class VecS>
Long lat_data_offset(const LatDataT<T>& ld, const VecS& idx)
// will return offset at the level the idx specify
// VecS can be std::vector<std::string> or std::vector<Long>
// or can be array of certain length
{
return lat_info_offset(ld.info, idx);
}
template <class T>
void set_zero(LatDataT<T>& ld)
{
std::memset(ld.res.data(), 0, ld.res.size() * sizeof(T));
}
template <class T>
bool is_matching(const LatDataT<T>& ld1, const LatDataT<T>& ld2)
{
return ld1.res.size() == ld2.res.size() and ld1.info == ld2.info;
}
template <class T, class VecS>
Vector<RealD> lat_data_get(LatDataT<T>& ld, const VecS& idx)
{
const Long offset = lat_data_offset(ld, idx);
const Long size = lat_data_size(ld, idx.size());
qassert(offset * size + size <= (Long)ld.res.size());
Vector<T> ret(&ld.res[offset * size], size);
return ret;
}
template <class T, class VecS>
Vector<RealD> lat_data_get_const(const LatDataT<T>& ld, const VecS& idx)
// Be cautious about the const property
// 改不改靠自觉
{
const Long offset = lat_data_offset(ld, idx);
const Long size = lat_data_size(ld, idx.size());
qassert(offset * size + size <= (Long)ld.res.size());
Vector<T> ret(&ld.res[offset * size], size);
return ret;
}
template <class T>
Vector<T> lat_data_get(LatDataT<T>& ld)
{
array<Int, 0> idx;
return lat_data_get(ld, idx);
}
template <class T>
Vector<T> lat_data_get_const(const LatDataT<T>& ld)
// Be cautious about the const property
// 改不改靠自觉
{
array<Int, 0> idx;
return lat_data_get_const(ld, idx);
}
template <class T>
Int glb_sum(LatDataT<T>& ld)
{
return glb_sum_vec(get_data(ld.res));
}
template <class T>
Int bcast(LatDataT<T>& ld, const Int root)
{
TIMER("bcast(ld,root)");
if (1 == get_num_node()) {
return 0;
}
Int ret = 0;
std::string info_str;
if (get_id_node() == root) {
info_str = show(ld.info);
}
ret = bcast_val(info_str, root);
if (ret != 0) {
return ret;
}
if (get_id_node() == root) {
qassert((Long)ld.res.size() == lat_data_size(ld));
} else {
ld.info = read_lat_info(info_str);
lat_data_alloc(ld);
}
ret = bcast_val(ld.res, root);
return ret;
}
template <class T>
void lat_data_load_sync_node(LatDataT<T>& ld, const std::string& path)
{
TIMER("lat_data_load_sync_node(ld)");
ld.init();
if (get_id_node() == 0) {
ld.load(path);
}
Int ret = bcast(ld, 0);
qassert(ret == 0);
}
template <class T>
void lat_data_save_info(const std::string& path, const LatDataT<T>& ld)
{
TIMER("lat_data_save_info");
if (get_id_node() == 0) {
ld.save(path);
}
}
// ------------------------------------------
struct API LatDataInt : LatDataT<Int> {
};
template <>
void LatDataT<Int>::load(QFile& qfile);
template <>
void LatDataT<Int>::save(QFile& qfile) const;
inline LatDataInt lat_data_int_load_sync_node(const std::string& path)
{
LatDataInt ld;
lat_data_load_sync_node(ld, path);
return ld;
}
template <>
struct IsDataVectorType<LatDataInt> {
using DataType = Int;
using BasicDataType = typename IsDataValueType<DataType>::BasicDataType;
using ElementaryType = typename IsDataValueType<DataType>::ElementaryType;
static constexpr bool value = is_data_value_type<DataType>();
};
// ------------------------------------------
struct API LatDataLong : LatDataT<Long> {
};
template <>
void LatDataT<Long>::load(QFile& qfile);
template <>
void LatDataT<Long>::save(QFile& qfile) const;
inline LatDataLong lat_data_long_load_sync_node(const std::string& path)
{
LatDataLong ld;
lat_data_load_sync_node(ld, path);
return ld;
}
template <>
struct IsDataVectorType<LatDataLong> {
using DataType = Long;
using BasicDataType = typename IsDataValueType<DataType>::BasicDataType;
using ElementaryType = typename IsDataValueType<DataType>::ElementaryType;
static constexpr bool value = is_data_value_type<DataType>();
};
// ------------------------------------------
struct API LatData;
struct API LatDataRealF;
// ------------------------------------------
struct API LatData : LatDataT<RealD> {
LatData() = default;
LatData(const LatData&) = default;
LatData(LatData&&) noexcept = default;
LatData& operator=(const LatData&) = default;
LatData& operator=(LatData&&) noexcept = default;
LatData(const LatDataRealF& ld);
LatData& operator=(const LatDataRealF& ld);
};
template <>
void LatDataT<RealD>::load(QFile& qfile);
template <>
void LatDataT<RealD>::save(QFile& qfile) const;
inline LatData lat_data_load_sync_node(const std::string& path)
{
LatData ld;
lat_data_load_sync_node(ld, path);
return ld;
}
template <>
struct IsDataVectorType<LatData> {
using DataType = RealD;
using BasicDataType = typename IsDataValueType<DataType>::BasicDataType;
using ElementaryType = typename IsDataValueType<DataType>::ElementaryType;
static constexpr bool value = is_data_value_type<DataType>();
};
// ------------------------------------------
std::string show(const LatData& ld);
std::string show_real(const LatData& ld);
std::string show_complex(const LatData& ld);
void print(const LatData& ld);
const LatData& operator*=(LatData& ld, const RealD factor);
const LatData& operator*=(LatData& ld, const ComplexD& factor);
LatData operator*(const LatData& ld, const RealD factor);
LatData operator*(const RealD factor, const LatData& ld);
LatData operator*(const LatData& ld, const ComplexD& factor);
LatData operator*(const ComplexD& factor, const LatData& ld);
const LatData& operator+=(LatData& ld, const LatData& ld1);
const LatData& operator-=(LatData& ld, const LatData& ld1);
LatData operator+(const LatData& ld, const LatData& ld1);
LatData operator-(const LatData& ld, const LatData& ld1);
LatData operator-(const LatData& ld);
template <class VecS>
Vector<ComplexD> lat_data_cget(LatData& ld, const VecS& idx)
{
qassert(is_lat_info_complex(ld.info));
qassert((Long)idx.size() < (Long)ld.info.size());
const Long offset = lat_data_offset(ld, idx);
const Long size = lat_data_size(ld, idx.size());
qassert(size % 2 == 0);
qassert(offset * size + size <= (Long)ld.res.size());
Vector<ComplexD> ret((ComplexD*)&ld.res[offset * size], size / 2);
return ret;
}
template <class VecS>
Vector<ComplexD> lat_data_cget_const(const LatData& ld, const VecS& idx)
// Be cautious about the const property
// 改不改靠自觉
{
qassert(is_lat_info_complex(ld.info));
qassert((Long)idx.size() < (Long)ld.info.size());
const Long offset = lat_data_offset(ld, idx);
const Long size = lat_data_size(ld, idx.size());
qassert(size % 2 == 0);
qassert(offset * size + size <= (Long)ld.res.size());
Vector<ComplexD> ret((ComplexD*)&ld.res[offset * size], size / 2);
return ret;
}
inline Vector<ComplexD> lat_data_cget(LatData& ld)
{
array<Int, 0> idx;
return lat_data_cget(ld, idx);
}
inline Vector<ComplexD> lat_data_cget_const(const LatData& ld)
// Be cautious about the const property
// 改不改靠自觉
{
array<Int, 0> idx;
return lat_data_cget_const(ld, idx);
}
inline RealD qnorm(const LatData& ld) { return qnorm(ld.res); }
// ------------------------------------------
struct API LatDataRealF : LatDataT<RealF> {
LatDataRealF() = default;
LatDataRealF(const LatDataRealF&) = default;
LatDataRealF(LatDataRealF&&) noexcept = default;
LatDataRealF& operator=(const LatDataRealF&) = default;
LatDataRealF& operator=(LatDataRealF&&) noexcept = default;
LatDataRealF(const LatData& ld);
LatDataRealF& operator=(const LatData& ld);
};
template <>
void LatDataT<RealF>::load(QFile& qfile);
template <>
void LatDataT<RealF>::save(QFile& qfile) const;
inline LatDataRealF lat_data_real_f_load_sync_node(const std::string& path)
{
LatDataRealF ld;
lat_data_load_sync_node(ld, path);
return ld;
}
template <>
struct IsDataVectorType<LatDataRealF> {
using DataType = RealF;
using BasicDataType = typename IsDataValueType<DataType>::BasicDataType;
using ElementaryType = typename IsDataValueType<DataType>::ElementaryType;
static constexpr bool value = is_data_value_type<DataType>();
};
} // namespace qlat
Gauge Field¶
|
|
|
Save with the standard NERSC format |
|
Load with the standard NERSC format |
Gauge Transform¶
|
|
|
Save as double precision with the generic Field format |
|
Load as double precision with the generic Field format |
|
Save with the format used in CPS |
|
Load with the format used in CPS |
FieldBase¶
Support np.asarray(f)
.
|
|
|
Generic save for Field object save Field directly (without any conversion of endianness or precision) possible way to call: f.save_direct(path) f.save_direct(sfw, fn) |
|
Generic load for Field object load Field directly (without any conversion of endianness or precision) Field geo and multiplicity will be determined during loading possible way to call: f.load_direct(path) f.load_direct(sfr, fn) |
|
Generic save for 64-bit size element Field object save 64-bit Field (do conversion of endianness) |
|
Generic load for 64-bit size element Field object load 64-bit Field (do conversion of endianness) |
|
Generic save for double element Field object save double Field as double (do conversion of endianness) |
|
Generic load for double Field object load double Field (do conversion of endianness) |
|
Generic save for double element Field object save double Field as float (do conversion of endianness and precision) |
|
Generic load for double Field object load double Field from float(do conversion of endianness or precision) |
|
self needs to be FieldRealF |
|
self can be any FieldBase subtype but need to be actually contains double precision numbers |
|
Convert between the native endianness and the endianness specified by |
|
return new Field(ctype) with the same content |
|
assign from f with the same content but possibly different type |
FieldSelection¶
|
|
|
|
|
|
|
|
SelectedFieldBase¶
Support np.asarray(sf)
.
|
|
|
Generic save for SelectedField object possible way to call: f.save_direct(path) # has some limitations f.save_direct(sfw, fn) |
|
Generic load for SelectedField object possible way to call: f.load_direct(path) # has some limitations f.load_direct(sfr, fn) if self.fsel is None, self.fsel will be set during f.load_direct(sfr, fn) |
|
Generic save for SelectedField object with conversion |
|
Generic load for SelectedField object with conversion |
|
Generic save for SelectedField object with conversion |
|
Generic load for SelectedField object with conversion |
Generic save for SelectedField object with conversion |
|
Generic load for SelectedField object with conversion |
|
|
|
|
|
|
PointsSelection¶
Support np.asarray(psel)
.
|
|
|
|
|
|
return xg for all selected points shape = (psel.n_points, 4,) |
SelectedPointsBase¶
Support np.asarray(sp)
.
|
|
|
|
|
need to be already initialized with ctype and psel arr.shape[0] == n_points |
|
|
|
|
|