mirror of
https://github.com/triqs/dft_tools
synced 2024-12-24 13:23:37 +01:00
parameters & wrapper
- new parameter class : parameters are viewed as form, built in C++, and filled in C++/python. Each field of the form as a precise C++ type (erased using standard techniques). First tests ok, to be reread/checked. TODO : serialization is commented. Lead to long compilation time & large code due to boost::serialization. Use h5 when possible. - wrapper : - separated the converters of the wrapped type in the TRIQS library - necessary for parameters (it used outside an .so) and potentially other codes, outside an .so module
This commit is contained in:
parent
a9bcc33c7e
commit
af084f5d59
@ -335,9 +335,9 @@ enable_testing()
|
||||
option(Build_Documentation "Build the documentation ?" OFF)
|
||||
option(Build_PDF_Documentation "Build the pdf documentation ?" OFF)
|
||||
|
||||
#------------------------
|
||||
#------------------------------------------------------
|
||||
# link libs for shared libs or for pytriqs
|
||||
#------------------------
|
||||
#------------------------------------------------------
|
||||
|
||||
set(TRIQS_LINK_LIBS
|
||||
${TRIQS_LIBRARY_PYTHON}
|
||||
@ -351,39 +351,39 @@ set(TRIQS_LINK_LIBS
|
||||
# remove this dep to C++
|
||||
include_directories(${TRIQS_SOURCE_DIR})
|
||||
|
||||
#------------------------
|
||||
# General triqs libraries
|
||||
#------------------------
|
||||
#--------------------------------
|
||||
# General C++ compilation flags
|
||||
#--------------------------------
|
||||
|
||||
message( STATUS "TRIQS_CXX_DEFINITIONS = ${TRIQS_CXX_DEFINITIONS}")
|
||||
#message( STATUS "TRIQS_CXX_DEFINITIONS = ${TRIQS_CXX_DEFINITIONS}")
|
||||
|
||||
# needed for utility/first_include.hpp that includes either the triqs_config.h installed in the proper directory
|
||||
# (Case of an installed lib) or the triqs_config.h just generated in the built dir (when compiling the lib itself).
|
||||
add_definitions ( ${TRIQS_CXX_DEFINITIONS} -DTRIQS_BUILDING_LIBRARY -I ${CMAKE_BINARY_DIR}/Config)
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# pytriqs modules : MUST be before TRIQS, to have the py_converters
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
if (PythonSupport)
|
||||
message( STATUS "-------- Preparing python extension modules -------------")
|
||||
add_subdirectory(${TRIQS_SOURCE_DIR}/pytriqs )
|
||||
endif (PythonSupport)
|
||||
|
||||
#------------------------
|
||||
# General triqs libraries
|
||||
#------------------------
|
||||
|
||||
add_subdirectory(${TRIQS_SOURCE_DIR}/triqs triqs)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
list (REMOVE_DUPLICATES TRIQS_LINK_LIBS)
|
||||
endif( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
|
||||
#------------------------
|
||||
# Applications
|
||||
#------------------------
|
||||
|
||||
#add_subdirectory(${TRIQS_SOURCE_DIR}/applications )
|
||||
|
||||
#------------------------
|
||||
# pytriqs modules
|
||||
#------------------------
|
||||
if (PythonSupport)
|
||||
message( STATUS "-------- Preparing python modules -------------")
|
||||
add_subdirectory(${TRIQS_SOURCE_DIR}/pytriqs )
|
||||
endif (PythonSupport)
|
||||
|
||||
#------------------------
|
||||
# tests
|
||||
#------------------------
|
||||
## Remove the test from the build ?
|
||||
|
||||
option(Build_Triqs_General_Tools_Test "Build the test of the general tool ? ( array class , ... ) " ON)
|
||||
if (Build_Triqs_General_Tools_Test)
|
||||
message( STATUS "-------- Preparing tests -------------")
|
||||
|
@ -6,21 +6,30 @@ include_directories(${PYTHON_INCLUDE_DIRS} ${PYTHON_NUMPY_INCLUDE_DIR})
|
||||
# ModuleName = the python name of the module
|
||||
# ModuleDest = path in the pytriqs tree [ FOR INSTALLATION ONLY] IMPROVE MAKE THIS OPTIONAL (for test)
|
||||
|
||||
#EXECUTE_PROCESS(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/pytriqs/converters/)
|
||||
include_directories( ${CMAKE_BINARY_DIR})
|
||||
|
||||
macro (triqs_python_extension ModuleName)
|
||||
message(STATUS "TRIQS: Preparing extension module ${ModuleName} with the interpreter ${TRIQS_PYTHON_INTERPRETER} ")
|
||||
message(STATUS "Preparing extension module ${ModuleName}")
|
||||
|
||||
SET(wrap_name ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_wrap.cpp)
|
||||
SET(converter_name ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_converter.cpp)
|
||||
|
||||
# Adjust pythonpath so that pytriqs is visible and the wrap_generator too...
|
||||
# pytriqs needed since we import modules with pure python method to extract the doc..
|
||||
add_custom_command(OUTPUT ${wrap_name} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${ModuleName}_desc.py
|
||||
COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/pytriqs/wrap_generator:${CMAKE_BINARY_DIR}/ ${PYTHON_INTERPRETER} ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_desc.py ${CMAKE_SOURCE_DIR}/pytriqs/wrap_generator/wrapper.mako.cpp ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_wrap.cpp )
|
||||
add_custom_command(OUTPUT ${wrap_name} ${converter_name} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${ModuleName}_desc.py
|
||||
COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/pytriqs/wrap_generator:${CMAKE_BINARY_DIR}/ ${PYTHON_INTERPRETER} ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_desc.py ${CMAKE_SOURCE_DIR}/pytriqs/wrap_generator/wrapper.mako.cpp ${wrap_name} ${CMAKE_SOURCE_DIR}/pytriqs/wrap_generator/py_converter_wrapper.mako.hpp ${converter_name} )
|
||||
|
||||
add_custom_target(python_wrap_${ModuleName} ALL DEPENDS ${wrap_name})
|
||||
add_dependencies(python_wrap_${ModuleName} py_copy)
|
||||
set_property (GLOBAL APPEND PROPERTY TRIQS_PY_CONVERTERS_CPP_LIST "${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_converter.cpp")
|
||||
set_property (GLOBAL APPEND PROPERTY TRIQS_PY_CONVERTERS_TARGETS "python_wrap_${ModuleName}")
|
||||
|
||||
add_custom_target(python_wrap_${ModuleName} ALL DEPENDS ${wrap_name} ${converter_name})
|
||||
#//add_custom_target(${ModuleName}_converter.cpp ALL DEPENDS ${wrap_name})
|
||||
|
||||
add_dependencies(python_wrap_${ModuleName} py_copy ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_desc.py )
|
||||
|
||||
add_library(${ModuleName} MODULE ${wrap_name})
|
||||
set_target_properties(${ModuleName} PROPERTIES PREFIX "") #eliminate the lib in front of the module name
|
||||
set_target_properties(${ModuleName} PROPERTIES PREFIX "") #eliminate the lib in front of the module name
|
||||
target_link_libraries(${ModuleName} ${TRIQS_LINK_LIBS} triqs)
|
||||
|
||||
if (${ARGN} MATCHES "")
|
||||
|
@ -27,7 +27,9 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/utility/mpi.py.in ${CMAKE_CURRENT_BIN
|
||||
|
||||
install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST})
|
||||
|
||||
# All subdirs
|
||||
add_all_subdirectories_with_cmakelist()
|
||||
|
||||
#
|
||||
add_custom_target(wrap_clean COMMAND find ${CMAKE_BINARY_DIR} -name \"*.cpp\" |xargs rm)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
from wrap_generator import *
|
||||
|
||||
module = module_(full_name = "pytriqs.gf.local.gf", doc = "Local Green functions ...")
|
||||
module.add_include("<typeindex>")
|
||||
module.add_include("<triqs/gfs.hpp>")
|
||||
module.add_include("<triqs/gfs/local/functions.hpp>")
|
||||
module.add_include("<triqs/gfs/local/pade.hpp>")
|
||||
@ -302,9 +303,13 @@ def make_gf( py_type, c_tag, is_complex_data = True, is_im = False) :
|
||||
signature = "void()",
|
||||
doc = "Put the Green function to 0")
|
||||
|
||||
# Pure python methods
|
||||
# Pure python methods
|
||||
g.add_pure_python_method("pytriqs.gf.local._gf_%s.plot"%c_tag, py_name = "_plot_")
|
||||
|
||||
g.add_method(py_name = "_as_C_pointer",
|
||||
calling_pattern = 'auto result = PyCapsule_New(new std::pair<void *,std::type_index>(&self_c,typeid(self_c)),NULL,NULL)',
|
||||
signature = "PyObject*()")
|
||||
|
||||
return g
|
||||
|
||||
########################
|
||||
@ -391,4 +396,5 @@ module.add_function(name = "make_gf_from_inverse_fourier", signature="gf_view<re
|
||||
|
||||
if __name__ == '__main__' :
|
||||
module.generate_code(mako_template = sys.argv[1], wrap_file = sys.argv[2])
|
||||
|
||||
module.generate_py_converter_header(mako_template = sys.argv[3], wrap_file = sys.argv[4])
|
||||
|
||||
|
@ -4,7 +4,7 @@ SET(PYTHON_SOURCES
|
||||
|
||||
install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/parameters)
|
||||
|
||||
cython_module(Parameters parameters parameters )
|
||||
triqs_python_extension(parameters parameters )
|
||||
|
||||
FILE(GLOB all_pxd_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.pxd )
|
||||
install (FILES ${all_pxd_files} DESTINATION "include/pytriqs/parameters")
|
||||
|
@ -1,21 +0,0 @@
|
||||
from libcpp.string cimport string as std_string
|
||||
from libcpp.vector cimport vector
|
||||
cdef extern from "triqs/parameters/parameters.hpp" namespace "triqs::parameters" :
|
||||
|
||||
cdef cppclass _object "triqs::utility::_object":
|
||||
#cdef cppclass _object "triqs::parameters::_object":
|
||||
_object()
|
||||
|
||||
#cdef cppclass parameters " triqs::parameters::parameters" :
|
||||
cdef cppclass parameters "triqs::utility::parameters" :
|
||||
parameters()
|
||||
_object operator[](std_string &)
|
||||
std_string print_ "print" ()
|
||||
|
||||
cdef cppclass parameter_defaults "triqs::utility::parameter_defaults" :
|
||||
parameter_defaults()
|
||||
vector[vector[std_string]] generate_help()
|
||||
|
||||
|
||||
cdef class Parameters:
|
||||
cdef parameters _c
|
@ -1,89 +0,0 @@
|
||||
from dcomplex cimport *
|
||||
from shared_ptr cimport *
|
||||
from arrays cimport *
|
||||
from inserter_in_map cimport *
|
||||
from libcpp.pair cimport pair
|
||||
from libcpp.vector cimport vector
|
||||
from libcpp.string cimport string as std_string
|
||||
from cython.operator cimport dereference as deref, preincrement as inc #dereference and increment operator
|
||||
import numpy as np
|
||||
|
||||
cdef extern from "triqs/parameters/parameters.hpp" namespace "triqs::parameters" :
|
||||
|
||||
cdef cppclass extract_strict "triqs::utility::extract_strict" [T]:
|
||||
extract_strict()
|
||||
bint is_possible(_object &)
|
||||
T invoke(_object &)
|
||||
|
||||
cdef class Parameters:
|
||||
"""
|
||||
"""
|
||||
#cdef parameters _c
|
||||
def __init__(self) :
|
||||
""" """
|
||||
self._c = parameters()
|
||||
|
||||
def __getitem__(self, key) :
|
||||
cdef _object _o = self._c[key]
|
||||
if extract_strict[long]().is_possible(_o) : return extract_strict[long]().invoke(_o)
|
||||
if extract_strict[double]().is_possible(_o) : return extract_strict[double]().invoke(_o)
|
||||
if extract_strict[std_string]().is_possible(_o) : return extract_strict[std_string]().invoke(_o)
|
||||
if extract_strict[int]().is_possible(_o) : return extract_strict[int]().invoke(_o)
|
||||
|
||||
if extract_strict[parameters]().is_possible(_o) :
|
||||
pp = Parameters()
|
||||
pp._c = extract_strict[parameters]().invoke(_o)
|
||||
return pp
|
||||
|
||||
if extract_strict[array_view[long, ONE]]().is_possible(_o) : return extract_strict[array_view[long,ONE]]().invoke(_o).to_python()
|
||||
if extract_strict[array_view[long, TWO]]().is_possible(_o) : return extract_strict[array_view[long,TWO]]().invoke(_o).to_python()
|
||||
if extract_strict[array_view[long, THREE]]().is_possible(_o): return extract_strict[array_view[long,THREE]]().invoke(_o).to_python()
|
||||
if extract_strict[array_view[double,ONE]]().is_possible(_o) : return extract_strict[array_view[double,ONE]]().invoke(_o).to_python()
|
||||
if extract_strict[array_view[double,TWO]]().is_possible(_o) : return extract_strict[array_view[double,TWO]]().invoke(_o).to_python()
|
||||
if extract_strict[array_view[double,THREE]]().is_possible(_o) : return extract_strict[array_view[double,THREE]]().invoke(_o).to_python()
|
||||
|
||||
if extract_strict[vector[std_string]]().is_possible(_o) : return extract_strict[vector[std_string]]().invoke(_o)
|
||||
if extract_strict[vector[long]]().is_possible(_o) : return extract_strict[vector[long]]().invoke(_o)
|
||||
|
||||
raise ValueError, "Can not extract the key %s"%key
|
||||
|
||||
def __setitem__(self, key, rhs) :
|
||||
if isinstance(rhs, int) : inserter_in_map[parameters,long](self._c)(key, rhs)
|
||||
elif isinstance(rhs, float) : inserter_in_map[parameters,double](self._c)(key, rhs)
|
||||
elif isinstance(rhs, str) : inserter_in_map[parameters,std_string](self._c)(key, rhs)
|
||||
elif isinstance(rhs, Parameters) : inserter_in_map[parameters,parameters](self._c)(key, (<Parameters>rhs)._c)
|
||||
elif isinstance(rhs, dict) : self[key] = Parameters().update(rhs)
|
||||
elif isinstance(rhs, list) or isinstance(rhs,tuple) :
|
||||
if set([type(x) for x in rhs]) == set([type('')]) : # list or tuple of string
|
||||
inserter_in_map[parameters,vector[std_string]](self._c)(key, rhs)
|
||||
elif set([type(x) for x in rhs]) == set([type(1)]) : # list or tuple of int
|
||||
inserter_in_map[parameters,vector[long]](self._c)(key, rhs)
|
||||
else :
|
||||
raise TypeError, "List and tuple are not supported by Parameters. Please use numpy arrays"
|
||||
elif isinstance(rhs, np.ndarray) :
|
||||
try : inserter_in_map[parameters,array_view[long,ONE]](self._c)(key, array_view[long,ONE](rhs))
|
||||
except : pass
|
||||
try : inserter_in_map[parameters,array_view[long,TWO]](self._c)(key, array_view[long,TWO](rhs))
|
||||
except : pass
|
||||
try : inserter_in_map[parameters,array_view[long,THREE]](self._c)(key, array_view[long,THREE](rhs))
|
||||
except : pass
|
||||
try : inserter_in_map[parameters,array_view[double,ONE]](self._c)(key, array_view[double,ONE](rhs))
|
||||
except : pass
|
||||
try : inserter_in_map[parameters,array_view[double,TWO]](self._c)(key, array_view[double,TWO](rhs))
|
||||
except : pass
|
||||
try : inserter_in_map[parameters,array_view[double,THREE]](self._c)(key, array_view[double,THREE](rhs))
|
||||
except : pass
|
||||
else :
|
||||
raise TypeError, "Unknown object : key = %s, rhs = %s"%(key, rhs)
|
||||
|
||||
def __repr__(self) :
|
||||
return printer[parameters]()(self._c)
|
||||
|
||||
def update(self, d) :
|
||||
for k,v in d.items(): self[k]=v
|
||||
return self
|
||||
|
||||
def update2(self, **d) : return self.update(d)
|
||||
|
||||
|
||||
|
41
pytriqs/parameters/parameters_desc.py
Normal file
41
pytriqs/parameters/parameters_desc.py
Normal file
@ -0,0 +1,41 @@
|
||||
from wrap_generator import *
|
||||
|
||||
# The module
|
||||
module = module_(full_name = "pytriqs.parameters.parameters.my_module", doc = " Doc of my_module ")
|
||||
module.add_include("<triqs/parameters/parameters.hpp>")
|
||||
module.add_include("<triqs/utility/formatted_output.hpp>")
|
||||
module.add_using("namespace triqs::params")
|
||||
|
||||
# one class
|
||||
g = class_(
|
||||
py_type = "Parameters",
|
||||
c_type = "parameters",
|
||||
#serializable= "tuple",
|
||||
is_printable= True,
|
||||
hdf5 = True,
|
||||
# Add + for merging
|
||||
arithmetic = ("only_add")
|
||||
)
|
||||
|
||||
#add a constructor
|
||||
#g.add_constructor(doc = "DOC of constructor", args = [])
|
||||
|
||||
g.add_method(py_name = "help", calling_pattern = "auto result = triqs::utility::print_formatted(self_c.generate_help())", signature = "std::string()", doc = "help")
|
||||
|
||||
# add getitem/setitem ...
|
||||
g.add_getitem(signature = "PyObject *(const char * key)",
|
||||
calling_pattern = "PyObject * result = self_c[key].to_python()",
|
||||
doc = "")
|
||||
g.add_setitem(signature = "void(const char * key, PyObject * ob)",
|
||||
calling_pattern = """
|
||||
if (!self_c[key].from_python_convertible(ob)) return NULL; // early exit, the error is set by the converter
|
||||
self_c[key].set_from_python(ob);
|
||||
""",
|
||||
doc = "")
|
||||
|
||||
module.add_class(g)
|
||||
|
||||
if __name__ == '__main__' :
|
||||
module.generate_code(mako_template = sys.argv[1], wrap_file = sys.argv[2])
|
||||
module.generate_py_converter_header(mako_template = sys.argv[3], wrap_file = sys.argv[4])
|
||||
|
61
pytriqs/wrap_generator/py_converter_wrapper.mako.hpp
Normal file
61
pytriqs/wrap_generator/py_converter_wrapper.mako.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
// Specialization of py_converter to types wrapped by the wrap_generator.
|
||||
// DO NOT EDIT. Generated automatically by wrap_generator
|
||||
|
||||
%for file in module.include_list :
|
||||
%if file.startswith('<'):
|
||||
#include ${file}
|
||||
%else:
|
||||
#include "${file}"
|
||||
%endif
|
||||
%endfor
|
||||
|
||||
using dcomplex = std::complex<double>;
|
||||
|
||||
%for ns in module.using:
|
||||
using ${ns};
|
||||
%endfor
|
||||
|
||||
//#include <triqs/arrays.hpp>
|
||||
#include <triqs/python_tools/wrapper_tools.hpp>
|
||||
|
||||
namespace triqs { namespace py_tools {
|
||||
|
||||
%for n,t in enumerate(module.wrapped_types_by_me) :
|
||||
|
||||
template<> struct py_converter<${t}> {
|
||||
static void ** init();
|
||||
static PyObject * c2py(${t} const & x);
|
||||
static ${t}& py2c(PyObject * ob);
|
||||
static bool is_convertible(PyObject *ob, bool raise_exception);
|
||||
};
|
||||
|
||||
void ** py_converter<${t}>::init() {
|
||||
PyObject * mod = PyImport_ImportModule("${module.full_name}");
|
||||
if (mod ==NULL) return NULL;
|
||||
void ** table = (void **)PyCapsule_Import("${module.full_name}._exported_wrapper_convert_fnt", 0);
|
||||
return table;
|
||||
}
|
||||
|
||||
PyObject * py_converter<${t}>::c2py(${t} const & x){
|
||||
static void **wrapped_convert_fnt = init();
|
||||
if (wrapped_convert_fnt == NULL) return NULL;
|
||||
return ((PyObject * (*)(${t} const &)) wrapped_convert_fnt[3*${n}])(x);
|
||||
}
|
||||
|
||||
${t}& py_converter<${t}>::py2c(PyObject * ob){
|
||||
static void **wrapped_convert_fnt = init();
|
||||
if (wrapped_convert_fnt == NULL) std::terminate(); // It should never happen since py2c is called only is is_convertible is true (py_converter specs)
|
||||
return ((${t}& (*)(PyObject *)) wrapped_convert_fnt[3*${n}+1])(ob);
|
||||
}
|
||||
|
||||
bool py_converter<${t}>::is_convertible(PyObject *ob, bool raise_exception) {
|
||||
static void **wrapped_convert_fnt = init();
|
||||
if (wrapped_convert_fnt == NULL) {
|
||||
if (!raise_exception && PyErr_Occurred()) {PyErr_Print();PyErr_Clear();}
|
||||
return false;
|
||||
}
|
||||
return ((bool (*)(PyObject *,bool)) wrapped_convert_fnt[3*${n}+2])(ob,raise_exception);
|
||||
}
|
||||
%endfor
|
||||
}}
|
||||
|
@ -66,6 +66,8 @@ class cfunction :
|
||||
self.rtype = kw.pop("rtype", None)
|
||||
args = kw.pop('args',())
|
||||
for a in args: # put back the default if there is none
|
||||
if a[0] == 'const' : a = [' '.join(a[:2])] + list(a[2:])
|
||||
if a[1] == '*' : a = [' '.join(a[:2])] + list(a[2:])
|
||||
if len(a) == 2 : (t,n),d = a,None
|
||||
elif len(a) == 3 : t,n,d = a
|
||||
else : raise RuntimeError, "Syntax error in overload: args = %s"%args
|
||||
@ -265,15 +267,17 @@ class class_ :
|
||||
# expect a tuple : "algebra", "scalar1", "scalar2", etc...
|
||||
self.number_protocol = {}
|
||||
if arithmetic :
|
||||
add = arithmetic[0] in ("algebra", "abelian_group", "vector_space", "only_add")
|
||||
abelian_group = arithmetic[0] in ("algebra", "abelian_group", "vector_space")
|
||||
vector_space = arithmetic[0] in ("algebra", "vector_space")
|
||||
algebra = arithmetic[0] in ("algebra")
|
||||
if abelian_group :
|
||||
if add :
|
||||
# add
|
||||
add = pyfunction(py_name ="__add__")
|
||||
add.arity = 2
|
||||
add.add_overload (calling_pattern = "+", args = [(self.c_type,'x'), (self.c_type,'y')], rtype = self.c_type)
|
||||
self.number_protocol['add'] = add
|
||||
if abelian_group :
|
||||
#sub
|
||||
sub = pyfunction(py_name ="__sub__")
|
||||
sub.arity = 2
|
||||
@ -424,7 +428,6 @@ class module_ :
|
||||
Representation of a module
|
||||
Data :
|
||||
- name : name of the module
|
||||
- imported_modules : name of the modules to import (with their wrapped type converters)
|
||||
- doc : the doc string.
|
||||
- classes : dict : string -> class_. Key is the Python type
|
||||
- c_types : dict : string -> string. Correspondance Python type -> C++ type
|
||||
@ -433,7 +436,7 @@ class module_ :
|
||||
"""
|
||||
wrapped_types = {}
|
||||
|
||||
def __init__(self, full_name, imported_modules = (), doc = '') :
|
||||
def __init__(self, full_name, doc = '') :
|
||||
self.full_name = full_name
|
||||
self.name = full_name.rsplit('.',1)[-1]
|
||||
self.doc = doc
|
||||
@ -441,17 +444,11 @@ class module_ :
|
||||
self.functions = {}
|
||||
self.include_list = []
|
||||
self.wrapped_types_by_me = {}
|
||||
self.imported_wrapped_types = {}
|
||||
self.enums = []
|
||||
self.using =[]
|
||||
self.python_functions = {}
|
||||
self.hidden_python_functions = {}
|
||||
|
||||
assert type(imported_modules) in [type(()), type([])]
|
||||
for m_desc in imported_modules:
|
||||
m = importlib.import_module("%s_desc"%m_desc)
|
||||
self.imported_wrapped_types[m_desc] = m.module.wrapped_types
|
||||
|
||||
def add_class(self, cls):
|
||||
if cls.py_type in self.classes : raise IndexError, "The class %s already exists"%cls.py_type
|
||||
self.classes[cls.py_type] = cls
|
||||
@ -510,3 +507,15 @@ class module_ :
|
||||
rendered = tpl.render(module=self, regular_type_if_view_else_type= regular_type_if_view_else_type, is_type_a_view = is_type_a_view)
|
||||
with open(wrap_file,'w') as f:
|
||||
f.write(rendered)
|
||||
|
||||
def generate_py_converter_header(self, mako_template, wrap_file) :
|
||||
self.prepare_for_generation()
|
||||
tpl = Template(filename=mako_template)
|
||||
rendered = tpl.render(module=self)
|
||||
with open(wrap_file,'w') as f:
|
||||
f.write(rendered)
|
||||
|
||||
#def generate_code_and_header(self, arglist) :
|
||||
# self.generate_code(mako_template = arglist.argv[0], wrap_file = arglist.argv[1])
|
||||
# self.generate_py_converter_header(mako_template = arglist.argv[2], wrap_file = arglist.argv[3])
|
||||
|
||||
|
@ -23,32 +23,6 @@ using namespace triqs::py_tools;
|
||||
static PyObject * _module_hidden_python_function = NULL;
|
||||
%endif
|
||||
|
||||
//--------------------- Reconnect the types wrapped in exported modules -----------------------------
|
||||
|
||||
%for m, t_dic in module.imported_wrapped_types.items() :
|
||||
|
||||
static void ** _imported_wrapped_convert_fnt_from_${m}; // initialized in init function
|
||||
|
||||
%for n,t in enumerate(t_dic) :
|
||||
|
||||
namespace triqs { namespace py_tools {
|
||||
|
||||
template<> struct py_converter<${t}> {
|
||||
static PyObject * c2py(${t} const & x){
|
||||
return ((PyObject * (*)(${t} const &)) _imported_wrapped_convert_fnt_from_${m}[3*${n}])(x);
|
||||
}
|
||||
static ${t}& py2c(PyObject * ob){
|
||||
return ((${t}& (*)(PyObject *)) _imported_wrapped_convert_fnt_from_${m}[3*${n}+1])(ob);
|
||||
}
|
||||
static bool is_convertible(PyObject *ob, bool raise_exception) {
|
||||
return ((bool (*)(PyObject *,bool)) _imported_wrapped_convert_fnt_from_${m}[3*${n}+2])(ob,raise_exception);
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
%endfor
|
||||
%endfor
|
||||
|
||||
// We use the order, in the following order (which is necessary for compilation : we need the converters in the implementations)
|
||||
// - function/method declaration
|
||||
// - implement type, and all tables
|
||||
@ -1006,16 +980,10 @@ init${module.name}(void)
|
||||
%endfor
|
||||
|
||||
/* Create a Capsule containing the API pointer array's address */
|
||||
PyObject *c_api_object = PyCapsule_New((void *)_exported_wrapped_convert_fnt, "${module.name}._exported_wrapper_convert_fnt", NULL);
|
||||
PyObject *c_api_object = PyCapsule_New((void *)_exported_wrapped_convert_fnt, "${module.full_name}._exported_wrapper_convert_fnt", NULL);
|
||||
if (c_api_object != NULL) PyModule_AddObject(m, "_exported_wrapper_convert_fnt", c_api_object);
|
||||
%endif
|
||||
|
||||
// Now import wrappers from other modules, if any
|
||||
%for m in module.imported_wrapped_types :
|
||||
_imported_wrapped_convert_fnt_from_${m} = (void **)PyCapsule_Import("${m}._exported_wrapper_convert_fnt", 0);
|
||||
//if (_imported_wrapped_convert_fnt_from_${m} ==NULL) // Nothing, the interpreter has raised an error already.
|
||||
%endfor
|
||||
|
||||
%if len(module.python_functions) + len(module.hidden_python_functions) > 0 :
|
||||
|
||||
PyObject* main_module = PyImport_AddModule("__main__"); //borrowed
|
||||
|
@ -9,6 +9,7 @@ install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/wrap_test)
|
||||
|
||||
# Build C extension module
|
||||
triqs_python_extension(my_module wrap_test)
|
||||
triqs_python_extension(my_moduleB wrap_test)
|
||||
# ??triqs_set_rpath_for_target(my_module)
|
||||
|
||||
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )
|
||||
|
@ -126,28 +126,28 @@ struct A {
|
||||
};
|
||||
|
||||
/// some function using A
|
||||
void print_a(A const & a) {
|
||||
inline void print_a(A const & a) {
|
||||
std::cout << "my a is " << a.x << std::endl;
|
||||
}
|
||||
|
||||
/// function with an error
|
||||
void print_err(A const &a) {
|
||||
inline void print_err(A const &a) {
|
||||
TRIQS_RUNTIME_ERROR << "hum does not look good" << a;
|
||||
}
|
||||
|
||||
/// DOC make_vector...
|
||||
std::vector<int> make_vector(int size) {
|
||||
inline std::vector<int> make_vector(int size) {
|
||||
std::vector<int> r(size, 0);
|
||||
for (int i = 0; i < size; ++i)
|
||||
r[i] = i;
|
||||
return r;
|
||||
}
|
||||
|
||||
std::vector<std::vector<int> > make_vector2(int size) {
|
||||
inline std::vector<std::vector<int> > make_vector2(int size) {
|
||||
return { make_vector(size), make_vector(size + 1) };
|
||||
}
|
||||
|
||||
std::vector<int> vector_x2(std::vector<int> const &v) {
|
||||
inline std::vector<int> vector_x2(std::vector<int> const &v) {
|
||||
auto r = v;
|
||||
for (auto &x : r)
|
||||
x *= 2;
|
||||
@ -159,35 +159,35 @@ using triqs::arrays::array;
|
||||
using triqs::arrays::range;
|
||||
using namespace triqs::arrays;
|
||||
|
||||
void iter_on_range(range r){
|
||||
inline void iter_on_range(range r){
|
||||
foreach(r, [](int i) { std::cout << i << std::endl;});
|
||||
}
|
||||
|
||||
matrix<double> make_matrix(int size) { return make_unit_matrix<double>(size); }
|
||||
inline matrix<double> make_matrix(int size) { return make_unit_matrix<double>(size); }
|
||||
|
||||
void print_matrix(matrix<double> const &M) {
|
||||
inline void print_matrix(matrix<double> const &M) {
|
||||
// std::cout << M <<std::endl;
|
||||
}
|
||||
|
||||
|
||||
std::function<int(int,int)> make_fnt_ii() {
|
||||
inline std::function<int(int,int)> make_fnt_ii() {
|
||||
return [](int i, int j) { return i + 2*j;};
|
||||
}
|
||||
|
||||
std::function<int(int,int,double)> make_fnt_iid() {
|
||||
inline std::function<int(int,int,double)> make_fnt_iid() {
|
||||
return [](int i, int j, double a) { return a+ i + 2*j;};
|
||||
}
|
||||
|
||||
|
||||
void use_fnt_ii(std::function<int(int,int)> f) {
|
||||
inline void use_fnt_ii(std::function<int(int,int)> f) {
|
||||
std::cout << "use_fnt ii \n"<< f(1,2) << std::endl;
|
||||
}
|
||||
|
||||
void use_fnt_iid(std::function<int(int,int,double)> f) {
|
||||
inline void use_fnt_iid(std::function<int(int,int,double)> f) {
|
||||
std::cout << "use_fnt iid \n"<< f(1,2,4.5) << std::endl;
|
||||
}
|
||||
|
||||
|
||||
std::function<void(int,int)> make_fnt_void() {
|
||||
inline std::function<void(int,int)> make_fnt_void() {
|
||||
return [](int i, int j) { std::cout << " I am a C++ lambda : "<<i <<" "<< j << std::endl;};
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "./a.hpp"
|
||||
|
||||
/// some function using A
|
||||
void print_a2(A const & a) {
|
||||
inline void print_a2(A const & a) {
|
||||
std::cout << "module B : my a is " << a.x << std::endl;
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
from wrap_generator import *
|
||||
|
||||
# The module
|
||||
mod = module_(full_name = "pytriqs.wrap_test.my_moduleB", imported_modules = ["my_module"], doc = " Doc of my_module ")
|
||||
mod.add_include("../c++/b.hpp") # FIX PUT ASOLUTE NAME
|
||||
mod = module_(full_name = "pytriqs.wrap_test.my_moduleB", doc = " Doc of my_module ")
|
||||
mod.add_include("<triqs/../pytriqs/wrap_test/b.hpp>")
|
||||
|
||||
mod.add_function (name = "print_a2", signature = "void(A a)", doc = "DOC of print_a")
|
||||
|
||||
mod.generate_code(mako_template = sys.argv[1], wrap_file = sys.argv[2])
|
||||
mod.generate_py_converter_header(mako_template = sys.argv[3], wrap_file = sys.argv[4])
|
||||
|
||||
|
@ -2,7 +2,7 @@ from wrap_generator import *
|
||||
|
||||
# The module
|
||||
module = module_(full_name = "pytriqs.wrap_test.my_module", doc = " Doc of my_module ")
|
||||
module.add_include("./a.hpp")
|
||||
module.add_include("<triqs/../pytriqs/wrap_test/a.hpp>")
|
||||
module.add_include("<triqs/arrays.hpp>")
|
||||
|
||||
# one class
|
||||
@ -101,4 +101,5 @@ module.add_python_function(f1)
|
||||
|
||||
if __name__ == '__main__' :
|
||||
module.generate_code(mako_template = sys.argv[1], wrap_file = sys.argv[2])
|
||||
module.generate_py_converter_header(mako_template = sys.argv[3], wrap_file = sys.argv[4])
|
||||
|
||||
|
@ -2,51 +2,103 @@
|
||||
#include <iostream>
|
||||
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||
|
||||
using namespace triqs::utility;
|
||||
using namespace triqs::params;
|
||||
using namespace triqs::arrays;
|
||||
|
||||
int main() {
|
||||
try {
|
||||
|
||||
parameters P,P2;
|
||||
parameter_defaults pdef;
|
||||
|
||||
pdef.required ( "A", int(), "really ?") ;
|
||||
P.add_field("A", no_default<int>(), "really ?")
|
||||
.add_field("D", 2.0, " int ")
|
||||
.add_field("E", 3u, " unsigned int ")
|
||||
.add_field("F", long(4), " long ")
|
||||
.add_field("B", short(0), " short ")
|
||||
.add_field("C", 1u, " unsigned short ")
|
||||
.add_field("G", 5ll, " long ")
|
||||
.add_field("I", double(7.8), " doube ")
|
||||
.add_field("K", std::complex<double>(12), " double complex ")
|
||||
.add_field("L", std::string("13"), " string ")
|
||||
.add_field("M", std::vector<double>{1, 4}, " vector ")
|
||||
.add_field("Ml", std::vector<double>{1, 2, 3, 4, 5, 6, 7, 8, 9}, " a long vector ")
|
||||
.add_field("N", double(15), "")
|
||||
.add_field("s", no_default<std::string>(), "")
|
||||
.add_field("sc", no_default<std::string>(), "")
|
||||
.add_field("a1", no_default<array<double, 2>>(), " A nice array")
|
||||
.add_field("a2", no_default<array<long, 1>>(), "")
|
||||
.add_field("W", int(16), "");
|
||||
|
||||
pdef.optional( "B", short(0), " short ")
|
||||
.optional( "C", 1u, " unsigned short ")
|
||||
.optional( "D", int(2), " int ")
|
||||
.optional( "E", 3u, " unsigned int ")
|
||||
.optional( "F", long(4), " long ")
|
||||
.optional( "G", 5ll, " long ")
|
||||
.optional( "H", float(6), " float ")
|
||||
.optional( "I", double(7.8), " doube ")
|
||||
.optional( "K", std::complex<double>(12), " double complex ")
|
||||
.optional( "L", std::string("13"), " string ")
|
||||
.optional( "M", std::vector<double> { 1,4 }, " vector ")
|
||||
.optional( "N", double(15), "")
|
||||
.optional( "W", int(16), "")
|
||||
;
|
||||
std::cout << P << std::endl;
|
||||
P2 = P;
|
||||
P2.sort_by_key();
|
||||
std::cout << P2 << std::endl;
|
||||
|
||||
auto P_vide = P ;
|
||||
|
||||
P["a"] = long(1);
|
||||
P["d"] = 2.7;
|
||||
P["A"] = long(1);
|
||||
|
||||
std::cout << P["A"];
|
||||
|
||||
P["D"] = 2;
|
||||
P["D"] = 2.5;
|
||||
P["s"] = std::string("-14.3");
|
||||
P["sc"] = "-14.3";
|
||||
|
||||
triqs::arrays::array<double,2> A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2;
|
||||
triqs::arrays::array<long,1> B(3); B()=0;B(0) = 3; B(1) = -8;
|
||||
P["A"] = std::move(A);
|
||||
P["B"] = B;
|
||||
array<double,2> A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2;
|
||||
array<long,1> B(100); B()=8; B(0) = 3; B(1) = -8;
|
||||
P["a1"] = std::move(A);
|
||||
P["a2"] =B;
|
||||
|
||||
// errors
|
||||
//P["D"] = "eee";
|
||||
//int i = P["D"];
|
||||
std::cout << P << std::endl;
|
||||
|
||||
// P2.update(pdef);
|
||||
|
||||
// testing that copy is a copy
|
||||
P2["A"] = 12;
|
||||
|
||||
std::cout << P["A"] << std::endl;
|
||||
std::cout << P2["A"] << std::endl;
|
||||
|
||||
// put a subparameter ...
|
||||
P.add_group("Group1", " doc ");
|
||||
P["Group1"].add_field("a", 1, "sub a 1");
|
||||
P["Group1"]["a"] = 10;
|
||||
P["Group1"].add_group("subgroup1.2", " doc ");
|
||||
P["Group1"]["subgroup1.2"].add_field("d", 1.8, "d is a double");
|
||||
P["Group1"]["subgroup1.2"]["d"] = 10.2;
|
||||
|
||||
std::cout << P << std::endl;
|
||||
std::cout << pdef<< std::endl;
|
||||
//std::cout << P["Group1"] << std::endl;
|
||||
|
||||
// hdf5
|
||||
{
|
||||
H5::H5File file( "ess.h5", H5F_ACC_TRUNC );
|
||||
h5_write( file, "Parameters", P);
|
||||
}
|
||||
|
||||
{
|
||||
H5::H5File file( "ess.h5", H5F_ACC_RDONLY );
|
||||
h5_read( file.openGroup("/"), "Parameters", P_vide);
|
||||
}
|
||||
|
||||
std::cout << P_vide << std::endl;
|
||||
|
||||
{
|
||||
H5::H5File file( "ess.h5", H5F_ACC_RDONLY );
|
||||
h5_read( file.openGroup("/"), "Parameters", P);
|
||||
}
|
||||
|
||||
//std::cout << P << std::endl;
|
||||
|
||||
|
||||
try {
|
||||
P2 = P;
|
||||
P2.update(pdef);
|
||||
}
|
||||
catch (triqs::runtime_error const & e) {
|
||||
std::cout<< " Caught as expected : update_with_defaults error "<< e.what() << std::endl ;
|
||||
std::cout<< " Caught "<< e.what() << std::endl ;
|
||||
}
|
||||
std::cout << P2 << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
@ -10,24 +10,28 @@
|
||||
#include <boost/mpi/communicator.hpp>
|
||||
#include <boost/serialization/complex.hpp>
|
||||
|
||||
using namespace triqs::utility;
|
||||
using namespace triqs::params;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
boost::mpi::environment env(argc, argv);
|
||||
boost::mpi::communicator world;
|
||||
|
||||
parameters P;
|
||||
|
||||
P.add_field("a", 1, "?")
|
||||
.add_field("d", 2.0, "")
|
||||
.add_field("s", "", "");
|
||||
|
||||
if (world.rank() == 0) {
|
||||
P["a"] = long(1);
|
||||
P["d"] = 2.7;
|
||||
P["s"] = std::string("-14.3");
|
||||
}
|
||||
|
||||
/*
|
||||
* WITH SERIALIZATION
|
||||
std::cout << "Before bcast rank " << world.rank() << " : " << P << std::endl ;
|
||||
boost::mpi::broadcast(world,P,0);
|
||||
std::cout << "After bcast rank " << world.rank() << " : " << P << std::endl ;
|
||||
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,9 @@
|
||||
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||
|
||||
using namespace triqs;
|
||||
using namespace triqs::utility;
|
||||
using triqs::arrays::array;
|
||||
using namespace triqs::params;
|
||||
using namespace triqs::arrays;
|
||||
using triqs::arrays::array;
|
||||
|
||||
// what is the concept of things that can be put in the dict ?
|
||||
struct my_obj {
|
||||
@ -39,43 +40,37 @@ struct my_obj {
|
||||
void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::make_nvp("i",i); }
|
||||
};
|
||||
|
||||
// just to make the object printable
|
||||
namespace std {
|
||||
template<typename K, typename V>
|
||||
std::ostream & operator << (std::ostream & out, std::map<K,V> const &) { return out << "map";}
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<typename K, typename V>
|
||||
std::string get_triqs_hdf5_data_scheme (std::map<K,V> const &) {
|
||||
using triqs::get_triqs_hdf5_data_scheme;// for the basic types, not found by ADL
|
||||
std::stringstream fs;
|
||||
fs<<"map<"<<get_triqs_hdf5_data_scheme(K())<<","<<get_triqs_hdf5_data_scheme(V())<<">";
|
||||
return fs.str();
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
try {
|
||||
|
||||
parameters P;
|
||||
|
||||
P["myobject1"] = my_obj(18);
|
||||
P.add_field("a", 1, "?")
|
||||
.add_field("d", 2.0, "")
|
||||
.add_field("s", "", "")
|
||||
.add_field("sc", "", "")
|
||||
.add_field("U", no_default<array<double, 2>>(), "")
|
||||
.add_field("A", no_default<matrix<double>>(), "")
|
||||
.add_field("V", no_default<arrays::vector<double>>(), "")
|
||||
.add_field("B", no_default<array<long, 1>>(), "")
|
||||
//.add_field("myobject1", no_default<my_obj>(), "")
|
||||
;
|
||||
|
||||
//P["myobject1"] = my_obj(18);
|
||||
|
||||
P["a"] = long(1);
|
||||
P["d"] = 2.7;
|
||||
P["s"] = std::string("-14.3");
|
||||
P["sc"] = "-14.3";
|
||||
|
||||
std::map<std::string, int> mm;
|
||||
mm["qwe"] = 123;
|
||||
P["mm"] = mm;
|
||||
std::cout << " map = "<< P["mm"]<< std::endl ;
|
||||
std::cout << "123 = "<<utility::extract<std::map<std::string,int>>(P["mm"])["qwe"]<< std::endl ;
|
||||
|
||||
// raises an error as it should ...
|
||||
//std::cout << utility::extract<int>(P["d"]) << std::endl;
|
||||
try {
|
||||
std::cout << extract<int>(P["d"]) << std::endl;
|
||||
}
|
||||
catch(std::exception const & e) {
|
||||
std::cout << "caught error "<< e.what() <<std::endl;
|
||||
}
|
||||
|
||||
triqs::arrays::array<double,2> A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2;
|
||||
triqs::arrays::array<long,1> B(3); B()=0;B(0) = 3; B(1) = -8;
|
||||
@ -92,17 +87,26 @@ int main() {
|
||||
C = extract<decltype(C)>(P["B"]);
|
||||
std::cout << "C" << C << std::endl;
|
||||
|
||||
array<array<int,2>, 1> aa(2);
|
||||
// testing that I can extract a view and modify it.
|
||||
triqs::arrays::array_view<long, 1> VC = extract<triqs::arrays::array_view<long, 1>>(P["B"]);
|
||||
std::cout << "VC" << VC << std::endl;
|
||||
VC(0) *= 2;
|
||||
|
||||
C = extract<decltype(C)>(P["B"]);
|
||||
std::cout << "C" << C << std::endl;
|
||||
|
||||
/*array<array<int,2>, 1> aa(2);
|
||||
aa(0) = A; aa(1) = 2*A;
|
||||
P["aa"] = aa;
|
||||
|
||||
std::cout << "get_triqs_hdf5_data_scheme :"<< get_triqs_hdf5_data_scheme(aa)<< std::endl;
|
||||
*/
|
||||
|
||||
long j = P["a"];
|
||||
double x = P["d"];
|
||||
double y = P["a"];
|
||||
double z = P["s"];
|
||||
double zc = P["sc"];
|
||||
std::string rs = P["s"];
|
||||
|
||||
std::cout << j << std::endl ;
|
||||
std::cout << x << std::endl;
|
||||
@ -110,17 +114,8 @@ int main() {
|
||||
std::cout << z << std::endl ;
|
||||
std::cout << zc << std::endl ;
|
||||
std::cout << P["a"] << std::endl ;
|
||||
std::cout << P["aa"] << std::endl ;
|
||||
//std::cout << P["aa"] << std::endl ;
|
||||
std::cout << P["s"] << std::endl ;
|
||||
|
||||
std::string rs = P["s"];
|
||||
|
||||
// testing that copy is a copy
|
||||
parameters P2 = P;
|
||||
P2["a"] = 12.3;
|
||||
|
||||
// Put P2 in P ...
|
||||
P["P2"] = P2;
|
||||
|
||||
std::cout << P << std::endl;
|
||||
|
||||
@ -129,22 +124,7 @@ int main() {
|
||||
h5_write( file, "Parameters", P);
|
||||
}
|
||||
|
||||
{
|
||||
H5::H5File file( "ess2.h5", H5F_ACC_TRUNC );
|
||||
h5_write( file, "Parameters", P2);
|
||||
}
|
||||
|
||||
std::string s = triqs::serialize(P);
|
||||
parameters P3 = triqs::deserialize<parameters>(s);
|
||||
{
|
||||
H5::H5File file( "ess3.h5", H5F_ACC_TRUNC );
|
||||
h5_write( file, "Parameters", P3);
|
||||
}
|
||||
|
||||
parameters P4;
|
||||
parameters::register_type<triqs::arrays::array<double,1>>();
|
||||
//parameters::register_type<triqs::arrays::array<int,2>>();
|
||||
std::cout << "P4 before : "<< P4<< std::endl ;
|
||||
auto P4 = P;
|
||||
{
|
||||
H5::H5File file( "ess.h5", H5F_ACC_RDONLY );
|
||||
h5_read( file.openGroup("/"), "Parameters", P4);
|
||||
@ -153,11 +133,8 @@ int main() {
|
||||
H5::H5File file( "ess_relo.h5", H5F_ACC_TRUNC );
|
||||
h5_write( file.openGroup("/"), "Parameters", P4);
|
||||
}
|
||||
std::cout << "P4 after : "<< P4<< std::endl ;
|
||||
std::cout << "P4 after : \n"<< P4<< std::endl ;
|
||||
|
||||
std::cout << "map retrieval "<<utility::extract<std::map<std::string,int>>(P4["mm"])["qwe"]<< std::endl ;
|
||||
|
||||
//std::cout << triqs::deserialize<array<array<int,2>,1>>(utility::extract<std::string>(P4["aa"])) << std::endl ;
|
||||
}
|
||||
TRIQS_CATCH_AND_ABORT;
|
||||
}
|
||||
|
@ -1,46 +0,0 @@
|
||||
#include <triqs/parameters.hpp>
|
||||
#include <iostream>
|
||||
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||
|
||||
using namespace triqs;
|
||||
using namespace triqs::utility;
|
||||
|
||||
int main() {
|
||||
|
||||
parameters P;
|
||||
|
||||
P["a"] = long(1);
|
||||
P["d"] = 2.7;
|
||||
P["s"] = std::string("-14.3");
|
||||
P["sc"] = "-14.3";
|
||||
|
||||
triqs::arrays::array<double,2> A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2;
|
||||
triqs::arrays::array<long,1> B(3); B()=0;B(0) = 3; B(1) = -8;
|
||||
triqs::arrays::matrix<double> U(2,2);U()=1.;
|
||||
P["U"] = U;
|
||||
triqs::arrays::vector<double> V(3);V()=1.;
|
||||
P["V"] = V;
|
||||
P["A"] = std::move(A);
|
||||
P["B"] = B;
|
||||
std::cout << "A"<< P["A"] << std::endl;
|
||||
std::cout << "B"<< P["B"] << std::endl;
|
||||
|
||||
triqs::arrays::array<long,1> C;
|
||||
C = extract<decltype(C)>(P["B"]);
|
||||
std::cout << "C" << C << std::endl;
|
||||
|
||||
// testing that I can extract a view and modify it.
|
||||
triqs::arrays::array_view <long,1> VC = extract<triqs::arrays::array_view <long,1>>(P["B"]);
|
||||
std::cout << "VC" << VC << std::endl;
|
||||
VC(0) *=2;
|
||||
|
||||
C = extract<decltype(C)>(P["B"]);
|
||||
std::cout << "C" << C << std::endl;
|
||||
|
||||
{
|
||||
H5::H5File file( "ess.h5", H5F_ACC_TRUNC );
|
||||
h5_write( file, "Parameters", P);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
A
|
||||
[[1.3,0]
|
||||
[0,-8.2]]
|
||||
B[3,-8,0]
|
||||
C[3,-8,0]
|
||||
VC[3,-8,0]
|
||||
C[6,-8,0]
|
@ -2,13 +2,15 @@
|
||||
#include <iostream>
|
||||
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||
|
||||
using namespace triqs::utility;
|
||||
|
||||
using namespace triqs::params;
|
||||
|
||||
int main() {
|
||||
|
||||
parameters P;
|
||||
|
||||
P.add_field("a", 1, "?")
|
||||
.add_field("d", 2.0, "")
|
||||
.add_field("s", "", "");
|
||||
|
||||
P["a"] = long(1);
|
||||
P["d"] = 2.7;
|
||||
P["s"] = std::string("-14.3");
|
||||
|
@ -5,18 +5,36 @@ FOREACH(CPP ${ALLSOURCES})
|
||||
ENDFOREACH(CPP ${ALLSOURCES})
|
||||
get_property(ALLSOURCES GLOBAL PROPERTY TRIQS_LIB_CPP_SOURCES_LIST)
|
||||
|
||||
## The library also contains all the converters python <-> C++
|
||||
## automatically generated for all wrapped modules.
|
||||
## The lists are defined in subdirectory, in each module
|
||||
## NB : pytriqs subdir is and must be called BEFORE triqs, or these lists are empty
|
||||
get_property(all_py_converters_sources GLOBAL PROPERTY TRIQS_PY_CONVERTERS_CPP_LIST)
|
||||
get_property(all_py_converters_targets GLOBAL PROPERTY TRIQS_PY_CONVERTERS_TARGETS)
|
||||
|
||||
# All files are generated, cmake should not worry not to see them at configuration time
|
||||
foreach(CPP ${all_py_converters_sources})
|
||||
set_source_files_properties(${CPP} PROPERTIES GENERATED TRUE)
|
||||
endforeach()
|
||||
|
||||
# compile every subdirectory
|
||||
add_all_subdirectories_with_cmakelist()
|
||||
|
||||
# The lib will be build from the sources
|
||||
# The lib will be build from the sources and the converters generated sources
|
||||
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
SET( LINK_RT "")
|
||||
else()
|
||||
SET( LINK_RT "-lrt")
|
||||
endif()
|
||||
add_library(triqs ${ALLSOURCES})
|
||||
add_library(triqs ${ALLSOURCES} ${all_py_converters_sources})
|
||||
target_link_libraries (triqs ${LINK_RT} ${TRIQS_LINK_LIBS} )
|
||||
|
||||
# The TRIQS library depends on the generation of the .cpp wrapper and converters files
|
||||
# which must be produced first.
|
||||
foreach(T ${all_py_converters_targets})
|
||||
add_dependencies(triqs ${T})
|
||||
endforeach()
|
||||
|
||||
# Install library
|
||||
install(TARGETS triqs DESTINATION lib)
|
||||
|
||||
|
83
triqs/parameters/_field.cpp
Normal file
83
triqs/parameters/_field.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include "./_field.hpp"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace triqs {
|
||||
namespace params {
|
||||
|
||||
std::map<std::type_index, std::string> _field::type_names;
|
||||
|
||||
std::string _field::type_name(std::type_index i) {
|
||||
try {
|
||||
return type_names.at(i);
|
||||
}
|
||||
catch (...) {
|
||||
return i.name();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void h5_write(h5::group g, std::string const &name, _field const &obj) {
|
||||
obj.p->h5_write_(g, name);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void h5_read(h5::group g, std::string const &name, _field &obj) {
|
||||
obj.p->h5_read_(g, name);
|
||||
obj.modified = true;
|
||||
};
|
||||
|
||||
template <typename T> T lex_cast_from_string(_field const &obj) {
|
||||
std::string s = extract<std::string>(obj);
|
||||
try {
|
||||
return boost::lexical_cast<T>(s);
|
||||
}
|
||||
catch (boost::bad_lexical_cast &) {
|
||||
TRIQS_RUNTIME_ERROR << " extraction : can not read the string " << s << " into a " << typeid(T).name();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
template <> // specialize for double since we can make int -> double conversion
|
||||
double extract(_field const &obj) {
|
||||
if (obj.has_type<double>()) return *static_cast<const double *>(obj.get());
|
||||
if (obj.has_type<std::string>()) {
|
||||
return lex_cast_from_string<double>(obj);
|
||||
}
|
||||
#define TRANSFORM_TYPE(T) \
|
||||
if (obj.has_type<T>()) return extract<T>(obj)
|
||||
TRANSFORM_TYPE(int);
|
||||
// TRANSFORM_TYPE(unsigned int);
|
||||
TRANSFORM_TYPE(long);
|
||||
// TRANSFORM_TYPE(unsigned long);
|
||||
TRANSFORM_TYPE(short);
|
||||
// TRANSFORM_TYPE(unsigned short);
|
||||
TRANSFORM_TYPE(long long);
|
||||
// TRANSFORM_TYPE(unsigned long long);
|
||||
// TRANSFORM_TYPE(float);
|
||||
#undef TRANSFORM_TYPE
|
||||
TRIQS_RUNTIME_ERROR << "extraction of " << obj.name() << " impossible : type mismatch. Got " << obj.type_name()
|
||||
<< ", while I am supposed to extract a double";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
template <> // specialize for double since we can make int -> double conversion
|
||||
long extract(_field const &obj) {
|
||||
if (obj.has_type<long>()) return *static_cast<const long *>(obj.get());
|
||||
if (obj.has_type<std::string>()) {
|
||||
return lex_cast_from_string<long>(obj);
|
||||
}
|
||||
TRIQS_RUNTIME_ERROR << "extraction of " << obj.name() << " impossible : type mismatch. Got " << obj.type_name()
|
||||
<< ", while I am supposed to extract a double";
|
||||
}
|
||||
|
||||
// --------------- _field cast op implementation ---------------------------------------
|
||||
|
||||
#define CAST_OPERATOR(r, data, T) \
|
||||
_field::operator T() const { return extract<T>(*this); }
|
||||
BOOST_PP_SEQ_FOR_EACH(CAST_OPERATOR, nil, TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST);
|
||||
#undef CAST_OPERATOR
|
||||
}
|
||||
}
|
||||
|
232
triqs/parameters/_field.hpp
Normal file
232
triqs/parameters/_field.hpp
Normal file
@ -0,0 +1,232 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2014 by H. Hafermann, O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <triqs/utility/first_include.hpp>
|
||||
#include <string>
|
||||
#include <complex>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <typeindex>
|
||||
#include <boost/preprocessor/seq/for_each.hpp>
|
||||
|
||||
//#include <triqs/utility/serialization.hpp>
|
||||
|
||||
#include <triqs/arrays.hpp>
|
||||
#include <triqs/python_tools/wrapper_tools.hpp>
|
||||
|
||||
namespace triqs {
|
||||
namespace params {
|
||||
|
||||
using triqs::get_triqs_hdf5_data_scheme;
|
||||
|
||||
template <typename T> std::ostream &operator<<(std::ostream &out, std::vector<T> const &v) {
|
||||
out << "[";
|
||||
if (v.size() > 3)
|
||||
out << v[0] << ", ..., " << v[v.size()-1];
|
||||
else {
|
||||
int c = 0;
|
||||
for (auto const &x : v) out << (c++ ? ", " : "") << x;
|
||||
}
|
||||
return out << "]";
|
||||
}
|
||||
|
||||
// All the predefined cast of _field
|
||||
#define TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST \
|
||||
(int)(long)(long long)(unsigned int)(unsigned long)(unsigned long long)(double)(bool)(std::string)
|
||||
|
||||
// a trait to compute the type actually stored in the opaque object.
|
||||
// T except for integers, which are all stored as long
|
||||
template <typename T, typename Enable = void> struct storage_t_impl {
|
||||
using type = T;
|
||||
};
|
||||
template <typename T> using storage_t = typename storage_t_impl<std::c14::decay_t<T>>::type;
|
||||
|
||||
template <typename T> struct storage_t_impl<T, std::c14::enable_if_t<std::is_integral<T>::value>> {
|
||||
using type = long;
|
||||
};
|
||||
// differentiate value and view ?
|
||||
template <typename A> struct storage_t_impl<A, std::c14::enable_if_t<arrays::is_amv_value_or_view_class<A>::value>> {
|
||||
using type = arrays::array<typename A::value_type, A::rank>;
|
||||
};
|
||||
|
||||
template<> struct storage_t_impl<const char *> {using type = std::string;};
|
||||
template<> struct storage_t_impl<char *> {using type = std::string;};
|
||||
|
||||
// --------------- the field object ---------------------------------------
|
||||
|
||||
class _field {
|
||||
friend class parameters;
|
||||
|
||||
struct _data {
|
||||
virtual const void *get() const = 0;
|
||||
virtual _data *clone() const = 0;
|
||||
virtual void h5_write_(h5::group, std::string const &) const = 0;
|
||||
virtual void h5_read_(h5::group, std::string const &) = 0;
|
||||
|
||||
//virtual std::string serialize() const = 0;
|
||||
//virtual void deserialize(std::string const &) = 0;
|
||||
|
||||
virtual std::ostream &print(std::ostream &out) const = 0;
|
||||
virtual bool from_python_convertible(PyObject *) const = 0;
|
||||
virtual void set_from_python(PyObject *) = 0;
|
||||
virtual PyObject *to_python() const = 0;
|
||||
};
|
||||
|
||||
template <typename T> struct _data_impl : _data {
|
||||
T x;
|
||||
|
||||
_data_impl(T obj) : x(std::move(obj)) {}
|
||||
_data_impl(_data_impl &&c) = default;
|
||||
_data_impl(_data_impl const &) = default;
|
||||
|
||||
virtual const void *get() const override { return &x; }
|
||||
virtual _data *clone() const override { return new _data_impl(*this); }
|
||||
virtual void h5_write_(h5::group f, std::string const &name) const override { h5_write(f, name, x); }
|
||||
virtual void h5_read_(h5::group f, std::string const &name) override { h5_read(f, name, x); }
|
||||
|
||||
/*
|
||||
virtual std::string serialize() const override { return triqs::serialize(x); }
|
||||
virtual void deserialize(std::string const &s) override {
|
||||
x = triqs::deserialize<T>(s);
|
||||
};
|
||||
*/
|
||||
virtual std::ostream &print(std::ostream &out) const override { return out << x; }
|
||||
virtual bool from_python_convertible(PyObject *ob) const override {
|
||||
return py_tools::py_converter<T>::is_convertible(ob, true);
|
||||
}
|
||||
virtual void set_from_python(PyObject *ob) override { x = py_tools::py_converter<T>::py2c(ob); }
|
||||
virtual PyObject *to_python() const override { return py_tools::py_converter<T>::c2py(x); }
|
||||
};
|
||||
|
||||
std::type_index index;
|
||||
std::unique_ptr<_data> p; //invariant : is never null
|
||||
static std::map<std::type_index, std::string> type_names;
|
||||
std::string name_; // for_error_messages
|
||||
bool modified = false;
|
||||
|
||||
// only parameters will construct _field
|
||||
template <typename T>
|
||||
_field(T obj, std::string n, bool modification_required)
|
||||
: index(typeid(storage_t<T>)), p(new _data_impl<storage_t<T>>{std::move(obj)}), name_(n), modified(!modification_required) {
|
||||
type_names.insert({index, get_triqs_hdf5_data_scheme(storage_t<T>{})});
|
||||
}
|
||||
|
||||
public:
|
||||
//_field() : index(typeid(void)) {} // BREAKS invariant : only used for BOOST serialization...
|
||||
_field(_field &&c) = default;
|
||||
_field(_field const &x) : index(x.index), p(x.p ? x.p->clone() : nullptr), name_(x.name_), modified(x.modified) {} // regular type
|
||||
|
||||
_field &operator=(_field &&c) = default;
|
||||
_field &operator=(_field const &x) { return operator=(_field(x)); }
|
||||
|
||||
template <typename RHS> _field &operator=(RHS rhs) { // pass by value (sink)
|
||||
modified = true;
|
||||
using S_t = storage_t<RHS>;
|
||||
if (index != typeid(S_t)) {
|
||||
TRIQS_RUNTIME_ERROR << "Field "<< name_<<" is of type "<< type_name(index)<<". I can not put a " << type_name(typeid(S_t)) << " into it.";
|
||||
}
|
||||
p.reset(new _data_impl<S_t>{std::move(rhs)});
|
||||
return *this;
|
||||
}
|
||||
|
||||
// rewrite a few cases for convenience ...
|
||||
_field &operator=(int rhs) { // a special case where we can correct : int -> double
|
||||
if (index == typeid(double)) return operator=(double(rhs));
|
||||
return operator=(long(rhs));// beware infinite loop!
|
||||
}
|
||||
|
||||
// special treatment for const char *: fall back to string
|
||||
_field &operator=(const char *rhs) { return operator=(std::string(rhs)); }
|
||||
|
||||
// for subgroups only : implemented after parameters. Check type at runtime
|
||||
template <typename... T> _field &add_field(T &&... x);
|
||||
_field &operator[](const char * key);
|
||||
_field const &operator[](const char * key) const;
|
||||
friend bool is_parameter(_field const & f);
|
||||
_field& add_group(std::string const& key, std::string const& doc);
|
||||
|
||||
std::string type_name() const { return type_name(index); }
|
||||
|
||||
std::string const &name() const { return name_; }
|
||||
bool is_modified() const { return modified; }
|
||||
const void *get() const { return (p ? p->get() : nullptr); }
|
||||
template <typename T> bool has_type() const { return index == typeid(T); }
|
||||
static std::string type_name(std::type_index i);
|
||||
|
||||
bool from_python_convertible(PyObject *ob) const { return p->from_python_convertible(ob); }
|
||||
void set_from_python(PyObject *ob) { p->set_from_python(ob); }
|
||||
PyObject *to_python() const { return p->to_python(); }
|
||||
|
||||
// implemented later, since it needs the extract function ...
|
||||
#define CAST_OPERATOR(r, data, T) operator T() const;
|
||||
BOOST_PP_SEQ_FOR_EACH(CAST_OPERATOR, nil, TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST);
|
||||
#undef CAST_OPERATOR
|
||||
|
||||
// ----- Boost serialisation
|
||||
/*
|
||||
template<class Archive>
|
||||
void save(Archive & ar, const unsigned int version) const {
|
||||
std::string s = p->serialize();
|
||||
ar << TRIQS_MAKE_NVP("seria_str", s);
|
||||
}
|
||||
template<class Archive>
|
||||
void load(Archive & ar, const unsigned int version) {
|
||||
std::string s;
|
||||
ar >> TRIQS_MAKE_NVP("seria_str", s);
|
||||
p->deserialize(s);
|
||||
}
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER();
|
||||
*/
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &out, _field const &ob) { return ob.p->print(out); }
|
||||
|
||||
// --------------------- hdf5 ---------------------------------
|
||||
friend std::string get_triqs_hdf5_data_scheme(_field const &) { return ""; }
|
||||
friend void h5_write(h5::group F, std::string const &Name, _field const &);
|
||||
friend void h5_read(h5::group F, std::string const &Name, _field &);
|
||||
|
||||
}; // object class
|
||||
|
||||
// --------------------- arithmetic operations are deleted for _field ---------------------------------
|
||||
|
||||
#define DELETE_OP(op) \
|
||||
template <typename LHS, typename RHS> \
|
||||
std::c14::enable_if_t<std::is_same<LHS, _field>::value || std::is_same<RHS, _field>::value> operator op(LHS const &, \
|
||||
RHS const &) = delete;
|
||||
DELETE_OP(+);
|
||||
DELETE_OP(-);
|
||||
DELETE_OP(*);
|
||||
DELETE_OP(/ );
|
||||
#undef DELETE_OP
|
||||
|
||||
// --------------------- extraction with type checking for C++ ---------------------------------
|
||||
|
||||
template <typename T> T extract(_field const &ob) {
|
||||
if (!ob.has_type<storage_t<T>>())
|
||||
TRIQS_RUNTIME_ERROR << "extraction of " << ob.name() << " impossible : type mismatch. I have received a " << ob.type_name()
|
||||
<< ", while I am supposed to extract a " << _field::type_name(typeid(T));
|
||||
return *static_cast<const storage_t<T> *>(ob.get());
|
||||
}
|
||||
|
||||
template <> double extract(_field const &obj); // special treatment for basic types
|
||||
template <> long extract(_field const &obj);
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2013 by H. Hafermann, O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "./defaults.hpp"
|
||||
#include <triqs/utility/formatted_output.hpp>
|
||||
namespace triqs { namespace utility {
|
||||
|
||||
std::vector<std::vector<std::string>> parameter_defaults:: generate_help() const{
|
||||
std::vector<std::vector<std::string>> str;
|
||||
str.push_back({"parameter:", "status:", "type", "default value:", "description:"});
|
||||
for (auto const &s : object_map){
|
||||
std::string key=s.first; std::ostringstream val; val << s.second;
|
||||
if(is_required(key)) str.push_back({key, "required", s.second.type_name(), "-", doc(key)});
|
||||
else str.push_back({key, "optional", s.second.type_name(), val.str(), doc(key)});
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream & out, parameter_defaults const & p) {
|
||||
out<< print_formatted(p.generate_help());
|
||||
return out;
|
||||
}
|
||||
|
||||
}}
|
@ -1,106 +0,0 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2013 by H. Hafermann, O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_UTILITY_PARAMS_DEFAULT_H
|
||||
#define TRIQS_UTILITY_PARAMS_DEFAULT_H
|
||||
#include "./opaque_object_h5.hpp"
|
||||
namespace triqs { namespace utility {
|
||||
/**
|
||||
* Class to handle required and optional program parameters and default values for optional parameters.
|
||||
* Required parameters need to be provided by the user. Parameters that are optional need not be provided
|
||||
* by the user because sensible default values can be given. The former are inserted through the required
|
||||
* method, the latter by the optional method. An object of type parameters can be updated from an object
|
||||
* of type parameter_defaults (see parameters.hpp).
|
||||
*/
|
||||
class parameter_defaults {
|
||||
public :
|
||||
parameter_defaults() {};
|
||||
parameter_defaults (parameter_defaults const & other) = default;
|
||||
parameter_defaults (parameter_defaults && other) { swap(*this,other);}
|
||||
parameter_defaults & operator = (parameter_defaults const & other) = default;
|
||||
parameter_defaults & operator = (parameter_defaults && other) noexcept { swap(*this,other); return *this;}
|
||||
friend void swap(parameter_defaults & a, parameter_defaults &b)
|
||||
{ swap(a.object_map,b.object_map); swap(a.documentation, b.documentation);swap(a.is_optional, b.is_optional); }
|
||||
|
||||
private:
|
||||
typedef std::map<std::string, _object> map_t;
|
||||
map_t object_map;
|
||||
std::map<std::string, std::string> documentation;
|
||||
std::map<std::string, bool > is_optional;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int version) { ar & TRIQS_MAKE_NVP("object_map",object_map); }
|
||||
|
||||
template<typename T> parameter_defaults & insert(std::string const & key, T && def_val, std::string const & doc, bool opt) {
|
||||
object_map[key] = std::forward<T>(def_val);
|
||||
documentation[key] = doc;
|
||||
is_optional[key] = opt;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> const T getter(std::map<std::string,T> const & m, std::string const & key) const {
|
||||
auto it = m.find(key); assert(it !=m.end()); return it->second;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
typedef map_t::const_iterator const_iterator;
|
||||
typedef map_t::iterator iterator;
|
||||
const_iterator begin() const { return object_map.begin();}
|
||||
const_iterator end() const { return object_map.end();}
|
||||
iterator begin() { return object_map.begin();}
|
||||
iterator end() { return object_map.end();}
|
||||
|
||||
bool has_key(std::string const & key) const { return object_map.find(key) != object_map.end();}
|
||||
bool is_required(std::string const & key) const { return (has_key(key) && (! getter(this->is_optional,key)));}
|
||||
std::string doc(std::string const & key) const { return (has_key(key) ? getter(this->documentation,key) : "");}
|
||||
|
||||
/// inserter for optional parameters;
|
||||
/// calls can be chained for multiple parameters
|
||||
template <typename T> parameter_defaults &optional(std::string const &key, T &&def_val, std::string const &doc) {
|
||||
insert(key, std::forward<T>(def_val), doc, true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// inserter for required parameters;
|
||||
/// calls can be chained for multiple parameters
|
||||
template <typename T> parameter_defaults &required(std::string const &key, T &&def_val, std::string const &doc) {
|
||||
insert(key, std::forward<T>(def_val), doc, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///parameters class-like element access
|
||||
_object const & operator[](std::string const & key) const {
|
||||
auto it = object_map.find(key);
|
||||
if ( it== object_map.end()) TRIQS_RUNTIME_ERROR<<"Key : "<< key<< " not found";
|
||||
return it->second;
|
||||
}
|
||||
|
||||
///generate help in form of a table of strings containing a list of required and optional parameters
|
||||
std::vector<std::vector<std::string>> generate_help() const;
|
||||
|
||||
///print a formatted table of required and optional parameters
|
||||
friend std::ostream & operator << (std::ostream & out, parameter_defaults const & p);
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
#endif
|
@ -1,65 +0,0 @@
|
||||
#include "./opaque_object_h5.hpp"
|
||||
|
||||
namespace triqs { namespace utility {
|
||||
|
||||
std::map<size_t, std::function<_object(std::string const &)>> _object::code_to_deserialization_fnts;
|
||||
std::map<size_t, std::function<_object(h5::group const &, std::string const &)>> _object::code_to_h5_read_fnts;
|
||||
std::map<hid_t, size_t > _object::h5_type_to_c_equivalence;
|
||||
std::map<std::pair<size_t,int>, size_t > _object::code_element_rank_to_code_array;
|
||||
std::map<std::string, size_t > _object::h5_scheme_to_code;
|
||||
std::map<size_t, std::string > _object::type_code_to_type_name;
|
||||
std::map<std::string, size_t > _object::type_name_to_type_code;
|
||||
bool _object::initialized = false;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void _object::_init() {
|
||||
if (initialized) return;
|
||||
#define REGISTER_UNSERIALIZE_FUN(r, data, T) _object::register_native_type<T>();
|
||||
BOOST_PP_SEQ_FOR_EACH(REGISTER_UNSERIALIZE_FUN, nil , TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST);
|
||||
#undef REGISTER_UNSERIALIZE_FUN
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void h5_read ( h5::group g, std::string const & name, _object & obj){
|
||||
//std::cerr << " read object "<< name << std::endl ;
|
||||
using namespace H5;
|
||||
if (!g.has_key(name)) TRIQS_RUNTIME_ERROR << "no such "<<name <<" in file ";
|
||||
size_t type_hash;
|
||||
// First if it is not a subgroup, it is a scalar or a an array
|
||||
// TO BE CHECKED
|
||||
try {
|
||||
H5::DataSet ds = g.open_dataset( name.c_str() );
|
||||
hid_t dtype = H5Dget_type(ds.getId());
|
||||
hid_t native_type=H5Tget_native_type(dtype, H5T_DIR_DEFAULT);
|
||||
if (H5Tget_class(dtype) == H5T_STRING ) { // it is a string
|
||||
auto triqs_data_scheme = h5::read_string_attribute(&ds,"TRIQS_HDF5_data_scheme");
|
||||
type_hash = (triqs_data_scheme == "") ? _object::type_code<std::string>() : _object::h5_scheme_to_code[triqs_data_scheme];
|
||||
}
|
||||
else if ((H5Tget_class(dtype) == H5T_INTEGER ) || ((H5Tget_class(dtype) == H5T_FLOAT ) )) {
|
||||
int rank = ds.getSpace().getSimpleExtentNdims();
|
||||
auto it = _object::h5_type_to_c_equivalence.begin();
|
||||
for (;it != _object::h5_type_to_c_equivalence.end();++it) { if (H5Tequal(native_type, it->first)) break;}
|
||||
if (it == _object::h5_type_to_c_equivalence.end()) TRIQS_RUNTIME_ERROR << " h5_type_to_c_equivalence : type not found";
|
||||
type_hash = it->second;
|
||||
if (rank>0) {
|
||||
size_t type_hash_element = type_hash;
|
||||
auto it2= _object::code_element_rank_to_code_array.find(std::make_pair(type_hash_element,rank));
|
||||
if (it2 == _object::code_element_rank_to_code_array.end())
|
||||
TRIQS_RUNTIME_ERROR << " code_element_rank_to_code_array : type not found : " << name << " " << type_hash_element << " "
|
||||
<< rank;
|
||||
type_hash = it2->second;
|
||||
}
|
||||
}
|
||||
//else if (H5Tget_class(dtype)==H5T_ARRAY)
|
||||
herr_t status = H5Tclose (native_type);
|
||||
status = H5Tclose (dtype);
|
||||
}
|
||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||
|
||||
obj = _object::code_to_h5_read_fnts[type_hash](g,name);
|
||||
}
|
||||
}}
|
||||
|
@ -1,332 +0,0 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2013 by H. Hafermann, O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_UTILITY_OPAQUE_OBJECT_H5_H
|
||||
#define TRIQS_UTILITY_OPAQUE_OBJECT_H5_H
|
||||
#include <triqs/utility/first_include.hpp>
|
||||
#include <string>
|
||||
#include <complex>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/preprocessor/seq/for_each.hpp>
|
||||
#include <boost/serialization/map.hpp>
|
||||
#include <triqs/utility/exceptions.hpp>
|
||||
#include <triqs/utility/serialization.hpp>
|
||||
#include <triqs/arrays.hpp>
|
||||
#include <triqs/python_tools/array_interface.hpp>
|
||||
#include <triqs/h5/make_h5_read_write.hpp>
|
||||
|
||||
namespace triqs { namespace utility {
|
||||
|
||||
template<typename T>
|
||||
std::ostream & operator<<(std::ostream & out, std::vector<T> const & v) {
|
||||
out << "["; int c = 0; for (auto const & x : v) out << ( c++==0 ? ", " :" ") << x;
|
||||
return out << "]";
|
||||
}
|
||||
|
||||
// All the predefined cast of _object
|
||||
#define TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST (int)(long)(long long)(unsigned int)(unsigned long)(unsigned long long)(double)(bool)(std::string)
|
||||
|
||||
// a trait to compute the type actually stored in the opaque object.
|
||||
// T except for integers, which are all stored as long
|
||||
template<typename T> struct _object_collapse_type_impl : std::conditional<std::is_integral<T>::value, long, T > {};
|
||||
|
||||
// We store the array/matrix/vector as array_c (a view repackaged as a value) since :
|
||||
// in python : it allows to extract a view
|
||||
// in C++ : it allows to extract a value (array) with a copy, or a view (array_view) without a copy
|
||||
template<class T, int R, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::array<T,R,Opt,To>> { typedef arrays::array_c<T,R,Opt,To> type;};
|
||||
template<class T, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::matrix<T,Opt,To>> { typedef arrays::array_c<T,2,Opt,To> type;};
|
||||
template<class T, ull_t Opt> struct _object_collapse_type_impl< arrays::vector<T,Opt>> { typedef arrays::array_c<T,1,Opt> type;};
|
||||
|
||||
//same thing for the view
|
||||
template<class T, int R, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::array_view<T,R,Opt,To>> { typedef arrays::array_c<T,R,Opt,To> type;};
|
||||
template<class T, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::matrix_view<T,Opt,To>> { typedef arrays::array_c<T,2,Opt,To> type;};
|
||||
template<class T, ull_t Opt> struct _object_collapse_type_impl< arrays::vector_view<T,Opt>> { typedef arrays::array_c<T,1,Opt> type;};
|
||||
|
||||
// uncomment after merge qview branch
|
||||
//template<class T, int R, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::array_qview<T,R,Opt,To>> { typedef arrays::array_c<T,R,Opt,To> type;};
|
||||
//template<class T, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::matrix_qview<T,Opt,To>> { typedef arrays::array_c<T,2,Opt,To> type;};
|
||||
//template<class T, ull_t Opt> struct _object_collapse_type_impl< arrays::vector_qview<T,Opt>> { typedef arrays::array_c<T,1,Opt> type;};
|
||||
|
||||
template<typename T> struct _object_collapse_type: _object_collapse_type_impl <typename std::decay<T>::type> {};
|
||||
|
||||
// Since I used array_c to store in the dict, I need to make it h5 read/writable.
|
||||
// write is ok, because it is a view. Read : we can not use the view (no resize)
|
||||
// so I first build the value (an array) and rebind the array_c to it.
|
||||
template<class T, int R, ull_t Opt, ull_t To>
|
||||
void h5_read(h5::group const &gr, std::string const &Name, arrays::array_c<T,R,Opt,To> & a) {
|
||||
arrays::array<T,R,Opt,To> v; h5_read(gr,Name,v); a=v();// rebinds !
|
||||
}
|
||||
|
||||
// --------------- the opaque object ---------------------------------------
|
||||
// _object is a value : it makes deep copies in particular ...
|
||||
class _object {
|
||||
|
||||
std::shared_ptr<void> p; // the object handled by the class
|
||||
size_t type_code_; // id of the type, implementation dependent...
|
||||
std::function<_object()> clone_; // clones the object : will be used to make copy of parameters
|
||||
std::function<void(h5::group const &, std::string const &)> h5_w; // the function to write in h5
|
||||
std::function<std::string()> serialize_; // for boost serialization ...
|
||||
std::function<void(std::ostream&)> print_;
|
||||
std::string name_;
|
||||
|
||||
public :
|
||||
|
||||
template<typename T> static constexpr size_t type_code () { return typeid(T).hash_code();}
|
||||
template<typename T> static std::string make_type_name () { return get_triqs_hdf5_data_scheme(typename _object_collapse_type<T>::type());}
|
||||
//template<typename T> static std::string make_type_name () { return demangle(typeid(T).name());}
|
||||
|
||||
_object() {_init(); };
|
||||
|
||||
// pass a const & or a && (in which case a move will be used, provided that T has a move constructor)
|
||||
template<typename T>
|
||||
_object ( T && obj, std::string const & name){ delegate_constructor( new typename std::remove_cv<typename std::remove_reference<T>::type>::type(std::forward<T>(obj)), name); }
|
||||
|
||||
private:
|
||||
template<typename T> void delegate_constructor( T * obj, std::string const & name) {
|
||||
p = std::shared_ptr<T> (obj);
|
||||
type_code_ = type_code<T>();
|
||||
name_ = name;
|
||||
clone_ = [obj,name]() { return _object( *obj, name);} ;
|
||||
//clone_ = [this,obj]() { return _object::factory( *obj);} ; //clone_ = [obj]() { return _object( *obj, "");} ;
|
||||
//h5_w = [obj](h5::group const &F, std::string const &Name)->void { h5_write(F,Name, *obj);};
|
||||
h5_w = h5::make_h5_write(obj);// either call h5_write or synthetize one into a string using boost serialization
|
||||
//static_assert(h5::has_h5_write<T>::value, "oops");
|
||||
serialize_ = [obj](){ return triqs::serialize(*obj);};
|
||||
print_ = [obj](std::ostream & out ){out << *obj;};
|
||||
// CHECK if std::bind would lead to less code bloat ??
|
||||
_init();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
_object(_object const & x ) { *this = x; _init(); }
|
||||
_object(_object && c) { *this= std::move(c); _init();}
|
||||
|
||||
friend void swap (_object & a, _object & b) {
|
||||
#define SWAP(A) swap(a.A,b.A)
|
||||
SWAP(p); std::SWAP(type_code_); SWAP(clone_); SWAP(h5_w); SWAP(serialize_); SWAP(print_); SWAP(name_);
|
||||
#undef SWAP
|
||||
}
|
||||
|
||||
_object & operator = (_object && c) { swap(*this, c); return *this; }
|
||||
_object & operator = (_object const & x ) { if (x.p) *this = x.clone_(); else *this = _object(); return *this; }
|
||||
_object & operator = (_object & x ) { if (x.p) *this = x.clone_(); else *this = _object(); return *this; }
|
||||
// the last one is needed since otherwise the template for _object & is taken !
|
||||
// alternatively disable the template for object ...
|
||||
|
||||
template <typename RHS> _object & operator=(RHS && rhs) {
|
||||
typedef typename _object_collapse_type<RHS>::type storage_t;
|
||||
*this = _object (storage_t(std::forward<RHS>(rhs)),this->name());
|
||||
register_type<storage_t>::invoke();
|
||||
//register_type<typename std::remove_reference<RHS>::type>::invoke();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// special treatment for const char *: fall back to string
|
||||
_object & operator=(const char * rhs) { *this = std::string(rhs); return *this;}
|
||||
|
||||
bool is_empty() const { return bool(p);}
|
||||
|
||||
std::string const & name() const { return name_;}
|
||||
void set_name(std::string const & n) { name_ = n;}
|
||||
|
||||
friend bool have_same_type( _object const & a, _object const & b) { return a.type_code_ == b.type_code_;}
|
||||
|
||||
template<typename T> bool has_type() const { return type_code_ == type_code<T>();}
|
||||
|
||||
const void * get_void_ptr() const { return p.get();}
|
||||
void * get_void_ptr() { return p.get();}
|
||||
|
||||
// implemented later, since it needs the extract function ...
|
||||
#define CAST_OPERATOR(r, data, T) operator T () const;
|
||||
BOOST_PP_SEQ_FOR_EACH(CAST_OPERATOR, nil , TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST);
|
||||
#undef CAST_OPERATOR
|
||||
|
||||
friend std::ostream & operator << (std::ostream & out, _object const & p) { if (p.is_empty()) p.print_(out); else out<< "empty"; return out;}
|
||||
friend void h5_write ( h5::group F, std::string const & Name, _object const & obj){ obj.h5_w(F,Name); };
|
||||
friend void h5_read ( h5::group F, std::string const & Name, _object & obj);
|
||||
friend std::string get_triqs_hdf5_data_scheme(_object const&) { return "";}
|
||||
|
||||
std::string type_name() const { return type_code_to_type_name[type_code_];}
|
||||
|
||||
// ----- Boost serialisation
|
||||
template<class Archive>
|
||||
void save(Archive & ar, const unsigned int version) const {
|
||||
std::string s = serialize_();
|
||||
ar << TRIQS_MAKE_NVP("type_name", type_code_to_type_name[type_code_]);
|
||||
ar << TRIQS_MAKE_NVP("seria_str", s);
|
||||
}
|
||||
template<class Archive>
|
||||
void load(Archive & ar, const unsigned int version) {
|
||||
std::string s, tnn;
|
||||
ar >> TRIQS_MAKE_NVP("type_name", tnn);
|
||||
ar >> TRIQS_MAKE_NVP("seria_str", s);
|
||||
auto it = type_name_to_type_code.find(tnn);
|
||||
if (it== type_name_to_type_code.end())
|
||||
TRIQS_RUNTIME_ERROR << " Can not deserialize the type "<< tnn<< "\n Did you forget to register it ?";
|
||||
*this = code_to_deserialization_fnts[it->second](s);
|
||||
}
|
||||
BOOST_SERIALIZATION_SPLIT_MEMBER();
|
||||
|
||||
// ----- Deserialization (boost, h5) table : type_code -> deserialization function
|
||||
// init will register the most common types.
|
||||
static std::map<size_t, std::function<_object(std::string const &)>> code_to_deserialization_fnts;
|
||||
static std::map<size_t, std::function<_object(h5::group const &, std::string const &)>> code_to_h5_read_fnts;
|
||||
static std::map<hid_t, size_t > h5_type_to_c_equivalence;
|
||||
static std::map<std::pair<size_t,int>, size_t > code_element_rank_to_code_array;
|
||||
static std::map<std::string, size_t > h5_scheme_to_code;
|
||||
static std::map<size_t, std::string > type_code_to_type_name;
|
||||
static std::map<std::string, size_t > type_name_to_type_code;
|
||||
|
||||
static bool initialized;
|
||||
static void _init();
|
||||
static bool is_initialised(size_t code) { return type_code_to_type_name.find(code) != type_code_to_type_name.end();}
|
||||
|
||||
template <typename T> struct register_type;
|
||||
|
||||
private: // native type
|
||||
template <typename T>
|
||||
static void register_native_type() {
|
||||
if (register_type<T>::invoke()) return;
|
||||
h5_type_to_c_equivalence[h5::h5_type_from_C(T()).getId()] = type_code<T>();
|
||||
}
|
||||
|
||||
};// object class
|
||||
|
||||
// --------------------- type registering ---------------------------------
|
||||
|
||||
template <typename T> struct _object::register_type<const T> : _object::register_type<T>{};
|
||||
|
||||
template <typename T> struct _object::register_type {
|
||||
static bool invoke() { // returns true if already registered
|
||||
size_t code = type_code<T>();
|
||||
if (is_initialised(code)) return true;
|
||||
type_code_to_type_name[code] = make_type_name<T>();
|
||||
type_name_to_type_code[make_type_name<T>()]= code;
|
||||
code_to_deserialization_fnts[code] = [](std::string const &s) { return _object( triqs::deserialize<T>(s),"");};
|
||||
code_to_h5_read_fnts[code] = [](h5::group const &f,std::string const &s) ->_object { T n; h5::make_h5_read(&n)(f,s); return _object(std::move(n),"");};
|
||||
//code_to_h5_read_fnts[code] = [](h5::group const &f,std::string const &s) ->_object { T n; h5_read(f,s,n); return _object(std::move(n),true);};
|
||||
auto h5_scheme = get_triqs_hdf5_data_scheme(T());
|
||||
if (h5_scheme != "") h5_scheme_to_code[h5_scheme] = code;
|
||||
//std::cerr << " registering " << type_code_to_type_name[code] << "h5 scheme "<< h5_scheme<< std::endl ;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// special case for array, we need to fill one more table
|
||||
template<typename T, int R> struct _object::register_type<arrays::array_c<T,R>>{
|
||||
static bool invoke() {
|
||||
typedef arrays::array_c<T,R> A;
|
||||
typedef arrays::array<T,R> Aa;
|
||||
if (is_initialised(type_code<A>())) return true;
|
||||
type_code_to_type_name[type_code<A>()] = make_type_name<A>();
|
||||
type_name_to_type_code[make_type_name<A>()]= type_code<A>();
|
||||
code_to_deserialization_fnts[type_code<A>()] = [](std::string const &s) { return _object( triqs::deserialize<A>(s),"");};
|
||||
//code_to_h5_read_fnts[type_code<A>()] = [](h5::group const &f,std::string const &s) ->_object { A n; h5_read(f,s,n); return _object(std::move(n),true);};
|
||||
code_to_h5_read_fnts[type_code<A>()] = [](h5::group const &f,std::string const &s) ->_object { Aa a; h5::make_h5_read(&a)(f,s); return _object(A(a),"");};
|
||||
code_element_rank_to_code_array[std::make_pair(type_code<T>(), R)] = type_code<A>();
|
||||
auto h5_scheme = get_triqs_hdf5_data_scheme(Aa());
|
||||
if (h5_scheme != "") h5_scheme_to_code[h5_scheme] = type_code<A>();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------- arithmetic operations are deleted for _object ---------------------------------
|
||||
|
||||
#define DELETE_OP(op)\
|
||||
template <typename LHS, typename RHS> \
|
||||
typename std::enable_if< std::is_same<LHS,_object>::value || std::is_same<RHS,_object>::value>::type\
|
||||
operator op( LHS const &, RHS const &) = delete;
|
||||
DELETE_OP(+); DELETE_OP(-); DELETE_OP(*); DELETE_OP(/);
|
||||
#undef DELETE_OP
|
||||
|
||||
// --------------------- extraction with strict type checking for python ---------------------------------
|
||||
|
||||
template<typename T> struct extract_strict {
|
||||
typedef typename _object_collapse_type<T>::type T_stored;
|
||||
static bool is_possible (_object const &obj) { return obj.has_type<T_stored>(); }
|
||||
static T invoke(_object const &obj) {
|
||||
if (! is_possible(obj))
|
||||
TRIQS_RUNTIME_ERROR<<"extraction of "<< obj.name() << "impossible : type mismatch. Got a "<<obj.type_name()<< " while I am supposed to extract a "<<_object::make_type_name<T>();
|
||||
return T(* static_cast<const T_stored*>(obj.get_void_ptr()));
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------- extraction with more relaxed type checking for C++ ---------------------------------
|
||||
|
||||
template<typename T> T extract(_object const &obj);
|
||||
|
||||
template<typename T> T lex_cast_from_string(_object const &obj) {
|
||||
std::string s = extract<std::string>(obj);
|
||||
try { return boost::lexical_cast<T>(s); }
|
||||
catch(boost::bad_lexical_cast &) { TRIQS_RUNTIME_ERROR << " extraction : can not read the string "<<s <<" into a "<< _object::make_type_name<T>(); }
|
||||
}
|
||||
|
||||
template<typename T> struct lexical_cast_make_sense : std::is_arithmetic<T>{};
|
||||
//template<typename T> constexpr bool lexical_cast_make_sense() { return std::is_arithmetic<T>::value; }
|
||||
|
||||
template<typename T> T extract1(_object const &obj, std::false_type) {
|
||||
typedef typename _object_collapse_type<T>::type coll_t;
|
||||
if (! obj.has_type<coll_t>())
|
||||
TRIQS_RUNTIME_ERROR<<"extraction of "<< obj.name() << " impossible : type mismatch. Got "<<obj.type_name()<< ", while I am supposed to extract a "<<_object::make_type_name<T>();
|
||||
return * static_cast<const coll_t*>(obj.get_void_ptr());
|
||||
}
|
||||
|
||||
template<typename T> T extract1(_object const &obj, std::true_type) {
|
||||
// if T is not a string, and object contains a string, attempt lexical_cast
|
||||
if ((!std::is_same<T,std::string>::value) && (obj.has_type<std::string>())) { return lex_cast_from_string<T>(obj); }
|
||||
return extract1<T>(obj, std::false_type());
|
||||
}
|
||||
|
||||
template<typename T> T extract(_object const &obj) {
|
||||
return extract1<T>(obj, std::integral_constant<bool,lexical_cast_make_sense<T>::value>());
|
||||
}
|
||||
|
||||
template<> // specialize for double since we can make int -> double conversion
|
||||
inline double extract(_object const & obj) {
|
||||
if (obj.has_type<double>()) return * static_cast<const double*>(obj.get_void_ptr());
|
||||
if (obj.has_type<std::string>()) {return lex_cast_from_string<double>(obj); }
|
||||
#define TRANSFORM_TYPE(T) if (obj.has_type<T>()) return extract<T>(obj)
|
||||
TRANSFORM_TYPE(int);
|
||||
//TRANSFORM_TYPE(unsigned int);
|
||||
TRANSFORM_TYPE(long);
|
||||
//TRANSFORM_TYPE(unsigned long);
|
||||
TRANSFORM_TYPE(short);
|
||||
//TRANSFORM_TYPE(unsigned short);
|
||||
TRANSFORM_TYPE(long long);
|
||||
//TRANSFORM_TYPE(unsigned long long);
|
||||
//TRANSFORM_TYPE(float);
|
||||
#undef TRANSFORM_TYPE
|
||||
TRIQS_RUNTIME_ERROR<<"extraction of "<< obj.name() << " impossible : type mismatch. Got "<<obj.type_name()<< ", while I am supposed to extract a double";
|
||||
}
|
||||
|
||||
// template<> // special case to size_t
|
||||
// inline size_t extract(_object const & obj) { return extract<long>(obj);}
|
||||
|
||||
// --------------- _object cast op implementation ---------------------------------------
|
||||
|
||||
#define CAST_OPERATOR(r, data, T) inline _object::operator T () const{ return extract<T>(*this);}
|
||||
BOOST_PP_SEQ_FOR_EACH(CAST_OPERATOR, nil , TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST);
|
||||
#undef CAST_OPERATOR
|
||||
|
||||
}}
|
||||
#endif
|
@ -1,87 +1,154 @@
|
||||
#include "./parameters.hpp"
|
||||
#include <triqs/utility/first_include.hpp>
|
||||
#include <triqs/utility/formatted_output.hpp>
|
||||
#include <boost/serialization/string.hpp>
|
||||
#include "./parameters.hpp"
|
||||
#include <triqs/utility/serialization.hpp>
|
||||
#include <algorithm>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
namespace triqs { namespace utility {
|
||||
namespace triqs {
|
||||
namespace params {
|
||||
|
||||
void h5_read ( h5::group F, std::string const & subgroup_name, parameters & p){
|
||||
parameters::parameters() {
|
||||
using triqs::arrays::array;
|
||||
using dcomplex = std::complex<double>;
|
||||
if (_field::type_names.size() == 0) {
|
||||
#define R(...) _field::type_names.insert({typeid(__VA_ARGS__), get_triqs_hdf5_data_scheme(storage_t<__VA_ARGS__>{})});
|
||||
#define A(N) \
|
||||
R(array<int, N>); \
|
||||
R(array<long, N>); \
|
||||
R(array<double, N>); \
|
||||
R(array<dcomplex, N>);
|
||||
R(long);
|
||||
R(double);
|
||||
R(int);
|
||||
R(dcomplex);
|
||||
A(1);
|
||||
A(2);
|
||||
A(3);
|
||||
A(4);
|
||||
}
|
||||
}
|
||||
|
||||
parameters::_data_t::iterator parameters::find(std::string const& key) {
|
||||
return std::find_if(_data.begin(), _data.end(), [&key](_data_elem const& x) { return x.key == key; });
|
||||
}
|
||||
|
||||
parameters::_data_t::const_iterator parameters::find(std::string const& key) const {
|
||||
return std::find_if(_data.begin(), _data.end(), [&key](_data_elem const& x) { return x.key == key; });
|
||||
}
|
||||
|
||||
bool parameters::has_key(std::string const& k) const { return find(k) != _data.end();}
|
||||
|
||||
void parameters::sort_by_key() {
|
||||
std::sort(_data.begin(), _data.end(), [](_data_elem const& x, _data_elem const& y) { return x.key < y.key; });
|
||||
}
|
||||
|
||||
void parameters::insert(std::string const& key, _field&& f, std::string const& doc) {
|
||||
if (has_key(key)) TRIQS_RUNTIME_ERROR << "Field " << key << " already defined";
|
||||
_data.push_back({key, std::move(f),doc});
|
||||
}
|
||||
|
||||
_field& parameters::operator[](const char * key) {
|
||||
auto it = find(key);
|
||||
if (it == _data.end()) TRIQS_RUNTIME_ERROR << "Parameters : the key : " << key << " does not exists";
|
||||
return it->f;
|
||||
}
|
||||
|
||||
_field const& parameters::operator[](const char * key) const {
|
||||
auto it = find(key);
|
||||
if (it == _data.end()) TRIQS_RUNTIME_ERROR << "Parameters : the key : " << key << " does not exists";
|
||||
return it->f;
|
||||
}
|
||||
|
||||
void h5_write(h5::group F, std::string const& subgroup_name, parameters const& p) {
|
||||
auto gr = F.create_group(subgroup_name);
|
||||
for (auto& pvp : p._data) h5_write(gr, pvp.key, pvp.f);
|
||||
}
|
||||
|
||||
void h5_read(h5::group F, std::string const& subgroup_name, parameters& p) {
|
||||
auto gr = F.open_group(subgroup_name);
|
||||
std::vector<std::string> ds_name = F.get_all_dataset_names(subgroup_name), grp_name = F.get_all_subgroup_names(subgroup_name);
|
||||
for (auto & x : grp_name) {
|
||||
//std::cerr << " loading group : "<< x <<std::endl;
|
||||
auto x_grp = gr.open_group(x);
|
||||
auto triqs_data_scheme = x_grp.read_triqs_hdf5_data_scheme();
|
||||
if (triqs_data_scheme != "") {
|
||||
auto type_hash = _object::h5_scheme_to_code[triqs_data_scheme];
|
||||
auto it = _object::code_to_h5_read_fnts.find(type_hash);
|
||||
if (it == _object::code_to_h5_read_fnts.end()) TRIQS_RUNTIME_ERROR << "TRIQS_HDF5_data_scheme : ["<< triqs_data_scheme << "] is unknown. Did you register your object ?";
|
||||
p[x] = it->second(gr,x);
|
||||
}
|
||||
else {
|
||||
parameters p2;
|
||||
h5_read (gr,x,p2);
|
||||
p[x] = p2;
|
||||
}
|
||||
}
|
||||
for (auto & x : ds_name) {
|
||||
//std::cerr << " loading : "<< x <<std::endl;
|
||||
try {
|
||||
_object obj;
|
||||
h5_read(gr,x,obj);
|
||||
p[x] = obj;
|
||||
}
|
||||
catch(H5::Exception const & e) { TRIQS_RUNTIME_ERROR<< "Cannot load "<< x<<"\n H5 error is : \n "<< e.getCDetailMsg();}
|
||||
}
|
||||
for (auto& pvp : p._data) h5_read(gr, pvp.key, pvp.f);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
void parameters::update (parameters const & pdef){ for (auto const & pvp : pdef) (*this)[pvp.first] = pvp.second; }
|
||||
|
||||
void parameters::update (parameter_defaults const & pdef, ull_t flag ){
|
||||
|
||||
std::vector<std::vector<std::string>> missing;
|
||||
std::vector<std::vector<std::string>> wrong_t;
|
||||
std::vector<std::vector<std::string>> no_deft;
|
||||
|
||||
std::vector<std::string> desc{"key:", "description:"};
|
||||
std::vector<std::string> tdesc{"key:", "expected type:", "actual type:"};
|
||||
|
||||
if ( (flag & reject_key_without_default) ) { // check that no extra parameters are present
|
||||
for (auto const & pvp : *this) {
|
||||
auto key = pvp.first;
|
||||
if (!pdef.has_key(key)){
|
||||
no_deft.push_back({key});
|
||||
}
|
||||
}
|
||||
void parameters::update(parameters const& other) {
|
||||
for (auto const& kfd : other._data) {
|
||||
auto it = find(kfd.key);
|
||||
if (it !=_data.end()) {
|
||||
if (it->f.index != kfd.f.index) TRIQS_RUNTIME_ERROR << "Index mismatch in merging parameters";
|
||||
if (kfd.doc.size()>0) it->doc = kfd.doc;
|
||||
} else
|
||||
_data.push_back(kfd);
|
||||
}
|
||||
|
||||
for (auto const & pvp : pdef) {
|
||||
auto key = pvp.first;
|
||||
|
||||
// check whether required parameters are present
|
||||
if (pdef.is_required(key) && (!this->has_key(key))){
|
||||
// delay exception until all parameters have been checked
|
||||
if (!missing.size()) missing.push_back(desc);
|
||||
missing.push_back({key, pdef.doc(key)});
|
||||
}
|
||||
if (this->has_key(key)) { // check whether the type is correct
|
||||
if (! have_same_type(pvp.second, (*this)[key])){
|
||||
// delay exception until all parameters have been checked
|
||||
if (!wrong_t.size()) wrong_t.push_back(tdesc);
|
||||
wrong_t.push_back({key, pvp.second.type_name(), (*this)[key].type_name()});
|
||||
}
|
||||
}
|
||||
else {
|
||||
(*this)[key] = pvp.second; // insert the default
|
||||
}
|
||||
|
||||
}
|
||||
// raise a runtime exception if errors occured
|
||||
if(missing.size()) TRIQS_RUNTIME_ERROR << "update with defaults : the following parameters are required but absent: \n"<< print_formatted(missing);
|
||||
if(wrong_t.size()) TRIQS_RUNTIME_ERROR << "update with defaults : the following parameters have incorrect type: \n"<< print_formatted(wrong_t);
|
||||
if(no_deft.size()) TRIQS_RUNTIME_ERROR << "update with defaults : the following parameters are absent from the defaults and no_parameter_without_default is ON: \n"<< print_formatted(no_deft);
|
||||
|
||||
}
|
||||
|
||||
}}
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
std::vector<std::vector<std::string>> parameters::generate_help() const {
|
||||
std::vector<std::vector<std::string>> str;
|
||||
str.push_back({"parameter:", "type:", "value:", "description:"});
|
||||
for (auto const& s : _data)
|
||||
if (!s.f.is_modified()) str.push_back({s.key, s.f.type_name(), "-", s.doc});
|
||||
|
||||
for (auto const& s : _data) {
|
||||
if (is_parameter(s.f)) continue; // no subgroup
|
||||
if (s.f.is_modified()) {
|
||||
std::ostringstream val;
|
||||
val << s.f;
|
||||
auto sv = val.str();
|
||||
boost::algorithm::trim(sv);
|
||||
int size_max = 30;
|
||||
if (sv.size()>size_max) {
|
||||
auto s2 = std::string(size_max+5,'.');
|
||||
std::copy(sv.begin(), sv.begin()+size_max/2, s2.begin());
|
||||
std::copy(sv.end()-size_max/2, sv.end(), s2.end()-size_max/2);
|
||||
sv = s2;
|
||||
}
|
||||
std::replace( sv.begin(), sv.end(), '\n', ','); // replace all 'x' to 'y'
|
||||
str.push_back({s.key, s.f.type_name(), sv, s.doc});
|
||||
}
|
||||
}
|
||||
// all sub groups after
|
||||
for (auto const& s : _data) {
|
||||
if (!is_parameter(s.f)) continue;
|
||||
auto p = dynamic_cast<_field::_data_impl<parameters>*>(s.f.p.get());
|
||||
auto str2 = p->x.generate_help();
|
||||
for (auto & x : str2) x[0] = " " + x[0];
|
||||
str2.insert(str2.begin(), {"Sub-group : ", s.key, " ", ""});
|
||||
str.insert(str.end(), str2.begin(), str2.end());
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, parameters const& p) {
|
||||
out << utility::print_formatted(p.generate_help());
|
||||
return out;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
_field& _field::operator[](const char* key) {
|
||||
auto* pp = dynamic_cast<_data_impl<parameters>*>(p.get());
|
||||
if (!pp) TRIQS_RUNTIME_ERROR << "Can only use [] on a subgroup, which " << name() << " is not !";
|
||||
return pp->x.operator[](key);
|
||||
}
|
||||
|
||||
_field const& _field::operator[](const char* key) const {
|
||||
auto* pp = dynamic_cast<_data_impl<parameters>*>(p.get());
|
||||
if (!pp) TRIQS_RUNTIME_ERROR << "Can only use [] on a subgroup, which " << name() << " is not !";
|
||||
return pp->x.operator[](key);
|
||||
}
|
||||
|
||||
bool is_parameter(_field const& f) { return dynamic_cast<_field::_data_impl<parameters>*>(f.p.get()); }
|
||||
|
||||
_field& _field::add_group(std::string const& key, std::string const& doc) {
|
||||
auto* pp = dynamic_cast<_data_impl<parameters>*>(p.get());
|
||||
if (!pp) TRIQS_RUNTIME_ERROR << "Can only use [] on a subgroup, which " << name() << " is not !";
|
||||
pp->x.add_group(key, doc);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,15 +18,16 @@
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_UTILITY_PARAMS_H
|
||||
#define TRIQS_UTILITY_PARAMS_H
|
||||
#include "./opaque_object_h5.hpp"
|
||||
#include "./defaults.hpp"
|
||||
namespace triqs { namespace utility {
|
||||
#pragma once
|
||||
#include "./_field.hpp"
|
||||
namespace triqs {
|
||||
namespace params {
|
||||
|
||||
template<typename T> struct no_default {};
|
||||
/**
|
||||
* Class for storing program parameters.
|
||||
* Parameters can be added to and extracted from the parameter object using the element access operator [].
|
||||
* Each element is stored by means of an object of type _object, which also stores the original type (all
|
||||
* Each element is stored by means of an object of type _field, which also stores the original type (all
|
||||
* integral types are collapsed to long and char* is collapsed to std::string).
|
||||
* When accessing elements, a typecheck is performed. Typecasts are allowed and are similar to the C++ rules
|
||||
* for casts. If the lvalue has type double, a cast from any integral type is allowed. If the lvalue has
|
||||
@ -34,94 +35,80 @@ namespace triqs { namespace utility {
|
||||
* The class is boost-serializable and implements hdf5 I/O operations.
|
||||
*/
|
||||
class parameters {
|
||||
public :
|
||||
parameters() {};
|
||||
parameters (parameters const & other) = default;
|
||||
parameters (parameters && other) noexcept { swap(*this,other);}
|
||||
parameters & operator = (parameters const & other) = default;
|
||||
parameters & operator = (parameters && other) noexcept { swap(*this,other); return *this;}
|
||||
friend void swap(parameters & a, parameters &b) noexcept { swap(a.object_map,b.object_map);}
|
||||
struct _data_elem {
|
||||
std::string key;
|
||||
_field f;
|
||||
std::string doc;
|
||||
template <class Archive> void serialize(Archive& ar, const unsigned int version) {
|
||||
ar& TRIQS_MAKE_NVP("key", key) & TRIQS_MAKE_NVP("f", f) & TRIQS_MAKE_NVP("doc", doc);
|
||||
}
|
||||
};
|
||||
using _data_t = std::vector<_data_elem>;
|
||||
_data_t _data;
|
||||
void insert(std::string const& key, _field&& f, std::string const& doc);
|
||||
_data_t::iterator find(std::string const& key);
|
||||
_data_t::const_iterator find(std::string const& key) const;
|
||||
|
||||
private:
|
||||
typedef std::map<std::string, _object> map_t;
|
||||
map_t object_map;
|
||||
std::map<std::string, std::string> documentation;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int version) { ar & TRIQS_MAKE_NVP("object_map",object_map); }
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive> void serialize(Archive& ar, const unsigned int version) { ar& TRIQS_MAKE_NVP("_data", _data); }
|
||||
|
||||
public:
|
||||
parameters();
|
||||
|
||||
typedef map_t::const_iterator const_iterator;
|
||||
typedef map_t::iterator iterator;
|
||||
const_iterator begin() const { return object_map.begin();}
|
||||
const_iterator end() const { return object_map.end();}
|
||||
iterator begin() { return object_map.begin();}
|
||||
iterator end() { return object_map.end();}
|
||||
/// calls can be chained for multiple parameters
|
||||
template <typename T> parameters& add_field(std::string const& key, T&& x, std::string const& doc) {
|
||||
insert(key, _field{std::forward<T>(x),key, false}, doc);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool has_key(std::string const & k) const { return object_map.find(k) != object_map.end();}
|
||||
// add a field without a default value
|
||||
template <typename T> parameters& add_field(std::string const& key, no_default<T>, std::string const& doc) {
|
||||
insert(key, _field{T{}, key, true}, doc);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
_object & operator[](std::string const & key) {
|
||||
//std::cout << key << std::endl << std::flush;
|
||||
auto & r = object_map[key];
|
||||
if (r.name()=="") r.set_name(key); // in case the object has just been created, set its name
|
||||
return r;
|
||||
}
|
||||
parameters& add_group(std::string const& key, std::string const& doc) {
|
||||
insert(key, _field{parameters{}, key, false}, doc);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
_object const & operator[](std::string const & key) const {
|
||||
auto it = object_map.find(key);
|
||||
if ( it== object_map.end()) TRIQS_RUNTIME_ERROR<<"Parameters : the key : "<< key<< " does not exists";
|
||||
return it->second;
|
||||
}
|
||||
void sort_by_key();
|
||||
|
||||
friend std::string get_triqs_hdf5_data_scheme(parameters const&) { return "";}
|
||||
|
||||
///write contents to an hdf5 archive
|
||||
friend void h5_write ( h5::group F, std::string const & subgroup_name, parameters const & p){
|
||||
auto gr = F.create_group(subgroup_name);
|
||||
for (auto & pvp : p.object_map) h5_write(gr, pvp.first, pvp.second);
|
||||
}
|
||||
bool has_key(std::string const& k) const;
|
||||
|
||||
///read from an hdf5 archive
|
||||
friend void h5_read ( h5::group F, std::string const & subgroup_name, parameters & p);
|
||||
/// Access the parameter key, which must be present (or it throws an exception).
|
||||
_field& operator[](const char * key);
|
||||
_field const& operator[](const char * key) const;
|
||||
|
||||
friend std::ostream & operator << (std::ostream & out, parameters const & p) {
|
||||
out<< "{";
|
||||
for (auto & pvp : p.object_map) out<< pvp.first << " : " << pvp.second<< ", ";
|
||||
return out<<"}";
|
||||
}
|
||||
/// generate help in form of a table of strings containing a list of required and optional parameters
|
||||
std::vector<std::vector<std::string>> generate_help() const;
|
||||
|
||||
/**
|
||||
* Register a type for conversion, serialization and h5 read/write.
|
||||
* Note : can be called multiple times (no effect for second and later call).
|
||||
* Note : this is automatically called when putting an object in parameters
|
||||
*/
|
||||
template<typename T> static void register_type() { _object::register_type<T>::invoke();}
|
||||
|
||||
/**
|
||||
* Update with another parameter set.
|
||||
* If a key is present in other and not in this, add parameter to this.
|
||||
* If a key is present in both, overwrite parameter in this without any check (Python-like behaviour).
|
||||
*/
|
||||
void update(parameters const & pdef);
|
||||
|
||||
/// Flags controlling the update_with_default function
|
||||
//static constexpr ull_t strict_type_check = 1ull; // Type check is strict. Always true now
|
||||
static constexpr ull_t reject_key_without_default = 1ull<<2;
|
||||
|
||||
/**
|
||||
* Update with a default parameters set pdef.
|
||||
* If a key is a default parameter in pdef and not in this, add the pdef parameter and value to this.
|
||||
* If a key is a required parameter in pdef and not in this, then raise triqs::runtime_error exception.
|
||||
* If a key is present in both, do no change it in this, but check that type are the same.
|
||||
* If a key is present in this, and not in pdef, and reject_key_without_default is passed, then raise triqs::runtime_error exception.
|
||||
*/
|
||||
void update(parameter_defaults const & pdef, ull_t flag =0);
|
||||
friend std::string get_triqs_hdf5_data_scheme(parameters) { return ""; }
|
||||
friend void h5_write(h5::group F, std::string const& subgroup_name, parameters const& p);
|
||||
friend void h5_read(h5::group F, std::string const& subgroup_name, parameters& p);
|
||||
friend std::ostream& operator<<(std::ostream& out, parameters const& p);
|
||||
|
||||
/**
|
||||
* Update with another parameter set.
|
||||
* If a key is present in other and not in this, add parameter to this.
|
||||
* If a key is present in both, overwrite parameter in this without any check (Python-like behaviour).
|
||||
*/
|
||||
void update(parameters const&);
|
||||
};
|
||||
|
||||
}}
|
||||
#endif
|
||||
inline parameters operator+(parameters p1, parameters const& p2) {
|
||||
p1.update(p2);
|
||||
return p1;
|
||||
}
|
||||
|
||||
// can only be implemented after complete declaration of parameters
|
||||
template <typename... T> _field& _field::add_field(T&&... x) {
|
||||
auto* pp = dynamic_cast<_data_impl<parameters>*>(p.get());
|
||||
if (!pp) TRIQS_RUNTIME_ERROR << "Can only use add_field on a subgroup, which " << name() << " is not !";
|
||||
pp->x.add_field(std::forward<T>(x)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
18
triqs/python_tools/wrapper_tools.cpp
Normal file
18
triqs/python_tools/wrapper_tools.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
// REMOVE THIS
|
||||
#include <triqs/arrays.hpp>
|
||||
|
||||
#include "./wrapper_tools.hpp"
|
||||
namespace triqs { namespace py_tools {
|
||||
|
||||
template <> const char * make_format<0>::value = "";
|
||||
template <> const char * make_format<1>::value = "O&";
|
||||
template <> const char * make_format<2>::value = "O&O&";
|
||||
template <> const char * make_format<3>::value = "O&O&O&";
|
||||
template <> const char * make_format<4>::value = "O&O&O&O&";
|
||||
template <> const char * make_format<5>::value = "O&O&O&O&O&";
|
||||
|
||||
|
||||
pyref py_converter<triqs::h5::group>::group_type;
|
||||
|
||||
}}
|
@ -1,6 +1,10 @@
|
||||
#pragma once
|
||||
#include <Python.h>
|
||||
#include "structmember.h"
|
||||
#include <string>
|
||||
#include <complex>
|
||||
#include <vector>
|
||||
#include <triqs/utility/exceptions.hpp>
|
||||
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-writable-strings"
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-writable-strings"
|
||||
@ -48,11 +52,12 @@ class pyref {
|
||||
static pyref string(std::string const &s) { return PyString_FromString(s.c_str());}
|
||||
};
|
||||
|
||||
pyref borrowed(PyObject * ob) { Py_XINCREF(ob); return {ob};}
|
||||
inline pyref borrowed(PyObject * ob) { Py_XINCREF(ob); return {ob};}
|
||||
|
||||
//--------------------- py_converters -----------------------------
|
||||
|
||||
template<typename T> struct py_converter {
|
||||
static void ** init();
|
||||
static PyObject * c2py(T const & x);
|
||||
static T py2c(PyObject * ob);
|
||||
static bool is_convertible(PyObject * ob, bool raise_exception);
|
||||
@ -60,12 +65,12 @@ template<typename T> struct py_converter {
|
||||
|
||||
// We only use these functions in the code, not converter
|
||||
// TODO : Does c2py return NULL in failure ? Or is it undefined...
|
||||
template <typename T> PyObject *convert_to_python(T &&x) {
|
||||
template <typename T> static PyObject *convert_to_python(T &&x) {
|
||||
return py_converter<typename std::decay<T>::type>::c2py(std::forward<T>(x));
|
||||
}
|
||||
// can convert_from_python raise a triqs exception ? NO
|
||||
template<typename T> auto convert_from_python(PyObject * ob) DECL_AND_RETURN(py_converter<T>::py2c(ob));
|
||||
template <typename T> bool convertible_from_python(PyObject *ob, bool raise_exception) {
|
||||
template<typename T> static auto convert_from_python(PyObject * ob) -> decltype(py_converter<T>::py2c(ob)) { return py_converter<T>::py2c(ob);}
|
||||
template <typename T> static bool convertible_from_python(PyObject *ob, bool raise_exception) {
|
||||
return py_converter<T>::is_convertible(ob, raise_exception);
|
||||
}
|
||||
|
||||
@ -134,7 +139,6 @@ template <typename T> static int converter_for_parser(PyObject *ob, T *p) {
|
||||
static bool is_convertible(PyObject *ob, bool raise_exception) { return true;}
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
// basic types
|
||||
// -----------------------------------
|
||||
@ -216,6 +220,16 @@ template <> struct py_converter<std::string> {
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct py_converter<const char *> {
|
||||
static PyObject *c2py(const char *x) { return PyString_FromString(x); }
|
||||
static const char * py2c(PyObject *ob) { return PyString_AsString(ob); }
|
||||
static bool is_convertible(PyObject *ob, bool raise_exception) {
|
||||
if (PyString_Check(ob)) return true;
|
||||
if (raise_exception) { PyErr_SetString(PyExc_TypeError, "Can not convert to string");}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// --- h5 group of h5py into a triqs::h5 group
|
||||
|
||||
template <> struct py_converter<triqs::h5::group> {
|
||||
@ -282,9 +296,6 @@ template <typename T> struct py_converter<std::vector<T>> {
|
||||
}
|
||||
};
|
||||
|
||||
// in CPP file ?
|
||||
pyref py_converter<triqs::h5::group>::group_type;
|
||||
|
||||
// --- mini_vector<T,N>---
|
||||
// via std::vector
|
||||
template <typename T, int N> struct py_converter<triqs::utility::mini_vector<T,N>> {
|
||||
@ -305,7 +316,7 @@ template <typename T, int N> struct py_converter<triqs::utility::mini_vector<T,N
|
||||
template <typename ArrayType> struct py_converter_array {
|
||||
static PyObject *c2py(ArrayType const &x) { return x.to_python(); }
|
||||
static ArrayType py2c(PyObject *ob) {
|
||||
return ArrayType {ob};
|
||||
return ArrayType (ob);
|
||||
}
|
||||
static bool is_convertible(PyObject *ob, bool raise_exception) {
|
||||
try {
|
||||
@ -400,12 +411,6 @@ template <> struct _make_index_seq<4> { using type = index_seq<0, 1, 2, 3>; };
|
||||
template <> struct _make_index_seq<5> { using type = index_seq<0, 1, 2, 3, 4>; };
|
||||
|
||||
template <int N> struct make_format { static const char * value;};
|
||||
template <> const char * make_format<0>::value = "";
|
||||
template <> const char * make_format<1>::value = "O&";
|
||||
template <> const char * make_format<2>::value = "O&O&";
|
||||
template <> const char * make_format<3>::value = "O&O&O&";
|
||||
template <> const char * make_format<4>::value = "O&O&O&O&";
|
||||
template <> const char * make_format<5>::value = "O&O&O&O&O&";
|
||||
|
||||
template <typename R, typename... T> struct py_converter<std::function<R(T...)>> {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user