From f2c7d449cc0a4048550624ddc7c61af4bc3b0f5e Mon Sep 17 00:00:00 2001 From: Olivier Parcollet Date: Wed, 17 Jul 2013 19:24:07 +0200 Subject: [PATCH] First commit : triqs libs version 1.0 alpha1 for earlier commits, see TRIQS0.x repository. --- CITATIONS.bib | 99 + CMakeLists.txt | 474 ++ COPYING.txt | 674 ++ LICENSE.txt | 18 + README.txt | 13 + cmake/BuildSphinx.cmake | 47 + cmake/CompileBoost.cmake | 302 + cmake/Doxyfile.in | 1290 ++++ cmake/FindBuildF2pyModule.cmake | 38 + cmake/FindCompilerCheck.cmake | 91 + cmake/FindCythonModuleMacro.cmake | 35 + cmake/FindFFTW.cmake | 38 + cmake/FindGMP.cmake | 24 + cmake/FindGSL.cmake | 38 + cmake/FindGit3.cmake | 79 + cmake/FindLapack.cmake | 290 + cmake/FindMathJax.cmake | 23 + cmake/FindPython.cmake | 178 + cmake/FindTRIQS.cmake | 58 + cmake/FindTestCSimple.cmake | 44 + cmake/FindTestScriptHdf.cmake | 55 + cmake/FindTriqsMacros.cmake | 15 + cmake/FindTriqsTest.cmake.in | 101 + cmake/TRIQSConfig.cmake.in | 101 + cmake/postinst.in | 4 + cmake/prerm.in | 4 + cmake/run_test.cmake | 63 + cmake/run_test_simple.cmake | 64 + cmake/triqs_config.h.in | 18 + doc/CMakeLists.txt | 114 + doc/_templates/index.html | 193 + doc/_templates/layout.html | 19 + doc/conf.py.in | 245 + doc/contents.rst | 14 + doc/faq/faq.rst | 21 + doc/faq/relativedirforboost.rst | 7 + doc/faq/typeerrorunicode.rst | 7 + doc/installation/Ubuntu.rst | 73 + doc/installation/changelog.rst | 16 + doc/installation/clang.rst | 47 + doc/installation/dependencies.rst | 68 + doc/installation/get_started.rst | 34 + doc/installation/install.rst | 49 + doc/installation/install_on_osx_lion.rst | 113 + doc/installation/install_options.rst | 106 + doc/installation/intel.rst | 54 + doc/installation/ipython.rst | 24 + doc/installation/linux.rst | 51 + doc/installation/python.rst | 66 + doc/installation/wien2k_inst.rst | 27 + doc/license/collaboration.rst | 71 + doc/license/ctqmc1.bib | 14 + doc/license/ctqmc2.bib | 14 + doc/license/ctqmc3.bib | 14 + doc/license/legal/CITATIONS.bib | 93 + doc/license/legal/CITATIONS.rst | 3 + doc/license/legal/COPYING.txt | 674 ++ doc/license/legal/GPL.rst | 6 + doc/license/legal/License.rst | 6 + doc/license/legal/License.txt | 23 + doc/license/legal/legal.rst | 44 + doc/license/wien2k1.bib | 15 + doc/license/wien2k2.bib | 14 + doc/overview.rst | 209 + doc/reference/c++/CMakeLists.txt | 3 + doc/reference/c++/CMakeLists.txt.v1 | 86 + doc/reference/c++/arrays/CMakeLists.txt | 10 + .../c++/arrays/Design/centralconcept.rst | 39 + doc/reference/c++/arrays/Design/concepts.rst | 252 + doc/reference/c++/arrays/Design/contents.rst | 11 + .../c++/arrays/Design/cuboid_formula.rst | 60 + doc/reference/c++/arrays/Design/slicing.rst | 52 + doc/reference/c++/arrays/Design/strategy.rst | 62 + doc/reference/c++/arrays/FAQ.rst | 24 + doc/reference/c++/arrays/H5.rst | 27 + doc/reference/c++/arrays/IO.rst | 39 + doc/reference/c++/arrays/Interop_Python.rst | 78 + doc/reference/c++/arrays/Iterators.rst | 2 + doc/reference/c++/arrays/STL.rst | 67 + doc/reference/c++/arrays/algebras.rst | 114 + doc/reference/c++/arrays/all.rst | 360 + doc/reference/c++/arrays/arrays.rst | 139 + doc/reference/c++/arrays/assignment.rst | 66 + doc/reference/c++/arrays/basic_classes.rst | 103 + doc/reference/c++/arrays/basic_interop.rst | 21 + doc/reference/c++/arrays/blas_lapack.rst | 88 + doc/reference/c++/arrays/call.rst | 25 + doc/reference/c++/arrays/class_diff.rst | 33 + .../c++/arrays/compound_assignment.rst | 91 + doc/reference/c++/arrays/compound_ops.rst | 21 + doc/reference/c++/arrays/construct.rst | 117 + doc/reference/c++/arrays/contents.rst | 36 + doc/reference/c++/arrays/contents.rst.1 | 20 + doc/reference/c++/arrays/cookbook/basic.rst | 220 + .../c++/arrays/cookbook/contents.rst | 12 + .../c++/arrays/cookbook/intermediate.rst | 6 + doc/reference/c++/arrays/debug.rst | 40 + doc/reference/c++/arrays/element_acces.rst | 27 + .../c++/arrays/examples_h5/CMakeLists.txt | 19 + .../c++/arrays/examples_h5/h5_rw.cpp | 20 + .../c++/arrays/examples_h5/h5_rw.output | 0 .../c++/arrays/examples_h5/h5_stack_ex.cpp | 23 + .../c++/arrays/examples_h5/h5_stack_ex.output | 0 .../arrays/examples_h5/h5_stack_ex_sca.cpp | 18 + .../arrays/examples_h5/h5_stack_ex_sca.output | 0 doc/reference/c++/arrays/expr_arith.rst | 104 + doc/reference/c++/arrays/expr_custom.rst | 59 + doc/reference/c++/arrays/expr_predef.rst | 22 + doc/reference/c++/arrays/expression.rst | 48 + doc/reference/c++/arrays/fold.rst | 57 + doc/reference/c++/arrays/foreach.rst | 105 + doc/reference/c++/arrays/group_indices.rst | 13 + doc/reference/c++/arrays/h5_complex.rst | 15 + doc/reference/c++/arrays/h5_proxy.rst | 47 + doc/reference/c++/arrays/h5_rw.rst | 38 + doc/reference/c++/arrays/h5_stack.rst | 42 + doc/reference/c++/arrays/introduction.rst | 38 + doc/reference/c++/arrays/lazy.rst | 49 + doc/reference/c++/arrays/map.rst | 128 + doc/reference/c++/arrays/mapped_fnt.rst | 49 + doc/reference/c++/arrays/matrix.rst | 101 + .../c++/arrays/memory_management.rst | 40 + doc/reference/c++/arrays/move_swap.rst | 67 + doc/reference/c++/arrays/options.rst | 79 + doc/reference/c++/arrays/python_tools.rst | 18 + doc/reference/c++/arrays/shape.rst | 50 + doc/reference/c++/arrays/slicing.rst | 101 + doc/reference/c++/arrays/vector.rst | 98 + doc/reference/c++/arrays/view_or_not_view.rst | 54 + doc/reference/c++/arrays/views.rst | 66 + .../c++/arrays_old/CMakeLists.txt.Old | 22 + doc/reference/c++/arrays_old/FAQ.rst | 18 + doc/reference/c++/arrays_old/H5.rst | 20 + doc/reference/c++/arrays_old/IO.rst | 44 + .../c++/arrays_old/Interop_Python.rst | 151 + doc/reference/c++/arrays_old/Iterators.rst | 2 + doc/reference/c++/arrays_old/STL.rst | 92 + doc/reference/c++/arrays_old/algebras.rst | 98 + doc/reference/c++/arrays_old/all.rst | 361 + doc/reference/c++/arrays_old/arrays.rst | 120 + doc/reference/c++/arrays_old/assignment.rst | 91 + .../c++/arrays_old/basic_classes.rst | 23 + .../c++/arrays_old/basic_interop.rst | 21 + doc/reference/c++/arrays_old/blas_lapack.rst | 60 + .../c++/arrays_old/centralconcept.rst | 39 + doc/reference/c++/arrays_old/compound_ops.rst | 21 + doc/reference/c++/arrays_old/contents.rst | 33 + doc/reference/c++/arrays_old/debug.rst | 48 + .../c++/arrays_old/design/concepts.rst | 270 + .../c++/arrays_old/design/contents.rst | 10 + .../c++/arrays_old/design/cuboid_formula.rst | 60 + .../c++/arrays_old/design/slicing.rst | 51 + .../c++/arrays_old/design/strategy.rst | 62 + doc/reference/c++/arrays_old/expr_arith.rst | 104 + doc/reference/c++/arrays_old/expr_custom.rst | 59 + doc/reference/c++/arrays_old/expr_predef.rst | 22 + doc/reference/c++/arrays_old/expression.rst | 48 + doc/reference/c++/arrays_old/foreach.rst | 7 + doc/reference/c++/arrays_old/functional.rst | 78 + .../c++/arrays_old/getting_started.rst | 8 + doc/reference/c++/arrays_old/h5_complex.rst | 14 + doc/reference/c++/arrays_old/h5_proxy.rst | 47 + doc/reference/c++/arrays_old/h5_rw.rst | 20 + doc/reference/c++/arrays_old/h5_stack.rst | 42 + doc/reference/c++/arrays_old/introduction.rst | 67 + doc/reference/c++/arrays_old/matrix.rst | 101 + .../c++/arrays_old/memory_management.rst | 40 + doc/reference/c++/arrays_old/options.rst | 79 + doc/reference/c++/arrays_old/python_tools.rst | 18 + doc/reference/c++/arrays_old/shape.rst | 33 + doc/reference/c++/arrays_old/slicing.rst | 101 + doc/reference/c++/arrays_old/vector.rst | 98 + .../c++/arrays_old/view_or_not_view.rst | 80 + doc/reference/c++/clef/CMakeLists.txt | 1 + doc/reference/c++/clef/assign.rst | 114 + doc/reference/c++/clef/contents.rst | 23 + doc/reference/c++/clef/copy_policy.rst | 40 + doc/reference/c++/clef/examples/contents.rst | 12 + .../c++/clef/examples/lazy_function.rst | 16 + doc/reference/c++/clef/examples/lazy_sum.rst | 20 + .../c++/clef/examples/vector_and_math.rst | 25 + doc/reference/c++/clef/expressions.rst | 113 + doc/reference/c++/clef/expressions_eval.rst | 60 + doc/reference/c++/clef/expressions_form.rst | 132 + doc/reference/c++/clef/function.rst | 98 + doc/reference/c++/clef/introduction.rst | 15 + doc/reference/c++/clef/lazy_call.rst | 226 + doc/reference/c++/clef/lazy_function_cls.rst | 16 + doc/reference/c++/conf.py.in | 235 + doc/reference/c++/contents.rst | 16 + doc/reference/c++/det_manip/CMakeLists.txt | 11 + doc/reference/c++/det_manip/contents.rst | 37 + doc/reference/c++/det_manip/cookbook.rst | 70 + doc/reference/c++/det_manip/det_manip.rst | 122 + doc/reference/c++/gf/CMakeLists.txt | 11 + doc/reference/c++/gf/concepts.rst | 314 + doc/reference/c++/gf/contents.rst | 38 + doc/reference/c++/gf/cookbook/contents.rst | 11 + doc/reference/c++/gf/cookbook/imaginary.rst | 61 + doc/reference/c++/gf/cookbook/real.rst | 41 + doc/reference/c++/gf/fourier.rst | 40 + doc/reference/c++/intro.rst | 8 + doc/reference/c++/learn/first_mc.rst | 64 + doc/reference/c++/learn/intro.rst | 24 + doc/reference/c++/learn/m_vs_beta.png | Bin 0 -> 5290 bytes doc/reference/c++/learn/triqs_library.rst | 106 + doc/reference/c++/lectures/basic/C++11.rst | 326 + .../lectures/basic/compile_time_decision.rst | 13 + doc/reference/c++/lectures/basic/contents.rst | 16 + .../c++/lectures/basic/functions.rst | 14 + .../c++/lectures/basic/smart_ptr.rst | 182 + doc/reference/c++/lectures/contents.rst | 30 + doc/reference/c++/lectures/goal.rst | 25 + doc/reference/c++/lectures/intro.rst | 31 + .../lectures/patterns/assign_delegation.rst | 133 + .../c++/lectures/patterns/contents.rst | 24 + .../c++/lectures/patterns/h5_read_write.rst | 148 + .../c++/lectures/patterns/lazy_objects.rst | 47 + .../c++/lectures/patterns/python.rst | 57 + .../c++/lectures/patterns/type_erasure.rst | 55 + .../c++/lectures/patterns/view_value.rst | 18 + .../lectures/patterns/writing_an_iterator.rst | 42 + doc/reference/c++/lectures/smart_pointers.cpp | 91 + doc/reference/c++/mctools/CMakeLists.txt | 2 + doc/reference/c++/mctools/intro.rst | 18 + doc/reference/c++/mctools/ising.rst | 219 + doc/reference/c++/mctools/loop.png | Bin 0 -> 59821 bytes doc/reference/c++/mctools/loop.rst | 75 + doc/reference/c++/mctools/overview.rst | 355 + doc/reference/c++/mctools/random.rst | 96 + doc/reference/c++/mctools/reference.rst | 82 + doc/reference/c++/parameters/CMakeLists.txt | 3 + doc/reference/c++/parameters/parameters.rst | 191 + doc/reference/c++/utility.rst | 54 + doc/reference/python/CMakeLists.txt | 45 + doc/reference/python/conf.py.in | 209 + doc/reference/python/contents.rst | 23 + .../python/data_analysis/contents.rst | 26 + .../python/data_analysis/fit/demo1.py | 47 + .../python/data_analysis/fit/demo1_prepare.py | 14 + .../python/data_analysis/fit/fit.png | Bin 0 -> 66792 bytes .../python/data_analysis/fit/fit.rst | 48 + .../python/data_analysis/fit/fit_test.py | 26 + .../python/data_analysis/hdf5/CMakeLists.txt | 11 + .../python/data_analysis/hdf5/contents.rst | 48 + .../python/data_analysis/hdf5/protocol1.rst | 90 + .../python/data_analysis/hdf5/protocol2.rst | 9 + .../python/data_analysis/hdf5/ref.rst | 218 + .../python/data_analysis/hdf5/tut_ex1.py | 11 + .../python/data_analysis/hdf5/tut_ex1.rst | 65 + .../python/data_analysis/hdf5/tut_ex2.py | 16 + .../python/data_analysis/hdf5/tut_ex2.rst | 48 + .../python/data_analysis/hdf5/tut_ex2b.py | 9 + .../python/data_analysis/hdf5/tut_ex3.py | 12 + .../python/data_analysis/hdf5/tut_ex3.rst | 42 + .../python/data_analysis/hdf5/tut_ex3b.png | Bin 0 -> 62478 bytes .../python/data_analysis/hdf5/tut_ex3b.py | 15 + .../python/data_analysis/hdf5/tut_hdf1.png | Bin 0 -> 141624 bytes .../python/data_analysis/hdf5/tutorial.rst | 15 + .../python/data_analysis/plotting/example.png | Bin 0 -> 62486 bytes .../python/data_analysis/plotting/example.py | 15 + .../data_analysis/plotting/myobject.png | Bin 0 -> 52082 bytes .../python/data_analysis/plotting/myobject.py | 17 + .../data_analysis/plotting/myobject2.png | Bin 0 -> 68117 bytes .../data_analysis/plotting/myobject2.py | 20 + .../data_analysis/plotting/plotting.rst | 105 + .../python/data_analysis/provenance.rst | 101 + doc/reference/python/green/block.rst | 221 + doc/reference/python/green/block/GfImFreq.rst | 54 + doc/reference/python/green/block/GfImTime.rst | 50 + .../python/green/block/GfLegendre.rst | 55 + doc/reference/python/green/block/GfReFreq.rst | 62 + doc/reference/python/green/block/GfReTime.rst | 49 + .../python/green/block/green_imfreq.py | 11 + .../python/green/block/green_imtime.py | 13 + .../python/green/block/green_legendre.py | 14 + .../python/green/block/green_pade.py | 44 + .../python/green/block/green_refreq.py | 13 + .../python/green/block/green_retime.py | 12 + doc/reference/python/green/descriptors.rst | 31 + doc/reference/python/green/example.py | 10 + doc/reference/python/green/fourier.py | 11 + doc/reference/python/green/full.rst | 231 + doc/reference/python/green/green.rst | 38 + doc/reference/python/green/impinbath.py | 17 + doc/reference/python/green/legendre.py | 12 + doc/reference/python/green/transforms.rst | 33 + doc/reference/python/green/tutorial.rst | 109 + doc/reference/python/lattice/bravais.rst | 13 + doc/reference/python/lattice/dos.rst | 35 + doc/reference/python/lattice/ex1.png | Bin 0 -> 27250 bytes doc/reference/python/lattice/ex1.py | 40 + doc/reference/python/lattice/ex_Hilbert.py | 28 + doc/reference/python/lattice/hilbert.rst | 29 + doc/reference/python/lattice/lattice.rst | 40 + doc/reference/python/lattice/sumk.rst | 13 + doc/reference/python/lattice/tightbinding.rst | 9 + .../python/misc/python-powered-w-200x80.png | Bin 0 -> 8758 bytes doc/themes/agogo/layout.html | 92 + doc/themes/agogo/static/agogo.css_t | 519 ++ doc/themes/agogo/static/bgfooter.png | Bin 0 -> 434 bytes doc/themes/agogo/static/bgtop.png | Bin 0 -> 430 bytes doc/themes/agogo/theme.conf | 20 + doc/tutorials/c++/contents.rst | 8 + doc/tutorials/contents.rst | 10 + doc/tutorials/python/aim_plot1.png | Bin 0 -> 35018 bytes doc/tutorials/python/introduction.rst | 40 + doc/tutorials/python/logo.png | Bin 0 -> 14699 bytes doc/tutorials/python/reading.rst | 29 + doc/tutorials/python/tour1.rst | 26 + doc/tutorials/python/tour2.rst | 20 + doc/tutorials/python/tour3.rst | 47 + doc/tutorials/python/tour4.rst | 24 + examples/simple/CMakeLists.txt | 10 + examples/simple/hdf5.cpp | 104 + foreignlibs/autocompile/autocompile.py | 112 + foreignlibs/autocompile/autorun.py | 103 + foreignlibs/autocompile/pycon.py | 34 + foreignlibs/boost/CMakeLists.txt | 90 + foreignlibs/boost/__init__.py | 10 + foreignlibs/breathe/LICENCE | 28 + foreignlibs/breathe/README.rst | 70 + foreignlibs/breathe/breathe/__init__.py | 841 +++ .../breathe/breathe/finder/__init__.py | 65 + .../breathe/finder/doxygen/__init__.py | 147 + .../breathe/breathe/finder/doxygen/base.py | 10 + .../breathe/finder/doxygen/compound.py | 65 + .../breathe/breathe/finder/doxygen/index.py | 84 + .../breathe/breathe/parser/__init__.py | 83 + .../breathe/parser/doxygen/__init__.py | 0 .../breathe/parser/doxygen/compound.py | 867 +++ .../breathe/parser/doxygen/compoundsuper.py | 5801 +++++++++++++++++ .../breathe/breathe/parser/doxygen/index.py | 57 + .../breathe/parser/doxygen/indexsuper.py | 363 ++ .../breathe/breathe/renderer/__init__.py | 0 .../breathe/breathe/renderer/rst/__init__.py | 2 + .../breathe/renderer/rst/doxygen/__init__.py | 406 ++ .../breathe/renderer/rst/doxygen/base.py | 24 + .../breathe/renderer/rst/doxygen/compound.py | 778 +++ .../breathe/renderer/rst/doxygen/domain.py | 240 + .../breathe/renderer/rst/doxygen/filter.py | 454 ++ .../breathe/renderer/rst/doxygen/index.py | 115 + .../breathe/renderer/rst/doxygen/target.py | 40 + foreignlibs/doxylink/__init__.py | 2 + foreignlibs/doxylink/doxylink.py | 454 ++ foreignlibs/doxylink/parsing.py | 153 + foreignlibs/mpl/apigen.py | 427 ++ foreignlibs/mpl/docscrape.py | 497 ++ foreignlibs/mpl/docscrape_sphinx.py | 136 + foreignlibs/mpl/inheritance_diagram.py | 407 ++ .../mpl/ipython_console_highlighting.py | 114 + foreignlibs/mpl/numpydoc.py | 116 + foreignlibs/mpl/plot_directive.py | 773 +++ pytriqs/CMakeLists.txt | 24 + pytriqs/__init__.py | 32 + pytriqs/__init__.py.template | 3 + pytriqs/archive/CMakeLists.txt | 10 + pytriqs/archive/__init__.py | 24 + pytriqs/archive/hdf_archive.py | 410 ++ .../archive/hdf_archive_basic_layer_h5py.py | 131 + pytriqs/archive/hdf_archive_schemes.py | 59 + pytriqs/dos/CMakeLists.txt | 9 + pytriqs/dos/__init__.py | 26 + pytriqs/dos/dos.py | 191 + pytriqs/dos/hilbert_transform.py | 179 + pytriqs/fit/CMakeLists.txt | 8 + pytriqs/fit/__init__.py | 25 + pytriqs/fit/fit.py | 70 + pytriqs/gf/CMakeLists.txt | 10 + pytriqs/gf/__init__.py | 31 + pytriqs/gf/local/CMakeLists.txt | 30 + pytriqs/gf/local/__init__.py | 42 + pytriqs/gf/local/block_gf.py | 376 ++ pytriqs/gf/local/descriptors.py | 337 + pytriqs/gf/local/functions.pxd | 31 + pytriqs/gf/local/gf.pxd | 62 + pytriqs/gf/local/gf.pyx | 26 + pytriqs/gf/local/gf_generic.py | 403 ++ pytriqs/gf/local/gf_imfreq.py | 140 + pytriqs/gf/local/gf_imtime.py | 70 + pytriqs/gf/local/gf_legendre.py | 67 + pytriqs/gf/local/gf_refreq.py | 67 + pytriqs/gf/local/gf_retime.py | 67 + pytriqs/gf/local/gf_two_real_times.py | 69 + pytriqs/gf/local/imfreq.pxd | 56 + pytriqs/gf/local/imfreq.pyx | 81 + pytriqs/gf/local/impl_plot.py | 53 + pytriqs/gf/local/imtime.pxd | 57 + pytriqs/gf/local/imtime.pyx | 83 + pytriqs/gf/local/inverse.py | 32 + pytriqs/gf/local/lazy_expressions.py | 187 + pytriqs/gf/local/legendre.pxd | 54 + pytriqs/gf/local/legendre.pyx | 81 + pytriqs/gf/local/matrix_stack.pxd | 17 + pytriqs/gf/local/matrix_stack.pyx | 34 + pytriqs/gf/local/mesh_imfreq.pyx | 33 + pytriqs/gf/local/mesh_imtime.pyx | 37 + pytriqs/gf/local/mesh_legendre.pyx | 32 + pytriqs/gf/local/mesh_refreq.pyx | 34 + pytriqs/gf/local/mesh_retime.pyx | 34 + pytriqs/gf/local/mesh_two_real_times.pyx | 34 + pytriqs/gf/local/nothing.py | 43 + pytriqs/gf/local/refreq.pxd | 56 + pytriqs/gf/local/refreq.pyx | 78 + pytriqs/gf/local/retime.pxd | 56 + pytriqs/gf/local/retime.pyx | 75 + pytriqs/gf/local/tail.pxd | 37 + pytriqs/gf/local/tail.pyx | 190 + pytriqs/gf/local/tools.py | 82 + pytriqs/gf/local/two_real_times.pxd | 59 + pytriqs/gf/local/two_real_times.pyx | 71 + pytriqs/lattice/CMakeLists.txt | 16 + pytriqs/lattice/__init__.py | 23 + pytriqs/lattice/bz_patch.py | 55 + pytriqs/lattice/lattice_tools.pyx | 105 + pytriqs/lattice/super_lattice.py | 195 + pytriqs/lattice/tight_binding.py | 86 + pytriqs/parameters/CMakeLists.txt | 12 + pytriqs/parameters/__init__.py | 31 + pytriqs/parameters/parameters.pxd | 21 + pytriqs/parameters/parameters.pyx | 86 + pytriqs/plot/CMakeLists.txt | 9 + pytriqs/plot/__init__.py | 23 + pytriqs/plot/mpl_interface.py | 93 + pytriqs/plot/protocol.py | 75 + pytriqs/pxd/CMakeLists.txt | 3 + pytriqs/pxd/arrays.pxd | 72 + pytriqs/pxd/boost.pxd | 5 + pytriqs/pxd/clef.pxd | 66 + pytriqs/pxd/dcomplex.pxd | 21 + pytriqs/pxd/extractor.pxd | 13 + pytriqs/pxd/h5.pxd | 17 + pytriqs/pxd/inserter_in_map.pxd | 15 + pytriqs/pxd/shared_ptr.pxd | 8 + pytriqs/sumk/CMakeLists.txt | 9 + pytriqs/sumk/__init__.py | 26 + pytriqs/sumk/sumk_discrete.py | 147 + pytriqs/sumk/sumk_discrete_from_lattice.py | 178 + pytriqs/utility/CMakeLists.txt | 12 + pytriqs/utility/__init__.py | 23 + pytriqs/utility/dichotomy.py | 99 + pytriqs/utility/dist_on_nodes.py | 154 + pytriqs/utility/mpi.py | 110 + pytriqs/utility/redirect.py | 66 + pytriqs/version.py.in | 28 + shells/CMakeLists.txt | 30 + shells/ipytriqs_shell.bash.in | 13 + shells/ipytriqs_shell.nopypath.bash.in | 13 + shells/ipytriqs_shell.notebook.bash.in | 13 + .../ipytriqs_shell.notebook.nopypath.bash.in | 12 + shells/pytriqs_for_test_shell.bash.in | 5 + shells/pytriqs_shell.bash.in | 4 + shells/pytriqs_shell.nopypath.bash.in | 4 + test/CMakeLists.txt | 16 + test/pytriqs/CMakeLists.txt | 4 + test/pytriqs/arrays/CMakeLists.txt | 10 + test/pytriqs/arrays/__init__.py | 24 + test/pytriqs/arrays/array_cython.output | 107 + test/pytriqs/arrays/array_cython.py | 27 + test/pytriqs/arrays/array_cython.pyx | 28 + test/pytriqs/arrays/bug.hpp | 7 + test/pytriqs/arrays/bug.pyx | 27 + test/pytriqs/arrays/expr.py | 7 + test/pytriqs/arrays/expr.pyx | 39 + test/pytriqs/arrays/f.hpp | 16 + test/pytriqs/base/CMakeLists.txt | 23 + test/pytriqs/base/dos.output.h5 | Bin 0 -> 5088 bytes test/pytriqs/base/dos.py | 51 + test/pytriqs/base/gf_base_op.output.h5 | Bin 0 -> 127648 bytes test/pytriqs/base/gf_base_op.py | 77 + test/pytriqs/base/gf_bcast.py | 51 + test/pytriqs/base/gf_init.output.h5 | Bin 0 -> 45824 bytes test/pytriqs/base/gf_init.py | 50 + test/pytriqs/base/h5_example.output.h5 | Bin 0 -> 12968 bytes test/pytriqs/base/h5_example.py | 42 + test/pytriqs/base/hdf5_io.output.h5 | Bin 0 -> 12968 bytes test/pytriqs/base/hdf5_io.py | 49 + test/pytriqs/base/pade.output.h5 | Bin 0 -> 28512 bytes test/pytriqs/base/pade.py | 59 + test/pytriqs/base/test_example.output | 1 + test/pytriqs/base/test_example.py | 28 + test/pytriqs/parameters/test.py | 39 + test/speed/CMakeLists.txt | 6 + test/speed/apply_on_tuple_s.cpp | 58 + test/speed/array1.cpp | 171 + test/speed/array2.cpp | 140 + test/speed/array_lazy_assign.cpp | 67 + test/speed/array_short1.cpp | 171 + test/speed/clef1.cpp | 63 + test/speed/clef_common.hpp | 67 + test/speed/gemv.cpp | 67 + test/speed/gf_s.cpp | 69 + test/speed/isol_array_foreach_pb.cpp | 24 + test/speed/matmul_s.cpp | 79 + test/speed/pool.cpp | 31 + test/speed/speed_tester.hpp | 52 + test/triqs/CMakeLists.txt | 21 + test/triqs/arrays/CMakeLists.txt | 2 + test/triqs/arrays/a_x_ty.cpp | 73 + test/triqs/arrays/a_x_ty.output | 25 + test/triqs/arrays/algorithms.cpp | 48 + test/triqs/arrays/algorithms.output | 17 + test/triqs/arrays/alias_matmul.cpp | 40 + test/triqs/arrays/array_algebra.cpp | 53 + test/triqs/arrays/array_cache2.cpp | 94 + test/triqs/arrays/array_cache2.output | 50 + test/triqs/arrays/array_mpi.cpp | 65 + test/triqs/arrays/array_mpi.output | 8 + test/triqs/arrays/assign_vect_array.cpp | 42 + test/triqs/arrays/assign_vect_array.output | 2 + test/triqs/arrays/assignment.cpp | 75 + test/triqs/arrays/assignment.output | 27 + test/triqs/arrays/blas_lapack.cpp | 98 + test/triqs/arrays/blas_lapack.output | 30 + test/triqs/arrays/bound_check.cpp | 89 + test/triqs/arrays/bound_check.output | 5 + test/triqs/arrays/bug2.cpp | 33 + test/triqs/arrays/bug3.cpp | 21 + test/triqs/arrays/common.hpp | 34 + test/triqs/arrays/compound_ops.cpp | 63 + test/triqs/arrays/compound_ops.output | 14 + test/triqs/arrays/create.cpp | 47 + test/triqs/arrays/create.output | 1 + test/triqs/arrays/cross_construct.cpp | 60 + test/triqs/arrays/dot.cpp | 63 + test/triqs/arrays/eigenelements.cpp | 75 + test/triqs/arrays/eigenelements.output | 31 + test/triqs/arrays/ellipsis.cpp | 75 + test/triqs/arrays/ellipsis.output | 0 test/triqs/arrays/expr3.cpp.no-built | 218 + test/triqs/arrays/expr3.output | 61 + test/triqs/arrays/expr_matrix.cpp | 96 + test/triqs/arrays/expr_matrix.output | 65 + test/triqs/arrays/fill_with_lazy.cpp | 38 + test/triqs/arrays/fill_with_lazy.output | 6 + test/triqs/arrays/fold_expression.cpp | 57 + test/triqs/arrays/fold_expression.output | 18 + test/triqs/arrays/group_indices.cpp | 63 + test/triqs/arrays/group_indices.output | 46 + test/triqs/arrays/h5_proxy.cpp.no-built | 127 + test/triqs/arrays/h5_stack.cpp | 111 + test/triqs/arrays/h5_string_arrays.cpp | 65 + test/triqs/arrays/h5_vector_array.cpp | 64 + test/triqs/arrays/hdf5.cpp | 107 + test/triqs/arrays/hdf5.output | 22 + test/triqs/arrays/init_check.cpp | 43 + test/triqs/arrays/init_check.output | 0 test/triqs/arrays/init_list.cpp | 52 + test/triqs/arrays/init_list.output | 10 + test/triqs/arrays/inverse2.cpp | 110 + test/triqs/arrays/inverse2.output | 51 + test/triqs/arrays/iterators.cpp | 85 + test/triqs/arrays/iterators.output | 59 + test/triqs/arrays/lapack_on_view.cpp | 25 + test/triqs/arrays/lexico_vector.cpp | 61 + test/triqs/arrays/make_immutables.cpp | 40 + test/triqs/arrays/make_immutables.output | 5 + test/triqs/arrays/map_expression.cpp | 57 + test/triqs/arrays/map_expression.output | 30 + test/triqs/arrays/mapped_functions.cpp | 63 + test/triqs/arrays/mapped_functions.output | 205 + test/triqs/arrays/mat_stack.cpp | 89 + test/triqs/arrays/mat_stack.output | 77 + test/triqs/arrays/mat_vec_mul.cpp | 91 + test/triqs/arrays/mat_vec_mul.output | 49 + test/triqs/arrays/mat_vec_mul2.cpp | 58 + test/triqs/arrays/matmul.cpp | 90 + test/triqs/arrays/matmul2.cpp | 52 + test/triqs/arrays/matrix_transpose.cpp | 57 + test/triqs/arrays/matrix_transpose.output | 18 + test/triqs/arrays/move.cpp | 47 + test/triqs/arrays/move.output | 2 + test/triqs/arrays/negate.cpp | 76 + test/triqs/arrays/non_numeric.cpp | 91 + test/triqs/arrays/non_numeric.output | 14 + test/triqs/arrays/permu.cpp | 78 + test/triqs/arrays/permu.output | 28 + test/triqs/arrays/printing.cpp | 61 + test/triqs/arrays/printing.output | 10 + test/triqs/arrays/scalar_assign.cpp | 47 + test/triqs/arrays/scalar_assign.output | 12 + test/triqs/arrays/serialization.cpp | 81 + test/triqs/arrays/serialization.output | 17 + test/triqs/arrays/slice_index_order.cpp | 115 + test/triqs/arrays/src | 1 + test/triqs/arrays/swap.cpp | 85 + test/triqs/arrays/swap.output | 11 + test/triqs/arrays/tridiag.cpp | 60 + test/triqs/arrays/vector_brack.cpp | 39 + test/triqs/arrays/vector_brack.output | 4 + test/triqs/arrays/vector_cmul.cpp | 53 + test/triqs/arrays/vector_cmul.output | 3 + test/triqs/arrays/vector_copy.cpp | 64 + test/triqs/arrays/vector_copy.output | 10 + test/triqs/arrays/views.cpp | 79 + test/triqs/arrays/views.output | 20 + test/triqs/arrays/views3.cpp | 87 + test/triqs/arrays/views3.output | 85 + test/triqs/arrays/withSTL.cpp | 97 + test/triqs/arrays/withSTL.output | 15 + test/triqs/clef/CMakeLists.txt | 2 + test/triqs/clef/F7.cpp | 50 + test/triqs/clef/F7.output | 1 + test/triqs/clef/array_as_value.output | 16 + test/triqs/clef/array_as_value_long.output | 13 + test/triqs/clef/chain_call.cpp | 50 + test/triqs/clef/chain_call.output | 7 + test/triqs/clef/common.hpp | 67 + test/triqs/clef/function.cpp | 38 + test/triqs/clef/function.output | 11 + test/triqs/clef/general.cpp | 107 + test/triqs/clef/general.output | 61 + test/triqs/clef/lazy.cpp | 34 + test/triqs/clef/lazy.output | 10 + test/triqs/clef/lazy_function.cpp | 46 + test/triqs/clef/lazy_function.output | 14 + test/triqs/clef/math_functions.cpp | 40 + test/triqs/clef/math_functions.output | 10 + test/triqs/clef/test1.cpp | 106 + test/triqs/clef_examples/CMakeLists.txt | 2 + test/triqs/clef_examples/lazyfunction.cpp | 40 + test/triqs/clef_examples/lazyfunction2.output | 6 + test/triqs/clef_examples/simple.cpp | 18 + test/triqs/clef_examples/simple2.output | 4 + test/triqs/clef_examples/sum_functional.cpp | 56 + .../clef_examples/sum_functional2.output | 4 + test/triqs/clef_examples/vector_and_math.cpp | 23 + .../clef_examples/vector_and_math2.output | 10 + test/triqs/det_manip/CMakeLists.txt | 2 + test/triqs/det_manip/det_manip1.cpp | 125 + test/triqs/det_manip/det_manip2.cpp | 102 + test/triqs/det_manip/det_manipc1.cpp | 131 + test/triqs/det_manip/det_manipc2.cpp | 132 + test/triqs/gf/CMakeLists.txt | 3 + test/triqs/gf/block.cpp | 78 + test/triqs/gf/block.output | 27 + test/triqs/gf/fourier1.cpp | 35 + test/triqs/gf/gf.output | 156 + test/triqs/gf/gf_2times.cpp | 48 + test/triqs/gf/gf_2times_b.cpp | 39 + test/triqs/gf/gf_retw.cpp | 37 + test/triqs/gf/gfv2.cpp | 135 + test/triqs/gf/gfv2.output | 183 + test/triqs/gf/mpi_red.cpp | 57 + test/triqs/gf/ser.cpp | 34 + test/triqs/gf/test_gf_triqs.cpp | 118 + test/triqs/gf/vector_expr_temp.cpp | 20 + test/triqs/gf/wrap_tech.cpp | 23 + test/triqs/gf/wrap_tech.output | 3 + test/triqs/parameters/CMakeLists.txt | 3 + test/triqs/parameters/default.cpp | 55 + test/triqs/parameters/mpi_param.cpp | 40 + test/triqs/parameters/param.cpp | 169 + test/triqs/parameters/param2.cpp.no-built | 131 + test/triqs/parameters/param_array.cpp | 46 + test/triqs/parameters/param_array.output | 7 + test/triqs/parameters/simple_p.cpp | 27 + test/triqs/utility/CMakeLists.txt | 2 + test/triqs/utility/crash_logger.cpp | 64 + test/triqs/utility/function_arg_ret_type.cpp | 42 + test/triqs/utility/iterator_dressing.cpp | 74 + test/triqs/utility/iterator_dressing.output | 7 + test/triqs/utility/iterator_dressing3.cpp | 69 + test/triqs/utility/iterator_dressing3.output | 5 + test/triqs/utility/iterator_dressing_2.cpp | 91 + test/triqs/utility/qmc_time_t_test.cpp | 58 + test/triqs/utility/qmc_time_t_test.output | 24 + test/triqs/utility/tuple_tools.cpp | 101 + test/triqs/utility/view_tools.cpp | 48 + triqs/CMakeLists.txt | 37 + triqs/arrays.hpp | 41 + triqs/arrays/CMakeLists.txt | 2 + triqs/arrays/algorithms.hpp | 73 + triqs/arrays/array.hpp | 207 + triqs/arrays/asserts.hpp | 63 + triqs/arrays/blas_lapack/axpy.hpp | 60 + triqs/arrays/blas_lapack/blas_headers.hpp | 160 + triqs/arrays/blas_lapack/copy.hpp | 77 + triqs/arrays/blas_lapack/dot.hpp | 128 + triqs/arrays/blas_lapack/gemm.hpp | 136 + triqs/arrays/blas_lapack/gemv.hpp | 103 + triqs/arrays/blas_lapack/ger.hpp | 79 + triqs/arrays/blas_lapack/getrf.hpp | 64 + triqs/arrays/blas_lapack/getri.hpp | 71 + triqs/arrays/blas_lapack/qcache.hpp | 154 + triqs/arrays/blas_lapack/scal.hpp | 51 + triqs/arrays/blas_lapack/stev.hpp | 61 + triqs/arrays/blas_lapack/swap.hpp | 57 + triqs/arrays/blas_lapack/tools.hpp | 67 + triqs/arrays/cache.hpp | 118 + .../expression_template/array_algebra.hpp | 85 + .../expression_template/matrix_algebra.hpp | 117 + triqs/arrays/expression_template/tools.hpp | 100 + .../expression_template/vector_algebra.hpp | 91 + triqs/arrays/functional/fold.hpp | 66 + triqs/arrays/functional/map.hpp | 140 + triqs/arrays/h5.hpp | 24 + triqs/arrays/h5/array_proxy.hpp | 130 + triqs/arrays/h5/array_proxy_impl.hpp | 160 + triqs/arrays/h5/array_stack.hpp | 157 + triqs/arrays/h5/common.hpp.old | 230 + triqs/arrays/h5/simple_read_write.hpp | 193 + triqs/arrays/impl/assignment.hpp | 179 + triqs/arrays/impl/common.hpp | 95 + triqs/arrays/impl/exceptions.hpp | 48 + triqs/arrays/impl/flags.hpp | 119 + triqs/arrays/impl/indexmap_storage_pair.hpp | 272 + triqs/arrays/impl/iterator_adapter.hpp | 69 + triqs/arrays/impl/make_const.hpp | 39 + triqs/arrays/impl/tags.hpp | 34 + triqs/arrays/impl/traits.hpp | 85 + triqs/arrays/indexmaps/common.hpp | 89 + triqs/arrays/indexmaps/cuboid/domain.hpp | 197 + triqs/arrays/indexmaps/cuboid/foreach.hpp | 47 + .../arrays/indexmaps/cuboid/group_indices.hpp | 111 + triqs/arrays/indexmaps/cuboid/map.hpp | 216 + triqs/arrays/indexmaps/cuboid/mem_layout.hpp | 130 + triqs/arrays/indexmaps/cuboid/slice.hpp | 115 + .../cuboid/slice_traversal_order.hpp | 75 + triqs/arrays/indexmaps/permutation.hpp | 99 + triqs/arrays/indexmaps/range.hpp | 59 + triqs/arrays/linalg/a_x_ty.hpp | 88 + triqs/arrays/linalg/cross_product.hpp | 44 + triqs/arrays/linalg/det_and_inverse.hpp | 187 + triqs/arrays/linalg/determinant.hpp | 187 + triqs/arrays/linalg/eigenelements.hpp | 176 + triqs/arrays/linalg/inverse.hpp | 187 + triqs/arrays/linalg/mat_vec_mul.hpp | 97 + triqs/arrays/linalg/matmul.hpp | 99 + triqs/arrays/make_immutable_array.hpp | 56 + triqs/arrays/mapped_functions.hpp | 106 + triqs/arrays/matrix.hpp | 204 + triqs/arrays/matrix_stack_view.hpp | 85 + triqs/arrays/matrix_view_proxy.hpp | 147 + triqs/arrays/matrix_view_proxy_DEBUG.hpp | 151 + triqs/arrays/python/array_view_to_python.hpp | 76 + triqs/arrays/python/numpy_extractor.hpp | 172 + triqs/arrays/storages/basic_block.hpp | 68 + triqs/arrays/storages/mem_block.hpp | 156 + triqs/arrays/storages/memcopy.hpp | 52 + triqs/arrays/storages/shared_block.hpp | 149 + triqs/arrays/vector.hpp | 299 + triqs/clef.hpp | 5 + triqs/clef/CMakeLists.txt | 2 + triqs/clef/adapters/math.hpp | 40 + triqs/clef/adapters/vector.hpp | 44 + triqs/clef/clef.hpp | 429 ++ triqs/clef/io.hpp | 87 + triqs/det_manip/CMakeLists.txt | 3 + triqs/det_manip/det_manip.hpp | 819 +++ triqs/gf/CMakeLists.txt | 2 + triqs/gf/block.hpp | 137 + triqs/gf/data_proxies.hpp | 97 + triqs/gf/domains/R.hpp | 40 + triqs/gf/domains/discrete.hpp | 72 + triqs/gf/domains/legendre.hpp | 78 + triqs/gf/domains/matsubara.hpp | 64 + triqs/gf/domains/product.hpp | 36 + triqs/gf/gf.hpp | 405 ++ triqs/gf/gf_expr.hpp | 129 + triqs/gf/imfreq.hpp | 88 + triqs/gf/imtime.hpp | 138 + triqs/gf/legendre.hpp | 77 + triqs/gf/local/CMakeLists.txt | 2 + triqs/gf/local/fourier_base.cpp | 54 + triqs/gf/local/fourier_base.hpp | 44 + triqs/gf/local/fourier_matsubara.cpp | 173 + triqs/gf/local/fourier_matsubara.hpp | 42 + triqs/gf/local/fourier_real.cpp | 126 + triqs/gf/local/fourier_real.hpp | 67 + triqs/gf/local/functions.cpp | 127 + triqs/gf/local/functions.hpp | 57 + triqs/gf/local/legendre_matsubara.cpp | 118 + triqs/gf/local/legendre_matsubara.hpp | 51 + triqs/gf/local/pade.cpp | 68 + triqs/gf/local/pade.hpp | 40 + triqs/gf/local/tail.hpp | 402 ++ triqs/gf/meshes/discrete.hpp | 96 + triqs/gf/meshes/linear.hpp | 181 + triqs/gf/meshes/mesh_tools.hpp | 61 + triqs/gf/meshes/product.hpp | 150 + triqs/gf/refreq.hpp | 95 + triqs/gf/retime.hpp | 89 + triqs/gf/tools.hpp | 105 + triqs/gf/two_real_times.hpp | 154 + triqs/h5.hpp | 29 + triqs/h5/base.hpp | 184 + triqs/h5/group.cpp | 36 + triqs/h5/group.hpp | 108 + triqs/h5/h5_boost_python_exceptions.hpp | 44 + triqs/h5/h5_extractor.hpp | 41 + triqs/h5/make_h5_read_write.hpp | 78 + triqs/h5/scalar.hpp | 56 + triqs/h5/string.hpp | 124 + triqs/h5/vector.hpp | 99 + .../bravais_lattice_and_brillouin_zone.cpp | 93 + .../bravais_lattice_and_brillouin_zone.hpp | 98 + triqs/lattice/concepts.rst | 28 + triqs/lattice/functors.hpp | 90 + triqs/lattice/grid_generator.hpp | 73 + triqs/lattice/tight_binding.cpp | 222 + triqs/lattice/tight_binding.cpp.new | 295 + triqs/lattice/tight_binding.hpp | 91 + triqs/mc_tools/MersenneRNG.cpp | 41 + triqs/mc_tools/MersenneRNG.hpp | 245 + triqs/mc_tools/full_update_mechanism.hpp | 76 + triqs/mc_tools/generator.hpp | 90 + triqs/mc_tools/histograms.hpp | 111 + triqs/mc_tools/impl_tools.hpp | 57 + triqs/mc_tools/mc_basic_step.hpp | 51 + triqs/mc_tools/mc_generic.hpp | 222 + triqs/mc_tools/mc_measure_set.hpp | 193 + triqs/mc_tools/mc_move_set.hpp | 312 + triqs/mc_tools/random_generator.cpp | 81 + triqs/mc_tools/random_generator.hpp | 77 + triqs/mc_tools/v1/mc_measure_set.hpp | 171 + triqs/mc_tools/v1/mc_move_set.hpp | 263 + triqs/parameters.hpp | 25 + triqs/parameters/CMakeLists.txt | 1 + triqs/parameters/defaults.cpp | 58 + triqs/parameters/defaults.hpp | 112 + triqs/parameters/opaque_object_h5.cpp | 64 + triqs/parameters/opaque_object_h5.hpp | 331 + triqs/parameters/parameters.cpp | 106 + triqs/parameters/parameters.hpp | 127 + triqs/python_tools/CMakeLists.txt | 0 triqs/python_tools/array_interface.hpp | 65 + triqs/python_tools/boost_object.hpp | 21 + triqs/python_tools/cython_proxy.hpp | 44 + triqs/python_tools/inserter_in_map.hpp | 45 + triqs/utility/CMakeLists.txt | 2 + triqs/utility/callbacks.cpp | 45 + triqs/utility/callbacks.hpp | 34 + triqs/utility/compiler_details.hpp | 39 + triqs/utility/complex_ops.hpp | 20 + triqs/utility/concept_tools.hpp | 51 + triqs/utility/count_type_occurrence.hpp | 42 + triqs/utility/crash_logger.hpp | 95 + triqs/utility/draft/value_view.hpp | 98 + triqs/utility/dressed_iterator.hpp | 113 + triqs/utility/exceptions.hpp | 49 + triqs/utility/expression_template_tools.hpp | 59 + triqs/utility/factory.hpp | 97 + triqs/utility/first_include.hpp | 43 + triqs/utility/formatted_output.hpp | 54 + triqs/utility/fortran_mangling.hpp | 29 + triqs/utility/function_arg_ret_type.hpp | 67 + triqs/utility/has_traits.hpp | 60 + triqs/utility/legendre.hpp | 108 + triqs/utility/macros.hpp | 40 + triqs/utility/mini_vector.hpp | 147 + triqs/utility/pade_approximants.hpp | 118 + triqs/utility/python/extractor.hpp | 39 + triqs/utility/report_stream.hpp | 77 + triqs/utility/scope_guard.hpp | 51 + triqs/utility/serialization.hpp | 74 + triqs/utility/signal_handler.cpp | 72 + triqs/utility/signal_handler.hpp | 43 + triqs/utility/stack_trace.cpp | 104 + triqs/utility/stack_trace.hpp | 35 + triqs/utility/std_vector_expr_template.hpp | 118 + triqs/utility/time_pt.hpp | 117 + triqs/utility/timer.hpp | 46 + triqs/utility/tuple_tools.hpp | 164 + triqs/utility/typeid_name.hpp | 65 + triqs/utility/view_tools.hpp | 71 + 866 files changed, 73407 insertions(+) create mode 100644 CITATIONS.bib create mode 100644 CMakeLists.txt create mode 100644 COPYING.txt create mode 100644 LICENSE.txt create mode 100644 README.txt create mode 100644 cmake/BuildSphinx.cmake create mode 100644 cmake/CompileBoost.cmake create mode 100644 cmake/Doxyfile.in create mode 100644 cmake/FindBuildF2pyModule.cmake create mode 100644 cmake/FindCompilerCheck.cmake create mode 100644 cmake/FindCythonModuleMacro.cmake create mode 100644 cmake/FindFFTW.cmake create mode 100644 cmake/FindGMP.cmake create mode 100644 cmake/FindGSL.cmake create mode 100644 cmake/FindGit3.cmake create mode 100644 cmake/FindLapack.cmake create mode 100644 cmake/FindMathJax.cmake create mode 100644 cmake/FindPython.cmake create mode 100644 cmake/FindTRIQS.cmake create mode 100644 cmake/FindTestCSimple.cmake create mode 100644 cmake/FindTestScriptHdf.cmake create mode 100644 cmake/FindTriqsMacros.cmake create mode 100644 cmake/FindTriqsTest.cmake.in create mode 100644 cmake/TRIQSConfig.cmake.in create mode 100644 cmake/postinst.in create mode 100644 cmake/prerm.in create mode 100644 cmake/run_test.cmake create mode 100644 cmake/run_test_simple.cmake create mode 100644 cmake/triqs_config.h.in create mode 100644 doc/CMakeLists.txt create mode 100644 doc/_templates/index.html create mode 100644 doc/_templates/layout.html create mode 100644 doc/conf.py.in create mode 100644 doc/contents.rst create mode 100644 doc/faq/faq.rst create mode 100644 doc/faq/relativedirforboost.rst create mode 100644 doc/faq/typeerrorunicode.rst create mode 100644 doc/installation/Ubuntu.rst create mode 100644 doc/installation/changelog.rst create mode 100644 doc/installation/clang.rst create mode 100644 doc/installation/dependencies.rst create mode 100644 doc/installation/get_started.rst create mode 100644 doc/installation/install.rst create mode 100644 doc/installation/install_on_osx_lion.rst create mode 100644 doc/installation/install_options.rst create mode 100644 doc/installation/intel.rst create mode 100644 doc/installation/ipython.rst create mode 100644 doc/installation/linux.rst create mode 100644 doc/installation/python.rst create mode 100644 doc/installation/wien2k_inst.rst create mode 100644 doc/license/collaboration.rst create mode 100644 doc/license/ctqmc1.bib create mode 100644 doc/license/ctqmc2.bib create mode 100644 doc/license/ctqmc3.bib create mode 100644 doc/license/legal/CITATIONS.bib create mode 100644 doc/license/legal/CITATIONS.rst create mode 100644 doc/license/legal/COPYING.txt create mode 100644 doc/license/legal/GPL.rst create mode 100644 doc/license/legal/License.rst create mode 100644 doc/license/legal/License.txt create mode 100644 doc/license/legal/legal.rst create mode 100644 doc/license/wien2k1.bib create mode 100644 doc/license/wien2k2.bib create mode 100644 doc/overview.rst create mode 100644 doc/reference/c++/CMakeLists.txt create mode 100644 doc/reference/c++/CMakeLists.txt.v1 create mode 100644 doc/reference/c++/arrays/CMakeLists.txt create mode 100644 doc/reference/c++/arrays/Design/centralconcept.rst create mode 100644 doc/reference/c++/arrays/Design/concepts.rst create mode 100644 doc/reference/c++/arrays/Design/contents.rst create mode 100644 doc/reference/c++/arrays/Design/cuboid_formula.rst create mode 100644 doc/reference/c++/arrays/Design/slicing.rst create mode 100644 doc/reference/c++/arrays/Design/strategy.rst create mode 100644 doc/reference/c++/arrays/FAQ.rst create mode 100644 doc/reference/c++/arrays/H5.rst create mode 100644 doc/reference/c++/arrays/IO.rst create mode 100644 doc/reference/c++/arrays/Interop_Python.rst create mode 100644 doc/reference/c++/arrays/Iterators.rst create mode 100644 doc/reference/c++/arrays/STL.rst create mode 100644 doc/reference/c++/arrays/algebras.rst create mode 100644 doc/reference/c++/arrays/all.rst create mode 100644 doc/reference/c++/arrays/arrays.rst create mode 100644 doc/reference/c++/arrays/assignment.rst create mode 100644 doc/reference/c++/arrays/basic_classes.rst create mode 100644 doc/reference/c++/arrays/basic_interop.rst create mode 100644 doc/reference/c++/arrays/blas_lapack.rst create mode 100644 doc/reference/c++/arrays/call.rst create mode 100644 doc/reference/c++/arrays/class_diff.rst create mode 100644 doc/reference/c++/arrays/compound_assignment.rst create mode 100644 doc/reference/c++/arrays/compound_ops.rst create mode 100644 doc/reference/c++/arrays/construct.rst create mode 100644 doc/reference/c++/arrays/contents.rst create mode 100644 doc/reference/c++/arrays/contents.rst.1 create mode 100644 doc/reference/c++/arrays/cookbook/basic.rst create mode 100644 doc/reference/c++/arrays/cookbook/contents.rst create mode 100644 doc/reference/c++/arrays/cookbook/intermediate.rst create mode 100644 doc/reference/c++/arrays/debug.rst create mode 100644 doc/reference/c++/arrays/element_acces.rst create mode 100644 doc/reference/c++/arrays/examples_h5/CMakeLists.txt create mode 100644 doc/reference/c++/arrays/examples_h5/h5_rw.cpp create mode 100644 doc/reference/c++/arrays/examples_h5/h5_rw.output create mode 100644 doc/reference/c++/arrays/examples_h5/h5_stack_ex.cpp create mode 100644 doc/reference/c++/arrays/examples_h5/h5_stack_ex.output create mode 100644 doc/reference/c++/arrays/examples_h5/h5_stack_ex_sca.cpp create mode 100644 doc/reference/c++/arrays/examples_h5/h5_stack_ex_sca.output create mode 100644 doc/reference/c++/arrays/expr_arith.rst create mode 100644 doc/reference/c++/arrays/expr_custom.rst create mode 100644 doc/reference/c++/arrays/expr_predef.rst create mode 100644 doc/reference/c++/arrays/expression.rst create mode 100644 doc/reference/c++/arrays/fold.rst create mode 100644 doc/reference/c++/arrays/foreach.rst create mode 100644 doc/reference/c++/arrays/group_indices.rst create mode 100644 doc/reference/c++/arrays/h5_complex.rst create mode 100644 doc/reference/c++/arrays/h5_proxy.rst create mode 100644 doc/reference/c++/arrays/h5_rw.rst create mode 100644 doc/reference/c++/arrays/h5_stack.rst create mode 100644 doc/reference/c++/arrays/introduction.rst create mode 100644 doc/reference/c++/arrays/lazy.rst create mode 100644 doc/reference/c++/arrays/map.rst create mode 100644 doc/reference/c++/arrays/mapped_fnt.rst create mode 100644 doc/reference/c++/arrays/matrix.rst create mode 100644 doc/reference/c++/arrays/memory_management.rst create mode 100644 doc/reference/c++/arrays/move_swap.rst create mode 100644 doc/reference/c++/arrays/options.rst create mode 100644 doc/reference/c++/arrays/python_tools.rst create mode 100644 doc/reference/c++/arrays/shape.rst create mode 100644 doc/reference/c++/arrays/slicing.rst create mode 100644 doc/reference/c++/arrays/vector.rst create mode 100644 doc/reference/c++/arrays/view_or_not_view.rst create mode 100644 doc/reference/c++/arrays/views.rst create mode 100644 doc/reference/c++/arrays_old/CMakeLists.txt.Old create mode 100644 doc/reference/c++/arrays_old/FAQ.rst create mode 100644 doc/reference/c++/arrays_old/H5.rst create mode 100644 doc/reference/c++/arrays_old/IO.rst create mode 100644 doc/reference/c++/arrays_old/Interop_Python.rst create mode 100644 doc/reference/c++/arrays_old/Iterators.rst create mode 100644 doc/reference/c++/arrays_old/STL.rst create mode 100644 doc/reference/c++/arrays_old/algebras.rst create mode 100644 doc/reference/c++/arrays_old/all.rst create mode 100644 doc/reference/c++/arrays_old/arrays.rst create mode 100644 doc/reference/c++/arrays_old/assignment.rst create mode 100644 doc/reference/c++/arrays_old/basic_classes.rst create mode 100644 doc/reference/c++/arrays_old/basic_interop.rst create mode 100644 doc/reference/c++/arrays_old/blas_lapack.rst create mode 100644 doc/reference/c++/arrays_old/centralconcept.rst create mode 100644 doc/reference/c++/arrays_old/compound_ops.rst create mode 100644 doc/reference/c++/arrays_old/contents.rst create mode 100644 doc/reference/c++/arrays_old/debug.rst create mode 100644 doc/reference/c++/arrays_old/design/concepts.rst create mode 100644 doc/reference/c++/arrays_old/design/contents.rst create mode 100644 doc/reference/c++/arrays_old/design/cuboid_formula.rst create mode 100644 doc/reference/c++/arrays_old/design/slicing.rst create mode 100644 doc/reference/c++/arrays_old/design/strategy.rst create mode 100644 doc/reference/c++/arrays_old/expr_arith.rst create mode 100644 doc/reference/c++/arrays_old/expr_custom.rst create mode 100644 doc/reference/c++/arrays_old/expr_predef.rst create mode 100644 doc/reference/c++/arrays_old/expression.rst create mode 100644 doc/reference/c++/arrays_old/foreach.rst create mode 100644 doc/reference/c++/arrays_old/functional.rst create mode 100644 doc/reference/c++/arrays_old/getting_started.rst create mode 100644 doc/reference/c++/arrays_old/h5_complex.rst create mode 100644 doc/reference/c++/arrays_old/h5_proxy.rst create mode 100644 doc/reference/c++/arrays_old/h5_rw.rst create mode 100644 doc/reference/c++/arrays_old/h5_stack.rst create mode 100644 doc/reference/c++/arrays_old/introduction.rst create mode 100644 doc/reference/c++/arrays_old/matrix.rst create mode 100644 doc/reference/c++/arrays_old/memory_management.rst create mode 100644 doc/reference/c++/arrays_old/options.rst create mode 100644 doc/reference/c++/arrays_old/python_tools.rst create mode 100644 doc/reference/c++/arrays_old/shape.rst create mode 100644 doc/reference/c++/arrays_old/slicing.rst create mode 100644 doc/reference/c++/arrays_old/vector.rst create mode 100644 doc/reference/c++/arrays_old/view_or_not_view.rst create mode 100644 doc/reference/c++/clef/CMakeLists.txt create mode 100644 doc/reference/c++/clef/assign.rst create mode 100644 doc/reference/c++/clef/contents.rst create mode 100644 doc/reference/c++/clef/copy_policy.rst create mode 100644 doc/reference/c++/clef/examples/contents.rst create mode 100644 doc/reference/c++/clef/examples/lazy_function.rst create mode 100644 doc/reference/c++/clef/examples/lazy_sum.rst create mode 100644 doc/reference/c++/clef/examples/vector_and_math.rst create mode 100644 doc/reference/c++/clef/expressions.rst create mode 100644 doc/reference/c++/clef/expressions_eval.rst create mode 100644 doc/reference/c++/clef/expressions_form.rst create mode 100644 doc/reference/c++/clef/function.rst create mode 100644 doc/reference/c++/clef/introduction.rst create mode 100644 doc/reference/c++/clef/lazy_call.rst create mode 100644 doc/reference/c++/clef/lazy_function_cls.rst create mode 100644 doc/reference/c++/conf.py.in create mode 100644 doc/reference/c++/contents.rst create mode 100644 doc/reference/c++/det_manip/CMakeLists.txt create mode 100644 doc/reference/c++/det_manip/contents.rst create mode 100644 doc/reference/c++/det_manip/cookbook.rst create mode 100644 doc/reference/c++/det_manip/det_manip.rst create mode 100644 doc/reference/c++/gf/CMakeLists.txt create mode 100644 doc/reference/c++/gf/concepts.rst create mode 100644 doc/reference/c++/gf/contents.rst create mode 100644 doc/reference/c++/gf/cookbook/contents.rst create mode 100644 doc/reference/c++/gf/cookbook/imaginary.rst create mode 100644 doc/reference/c++/gf/cookbook/real.rst create mode 100644 doc/reference/c++/gf/fourier.rst create mode 100644 doc/reference/c++/intro.rst create mode 100644 doc/reference/c++/learn/first_mc.rst create mode 100644 doc/reference/c++/learn/intro.rst create mode 100644 doc/reference/c++/learn/m_vs_beta.png create mode 100644 doc/reference/c++/learn/triqs_library.rst create mode 100644 doc/reference/c++/lectures/basic/C++11.rst create mode 100644 doc/reference/c++/lectures/basic/compile_time_decision.rst create mode 100644 doc/reference/c++/lectures/basic/contents.rst create mode 100644 doc/reference/c++/lectures/basic/functions.rst create mode 100644 doc/reference/c++/lectures/basic/smart_ptr.rst create mode 100644 doc/reference/c++/lectures/contents.rst create mode 100644 doc/reference/c++/lectures/goal.rst create mode 100644 doc/reference/c++/lectures/intro.rst create mode 100644 doc/reference/c++/lectures/patterns/assign_delegation.rst create mode 100644 doc/reference/c++/lectures/patterns/contents.rst create mode 100644 doc/reference/c++/lectures/patterns/h5_read_write.rst create mode 100644 doc/reference/c++/lectures/patterns/lazy_objects.rst create mode 100644 doc/reference/c++/lectures/patterns/python.rst create mode 100644 doc/reference/c++/lectures/patterns/type_erasure.rst create mode 100644 doc/reference/c++/lectures/patterns/view_value.rst create mode 100644 doc/reference/c++/lectures/patterns/writing_an_iterator.rst create mode 100644 doc/reference/c++/lectures/smart_pointers.cpp create mode 100644 doc/reference/c++/mctools/CMakeLists.txt create mode 100644 doc/reference/c++/mctools/intro.rst create mode 100644 doc/reference/c++/mctools/ising.rst create mode 100644 doc/reference/c++/mctools/loop.png create mode 100644 doc/reference/c++/mctools/loop.rst create mode 100644 doc/reference/c++/mctools/overview.rst create mode 100644 doc/reference/c++/mctools/random.rst create mode 100644 doc/reference/c++/mctools/reference.rst create mode 100644 doc/reference/c++/parameters/CMakeLists.txt create mode 100644 doc/reference/c++/parameters/parameters.rst create mode 100644 doc/reference/c++/utility.rst create mode 100644 doc/reference/python/CMakeLists.txt create mode 100644 doc/reference/python/conf.py.in create mode 100644 doc/reference/python/contents.rst create mode 100644 doc/reference/python/data_analysis/contents.rst create mode 100644 doc/reference/python/data_analysis/fit/demo1.py create mode 100644 doc/reference/python/data_analysis/fit/demo1_prepare.py create mode 100644 doc/reference/python/data_analysis/fit/fit.png create mode 100644 doc/reference/python/data_analysis/fit/fit.rst create mode 100644 doc/reference/python/data_analysis/fit/fit_test.py create mode 100644 doc/reference/python/data_analysis/hdf5/CMakeLists.txt create mode 100644 doc/reference/python/data_analysis/hdf5/contents.rst create mode 100644 doc/reference/python/data_analysis/hdf5/protocol1.rst create mode 100644 doc/reference/python/data_analysis/hdf5/protocol2.rst create mode 100644 doc/reference/python/data_analysis/hdf5/ref.rst create mode 100644 doc/reference/python/data_analysis/hdf5/tut_ex1.py create mode 100644 doc/reference/python/data_analysis/hdf5/tut_ex1.rst create mode 100644 doc/reference/python/data_analysis/hdf5/tut_ex2.py create mode 100644 doc/reference/python/data_analysis/hdf5/tut_ex2.rst create mode 100644 doc/reference/python/data_analysis/hdf5/tut_ex2b.py create mode 100644 doc/reference/python/data_analysis/hdf5/tut_ex3.py create mode 100644 doc/reference/python/data_analysis/hdf5/tut_ex3.rst create mode 100644 doc/reference/python/data_analysis/hdf5/tut_ex3b.png create mode 100644 doc/reference/python/data_analysis/hdf5/tut_ex3b.py create mode 100644 doc/reference/python/data_analysis/hdf5/tut_hdf1.png create mode 100644 doc/reference/python/data_analysis/hdf5/tutorial.rst create mode 100644 doc/reference/python/data_analysis/plotting/example.png create mode 100644 doc/reference/python/data_analysis/plotting/example.py create mode 100644 doc/reference/python/data_analysis/plotting/myobject.png create mode 100644 doc/reference/python/data_analysis/plotting/myobject.py create mode 100644 doc/reference/python/data_analysis/plotting/myobject2.png create mode 100644 doc/reference/python/data_analysis/plotting/myobject2.py create mode 100644 doc/reference/python/data_analysis/plotting/plotting.rst create mode 100644 doc/reference/python/data_analysis/provenance.rst create mode 100644 doc/reference/python/green/block.rst create mode 100644 doc/reference/python/green/block/GfImFreq.rst create mode 100644 doc/reference/python/green/block/GfImTime.rst create mode 100644 doc/reference/python/green/block/GfLegendre.rst create mode 100644 doc/reference/python/green/block/GfReFreq.rst create mode 100644 doc/reference/python/green/block/GfReTime.rst create mode 100644 doc/reference/python/green/block/green_imfreq.py create mode 100644 doc/reference/python/green/block/green_imtime.py create mode 100644 doc/reference/python/green/block/green_legendre.py create mode 100644 doc/reference/python/green/block/green_pade.py create mode 100644 doc/reference/python/green/block/green_refreq.py create mode 100644 doc/reference/python/green/block/green_retime.py create mode 100644 doc/reference/python/green/descriptors.rst create mode 100644 doc/reference/python/green/example.py create mode 100644 doc/reference/python/green/fourier.py create mode 100644 doc/reference/python/green/full.rst create mode 100644 doc/reference/python/green/green.rst create mode 100644 doc/reference/python/green/impinbath.py create mode 100644 doc/reference/python/green/legendre.py create mode 100644 doc/reference/python/green/transforms.rst create mode 100644 doc/reference/python/green/tutorial.rst create mode 100644 doc/reference/python/lattice/bravais.rst create mode 100644 doc/reference/python/lattice/dos.rst create mode 100644 doc/reference/python/lattice/ex1.png create mode 100644 doc/reference/python/lattice/ex1.py create mode 100644 doc/reference/python/lattice/ex_Hilbert.py create mode 100644 doc/reference/python/lattice/hilbert.rst create mode 100644 doc/reference/python/lattice/lattice.rst create mode 100644 doc/reference/python/lattice/sumk.rst create mode 100644 doc/reference/python/lattice/tightbinding.rst create mode 100644 doc/reference/python/misc/python-powered-w-200x80.png create mode 100644 doc/themes/agogo/layout.html create mode 100644 doc/themes/agogo/static/agogo.css_t create mode 100644 doc/themes/agogo/static/bgfooter.png create mode 100644 doc/themes/agogo/static/bgtop.png create mode 100644 doc/themes/agogo/theme.conf create mode 100644 doc/tutorials/c++/contents.rst create mode 100644 doc/tutorials/contents.rst create mode 100644 doc/tutorials/python/aim_plot1.png create mode 100644 doc/tutorials/python/introduction.rst create mode 100644 doc/tutorials/python/logo.png create mode 100644 doc/tutorials/python/reading.rst create mode 100644 doc/tutorials/python/tour1.rst create mode 100644 doc/tutorials/python/tour2.rst create mode 100644 doc/tutorials/python/tour3.rst create mode 100644 doc/tutorials/python/tour4.rst create mode 100644 examples/simple/CMakeLists.txt create mode 100644 examples/simple/hdf5.cpp create mode 100644 foreignlibs/autocompile/autocompile.py create mode 100644 foreignlibs/autocompile/autorun.py create mode 100644 foreignlibs/autocompile/pycon.py create mode 100644 foreignlibs/boost/CMakeLists.txt create mode 100644 foreignlibs/boost/__init__.py create mode 100644 foreignlibs/breathe/LICENCE create mode 100644 foreignlibs/breathe/README.rst create mode 100644 foreignlibs/breathe/breathe/__init__.py create mode 100644 foreignlibs/breathe/breathe/finder/__init__.py create mode 100644 foreignlibs/breathe/breathe/finder/doxygen/__init__.py create mode 100644 foreignlibs/breathe/breathe/finder/doxygen/base.py create mode 100644 foreignlibs/breathe/breathe/finder/doxygen/compound.py create mode 100644 foreignlibs/breathe/breathe/finder/doxygen/index.py create mode 100644 foreignlibs/breathe/breathe/parser/__init__.py create mode 100644 foreignlibs/breathe/breathe/parser/doxygen/__init__.py create mode 100644 foreignlibs/breathe/breathe/parser/doxygen/compound.py create mode 100644 foreignlibs/breathe/breathe/parser/doxygen/compoundsuper.py create mode 100644 foreignlibs/breathe/breathe/parser/doxygen/index.py create mode 100644 foreignlibs/breathe/breathe/parser/doxygen/indexsuper.py create mode 100644 foreignlibs/breathe/breathe/renderer/__init__.py create mode 100644 foreignlibs/breathe/breathe/renderer/rst/__init__.py create mode 100644 foreignlibs/breathe/breathe/renderer/rst/doxygen/__init__.py create mode 100644 foreignlibs/breathe/breathe/renderer/rst/doxygen/base.py create mode 100644 foreignlibs/breathe/breathe/renderer/rst/doxygen/compound.py create mode 100644 foreignlibs/breathe/breathe/renderer/rst/doxygen/domain.py create mode 100644 foreignlibs/breathe/breathe/renderer/rst/doxygen/filter.py create mode 100644 foreignlibs/breathe/breathe/renderer/rst/doxygen/index.py create mode 100644 foreignlibs/breathe/breathe/renderer/rst/doxygen/target.py create mode 100644 foreignlibs/doxylink/__init__.py create mode 100644 foreignlibs/doxylink/doxylink.py create mode 100644 foreignlibs/doxylink/parsing.py create mode 100644 foreignlibs/mpl/apigen.py create mode 100644 foreignlibs/mpl/docscrape.py create mode 100644 foreignlibs/mpl/docscrape_sphinx.py create mode 100644 foreignlibs/mpl/inheritance_diagram.py create mode 100644 foreignlibs/mpl/ipython_console_highlighting.py create mode 100644 foreignlibs/mpl/numpydoc.py create mode 100644 foreignlibs/mpl/plot_directive.py create mode 100644 pytriqs/CMakeLists.txt create mode 100644 pytriqs/__init__.py create mode 100644 pytriqs/__init__.py.template create mode 100644 pytriqs/archive/CMakeLists.txt create mode 100644 pytriqs/archive/__init__.py create mode 100644 pytriqs/archive/hdf_archive.py create mode 100644 pytriqs/archive/hdf_archive_basic_layer_h5py.py create mode 100644 pytriqs/archive/hdf_archive_schemes.py create mode 100644 pytriqs/dos/CMakeLists.txt create mode 100644 pytriqs/dos/__init__.py create mode 100644 pytriqs/dos/dos.py create mode 100644 pytriqs/dos/hilbert_transform.py create mode 100644 pytriqs/fit/CMakeLists.txt create mode 100644 pytriqs/fit/__init__.py create mode 100644 pytriqs/fit/fit.py create mode 100644 pytriqs/gf/CMakeLists.txt create mode 100644 pytriqs/gf/__init__.py create mode 100644 pytriqs/gf/local/CMakeLists.txt create mode 100644 pytriqs/gf/local/__init__.py create mode 100644 pytriqs/gf/local/block_gf.py create mode 100644 pytriqs/gf/local/descriptors.py create mode 100644 pytriqs/gf/local/functions.pxd create mode 100644 pytriqs/gf/local/gf.pxd create mode 100644 pytriqs/gf/local/gf.pyx create mode 100644 pytriqs/gf/local/gf_generic.py create mode 100644 pytriqs/gf/local/gf_imfreq.py create mode 100644 pytriqs/gf/local/gf_imtime.py create mode 100644 pytriqs/gf/local/gf_legendre.py create mode 100644 pytriqs/gf/local/gf_refreq.py create mode 100644 pytriqs/gf/local/gf_retime.py create mode 100644 pytriqs/gf/local/gf_two_real_times.py create mode 100644 pytriqs/gf/local/imfreq.pxd create mode 100644 pytriqs/gf/local/imfreq.pyx create mode 100644 pytriqs/gf/local/impl_plot.py create mode 100644 pytriqs/gf/local/imtime.pxd create mode 100644 pytriqs/gf/local/imtime.pyx create mode 100644 pytriqs/gf/local/inverse.py create mode 100644 pytriqs/gf/local/lazy_expressions.py create mode 100644 pytriqs/gf/local/legendre.pxd create mode 100644 pytriqs/gf/local/legendre.pyx create mode 100644 pytriqs/gf/local/matrix_stack.pxd create mode 100644 pytriqs/gf/local/matrix_stack.pyx create mode 100644 pytriqs/gf/local/mesh_imfreq.pyx create mode 100644 pytriqs/gf/local/mesh_imtime.pyx create mode 100644 pytriqs/gf/local/mesh_legendre.pyx create mode 100644 pytriqs/gf/local/mesh_refreq.pyx create mode 100644 pytriqs/gf/local/mesh_retime.pyx create mode 100644 pytriqs/gf/local/mesh_two_real_times.pyx create mode 100644 pytriqs/gf/local/nothing.py create mode 100644 pytriqs/gf/local/refreq.pxd create mode 100644 pytriqs/gf/local/refreq.pyx create mode 100644 pytriqs/gf/local/retime.pxd create mode 100644 pytriqs/gf/local/retime.pyx create mode 100644 pytriqs/gf/local/tail.pxd create mode 100644 pytriqs/gf/local/tail.pyx create mode 100644 pytriqs/gf/local/tools.py create mode 100644 pytriqs/gf/local/two_real_times.pxd create mode 100644 pytriqs/gf/local/two_real_times.pyx create mode 100644 pytriqs/lattice/CMakeLists.txt create mode 100644 pytriqs/lattice/__init__.py create mode 100644 pytriqs/lattice/bz_patch.py create mode 100644 pytriqs/lattice/lattice_tools.pyx create mode 100644 pytriqs/lattice/super_lattice.py create mode 100644 pytriqs/lattice/tight_binding.py create mode 100644 pytriqs/parameters/CMakeLists.txt create mode 100644 pytriqs/parameters/__init__.py create mode 100644 pytriqs/parameters/parameters.pxd create mode 100644 pytriqs/parameters/parameters.pyx create mode 100644 pytriqs/plot/CMakeLists.txt create mode 100644 pytriqs/plot/__init__.py create mode 100644 pytriqs/plot/mpl_interface.py create mode 100644 pytriqs/plot/protocol.py create mode 100644 pytriqs/pxd/CMakeLists.txt create mode 100644 pytriqs/pxd/arrays.pxd create mode 100644 pytriqs/pxd/boost.pxd create mode 100644 pytriqs/pxd/clef.pxd create mode 100644 pytriqs/pxd/dcomplex.pxd create mode 100644 pytriqs/pxd/extractor.pxd create mode 100644 pytriqs/pxd/h5.pxd create mode 100644 pytriqs/pxd/inserter_in_map.pxd create mode 100644 pytriqs/pxd/shared_ptr.pxd create mode 100644 pytriqs/sumk/CMakeLists.txt create mode 100644 pytriqs/sumk/__init__.py create mode 100644 pytriqs/sumk/sumk_discrete.py create mode 100644 pytriqs/sumk/sumk_discrete_from_lattice.py create mode 100644 pytriqs/utility/CMakeLists.txt create mode 100644 pytriqs/utility/__init__.py create mode 100644 pytriqs/utility/dichotomy.py create mode 100644 pytriqs/utility/dist_on_nodes.py create mode 100644 pytriqs/utility/mpi.py create mode 100644 pytriqs/utility/redirect.py create mode 100644 pytriqs/version.py.in create mode 100644 shells/CMakeLists.txt create mode 100755 shells/ipytriqs_shell.bash.in create mode 100755 shells/ipytriqs_shell.nopypath.bash.in create mode 100755 shells/ipytriqs_shell.notebook.bash.in create mode 100755 shells/ipytriqs_shell.notebook.nopypath.bash.in create mode 100755 shells/pytriqs_for_test_shell.bash.in create mode 100755 shells/pytriqs_shell.bash.in create mode 100755 shells/pytriqs_shell.nopypath.bash.in create mode 100644 test/CMakeLists.txt create mode 100644 test/pytriqs/CMakeLists.txt create mode 100644 test/pytriqs/arrays/CMakeLists.txt create mode 100644 test/pytriqs/arrays/__init__.py create mode 100644 test/pytriqs/arrays/array_cython.output create mode 100644 test/pytriqs/arrays/array_cython.py create mode 100644 test/pytriqs/arrays/array_cython.pyx create mode 100644 test/pytriqs/arrays/bug.hpp create mode 100644 test/pytriqs/arrays/bug.pyx create mode 100644 test/pytriqs/arrays/expr.py create mode 100644 test/pytriqs/arrays/expr.pyx create mode 100644 test/pytriqs/arrays/f.hpp create mode 100644 test/pytriqs/base/CMakeLists.txt create mode 100644 test/pytriqs/base/dos.output.h5 create mode 100644 test/pytriqs/base/dos.py create mode 100644 test/pytriqs/base/gf_base_op.output.h5 create mode 100644 test/pytriqs/base/gf_base_op.py create mode 100644 test/pytriqs/base/gf_bcast.py create mode 100644 test/pytriqs/base/gf_init.output.h5 create mode 100644 test/pytriqs/base/gf_init.py create mode 100644 test/pytriqs/base/h5_example.output.h5 create mode 100644 test/pytriqs/base/h5_example.py create mode 100644 test/pytriqs/base/hdf5_io.output.h5 create mode 100644 test/pytriqs/base/hdf5_io.py create mode 100644 test/pytriqs/base/pade.output.h5 create mode 100644 test/pytriqs/base/pade.py create mode 100644 test/pytriqs/base/test_example.output create mode 100644 test/pytriqs/base/test_example.py create mode 100644 test/pytriqs/parameters/test.py create mode 100644 test/speed/CMakeLists.txt create mode 100644 test/speed/apply_on_tuple_s.cpp create mode 100644 test/speed/array1.cpp create mode 100644 test/speed/array2.cpp create mode 100644 test/speed/array_lazy_assign.cpp create mode 100644 test/speed/array_short1.cpp create mode 100644 test/speed/clef1.cpp create mode 100644 test/speed/clef_common.hpp create mode 100644 test/speed/gemv.cpp create mode 100644 test/speed/gf_s.cpp create mode 100644 test/speed/isol_array_foreach_pb.cpp create mode 100644 test/speed/matmul_s.cpp create mode 100644 test/speed/pool.cpp create mode 100644 test/speed/speed_tester.hpp create mode 100644 test/triqs/CMakeLists.txt create mode 100644 test/triqs/arrays/CMakeLists.txt create mode 100644 test/triqs/arrays/a_x_ty.cpp create mode 100644 test/triqs/arrays/a_x_ty.output create mode 100644 test/triqs/arrays/algorithms.cpp create mode 100644 test/triqs/arrays/algorithms.output create mode 100644 test/triqs/arrays/alias_matmul.cpp create mode 100644 test/triqs/arrays/array_algebra.cpp create mode 100644 test/triqs/arrays/array_cache2.cpp create mode 100644 test/triqs/arrays/array_cache2.output create mode 100644 test/triqs/arrays/array_mpi.cpp create mode 100644 test/triqs/arrays/array_mpi.output create mode 100644 test/triqs/arrays/assign_vect_array.cpp create mode 100644 test/triqs/arrays/assign_vect_array.output create mode 100644 test/triqs/arrays/assignment.cpp create mode 100644 test/triqs/arrays/assignment.output create mode 100644 test/triqs/arrays/blas_lapack.cpp create mode 100644 test/triqs/arrays/blas_lapack.output create mode 100644 test/triqs/arrays/bound_check.cpp create mode 100644 test/triqs/arrays/bound_check.output create mode 100644 test/triqs/arrays/bug2.cpp create mode 100644 test/triqs/arrays/bug3.cpp create mode 100644 test/triqs/arrays/common.hpp create mode 100644 test/triqs/arrays/compound_ops.cpp create mode 100644 test/triqs/arrays/compound_ops.output create mode 100644 test/triqs/arrays/create.cpp create mode 100644 test/triqs/arrays/create.output create mode 100644 test/triqs/arrays/cross_construct.cpp create mode 100644 test/triqs/arrays/dot.cpp create mode 100644 test/triqs/arrays/eigenelements.cpp create mode 100644 test/triqs/arrays/eigenelements.output create mode 100644 test/triqs/arrays/ellipsis.cpp create mode 100644 test/triqs/arrays/ellipsis.output create mode 100644 test/triqs/arrays/expr3.cpp.no-built create mode 100644 test/triqs/arrays/expr3.output create mode 100644 test/triqs/arrays/expr_matrix.cpp create mode 100644 test/triqs/arrays/expr_matrix.output create mode 100644 test/triqs/arrays/fill_with_lazy.cpp create mode 100644 test/triqs/arrays/fill_with_lazy.output create mode 100644 test/triqs/arrays/fold_expression.cpp create mode 100644 test/triqs/arrays/fold_expression.output create mode 100644 test/triqs/arrays/group_indices.cpp create mode 100644 test/triqs/arrays/group_indices.output create mode 100644 test/triqs/arrays/h5_proxy.cpp.no-built create mode 100644 test/triqs/arrays/h5_stack.cpp create mode 100644 test/triqs/arrays/h5_string_arrays.cpp create mode 100644 test/triqs/arrays/h5_vector_array.cpp create mode 100644 test/triqs/arrays/hdf5.cpp create mode 100644 test/triqs/arrays/hdf5.output create mode 100644 test/triqs/arrays/init_check.cpp create mode 100644 test/triqs/arrays/init_check.output create mode 100644 test/triqs/arrays/init_list.cpp create mode 100644 test/triqs/arrays/init_list.output create mode 100644 test/triqs/arrays/inverse2.cpp create mode 100644 test/triqs/arrays/inverse2.output create mode 100644 test/triqs/arrays/iterators.cpp create mode 100644 test/triqs/arrays/iterators.output create mode 100644 test/triqs/arrays/lapack_on_view.cpp create mode 100644 test/triqs/arrays/lexico_vector.cpp create mode 100644 test/triqs/arrays/make_immutables.cpp create mode 100644 test/triqs/arrays/make_immutables.output create mode 100644 test/triqs/arrays/map_expression.cpp create mode 100644 test/triqs/arrays/map_expression.output create mode 100644 test/triqs/arrays/mapped_functions.cpp create mode 100644 test/triqs/arrays/mapped_functions.output create mode 100644 test/triqs/arrays/mat_stack.cpp create mode 100644 test/triqs/arrays/mat_stack.output create mode 100644 test/triqs/arrays/mat_vec_mul.cpp create mode 100644 test/triqs/arrays/mat_vec_mul.output create mode 100644 test/triqs/arrays/mat_vec_mul2.cpp create mode 100644 test/triqs/arrays/matmul.cpp create mode 100644 test/triqs/arrays/matmul2.cpp create mode 100644 test/triqs/arrays/matrix_transpose.cpp create mode 100644 test/triqs/arrays/matrix_transpose.output create mode 100644 test/triqs/arrays/move.cpp create mode 100644 test/triqs/arrays/move.output create mode 100644 test/triqs/arrays/negate.cpp create mode 100644 test/triqs/arrays/non_numeric.cpp create mode 100644 test/triqs/arrays/non_numeric.output create mode 100644 test/triqs/arrays/permu.cpp create mode 100644 test/triqs/arrays/permu.output create mode 100644 test/triqs/arrays/printing.cpp create mode 100644 test/triqs/arrays/printing.output create mode 100644 test/triqs/arrays/scalar_assign.cpp create mode 100644 test/triqs/arrays/scalar_assign.output create mode 100644 test/triqs/arrays/serialization.cpp create mode 100644 test/triqs/arrays/serialization.output create mode 100644 test/triqs/arrays/slice_index_order.cpp create mode 120000 test/triqs/arrays/src create mode 100644 test/triqs/arrays/swap.cpp create mode 100644 test/triqs/arrays/swap.output create mode 100644 test/triqs/arrays/tridiag.cpp create mode 100644 test/triqs/arrays/vector_brack.cpp create mode 100644 test/triqs/arrays/vector_brack.output create mode 100644 test/triqs/arrays/vector_cmul.cpp create mode 100644 test/triqs/arrays/vector_cmul.output create mode 100644 test/triqs/arrays/vector_copy.cpp create mode 100644 test/triqs/arrays/vector_copy.output create mode 100644 test/triqs/arrays/views.cpp create mode 100644 test/triqs/arrays/views.output create mode 100644 test/triqs/arrays/views3.cpp create mode 100644 test/triqs/arrays/views3.output create mode 100644 test/triqs/arrays/withSTL.cpp create mode 100644 test/triqs/arrays/withSTL.output create mode 100644 test/triqs/clef/CMakeLists.txt create mode 100644 test/triqs/clef/F7.cpp create mode 100644 test/triqs/clef/F7.output create mode 100644 test/triqs/clef/array_as_value.output create mode 100644 test/triqs/clef/array_as_value_long.output create mode 100644 test/triqs/clef/chain_call.cpp create mode 100644 test/triqs/clef/chain_call.output create mode 100644 test/triqs/clef/common.hpp create mode 100644 test/triqs/clef/function.cpp create mode 100644 test/triqs/clef/function.output create mode 100644 test/triqs/clef/general.cpp create mode 100644 test/triqs/clef/general.output create mode 100644 test/triqs/clef/lazy.cpp create mode 100644 test/triqs/clef/lazy.output create mode 100644 test/triqs/clef/lazy_function.cpp create mode 100644 test/triqs/clef/lazy_function.output create mode 100644 test/triqs/clef/math_functions.cpp create mode 100644 test/triqs/clef/math_functions.output create mode 100644 test/triqs/clef/test1.cpp create mode 100644 test/triqs/clef_examples/CMakeLists.txt create mode 100644 test/triqs/clef_examples/lazyfunction.cpp create mode 100644 test/triqs/clef_examples/lazyfunction2.output create mode 100644 test/triqs/clef_examples/simple.cpp create mode 100644 test/triqs/clef_examples/simple2.output create mode 100644 test/triqs/clef_examples/sum_functional.cpp create mode 100644 test/triqs/clef_examples/sum_functional2.output create mode 100644 test/triqs/clef_examples/vector_and_math.cpp create mode 100644 test/triqs/clef_examples/vector_and_math2.output create mode 100644 test/triqs/det_manip/CMakeLists.txt create mode 100644 test/triqs/det_manip/det_manip1.cpp create mode 100644 test/triqs/det_manip/det_manip2.cpp create mode 100644 test/triqs/det_manip/det_manipc1.cpp create mode 100644 test/triqs/det_manip/det_manipc2.cpp create mode 100644 test/triqs/gf/CMakeLists.txt create mode 100644 test/triqs/gf/block.cpp create mode 100644 test/triqs/gf/block.output create mode 100644 test/triqs/gf/fourier1.cpp create mode 100644 test/triqs/gf/gf.output create mode 100644 test/triqs/gf/gf_2times.cpp create mode 100644 test/triqs/gf/gf_2times_b.cpp create mode 100644 test/triqs/gf/gf_retw.cpp create mode 100644 test/triqs/gf/gfv2.cpp create mode 100644 test/triqs/gf/gfv2.output create mode 100644 test/triqs/gf/mpi_red.cpp create mode 100644 test/triqs/gf/ser.cpp create mode 100644 test/triqs/gf/test_gf_triqs.cpp create mode 100644 test/triqs/gf/vector_expr_temp.cpp create mode 100644 test/triqs/gf/wrap_tech.cpp create mode 100644 test/triqs/gf/wrap_tech.output create mode 100644 test/triqs/parameters/CMakeLists.txt create mode 100644 test/triqs/parameters/default.cpp create mode 100644 test/triqs/parameters/mpi_param.cpp create mode 100644 test/triqs/parameters/param.cpp create mode 100644 test/triqs/parameters/param2.cpp.no-built create mode 100644 test/triqs/parameters/param_array.cpp create mode 100644 test/triqs/parameters/param_array.output create mode 100644 test/triqs/parameters/simple_p.cpp create mode 100644 test/triqs/utility/CMakeLists.txt create mode 100644 test/triqs/utility/crash_logger.cpp create mode 100644 test/triqs/utility/function_arg_ret_type.cpp create mode 100644 test/triqs/utility/iterator_dressing.cpp create mode 100644 test/triqs/utility/iterator_dressing.output create mode 100644 test/triqs/utility/iterator_dressing3.cpp create mode 100644 test/triqs/utility/iterator_dressing3.output create mode 100644 test/triqs/utility/iterator_dressing_2.cpp create mode 100644 test/triqs/utility/qmc_time_t_test.cpp create mode 100644 test/triqs/utility/qmc_time_t_test.output create mode 100644 test/triqs/utility/tuple_tools.cpp create mode 100644 test/triqs/utility/view_tools.cpp create mode 100644 triqs/CMakeLists.txt create mode 100644 triqs/arrays.hpp create mode 100644 triqs/arrays/CMakeLists.txt create mode 100644 triqs/arrays/algorithms.hpp create mode 100644 triqs/arrays/array.hpp create mode 100644 triqs/arrays/asserts.hpp create mode 100644 triqs/arrays/blas_lapack/axpy.hpp create mode 100644 triqs/arrays/blas_lapack/blas_headers.hpp create mode 100644 triqs/arrays/blas_lapack/copy.hpp create mode 100644 triqs/arrays/blas_lapack/dot.hpp create mode 100644 triqs/arrays/blas_lapack/gemm.hpp create mode 100644 triqs/arrays/blas_lapack/gemv.hpp create mode 100644 triqs/arrays/blas_lapack/ger.hpp create mode 100644 triqs/arrays/blas_lapack/getrf.hpp create mode 100644 triqs/arrays/blas_lapack/getri.hpp create mode 100644 triqs/arrays/blas_lapack/qcache.hpp create mode 100644 triqs/arrays/blas_lapack/scal.hpp create mode 100644 triqs/arrays/blas_lapack/stev.hpp create mode 100644 triqs/arrays/blas_lapack/swap.hpp create mode 100644 triqs/arrays/blas_lapack/tools.hpp create mode 100644 triqs/arrays/cache.hpp create mode 100644 triqs/arrays/expression_template/array_algebra.hpp create mode 100644 triqs/arrays/expression_template/matrix_algebra.hpp create mode 100644 triqs/arrays/expression_template/tools.hpp create mode 100644 triqs/arrays/expression_template/vector_algebra.hpp create mode 100644 triqs/arrays/functional/fold.hpp create mode 100644 triqs/arrays/functional/map.hpp create mode 100644 triqs/arrays/h5.hpp create mode 100644 triqs/arrays/h5/array_proxy.hpp create mode 100644 triqs/arrays/h5/array_proxy_impl.hpp create mode 100644 triqs/arrays/h5/array_stack.hpp create mode 100644 triqs/arrays/h5/common.hpp.old create mode 100644 triqs/arrays/h5/simple_read_write.hpp create mode 100644 triqs/arrays/impl/assignment.hpp create mode 100644 triqs/arrays/impl/common.hpp create mode 100644 triqs/arrays/impl/exceptions.hpp create mode 100644 triqs/arrays/impl/flags.hpp create mode 100644 triqs/arrays/impl/indexmap_storage_pair.hpp create mode 100644 triqs/arrays/impl/iterator_adapter.hpp create mode 100644 triqs/arrays/impl/make_const.hpp create mode 100644 triqs/arrays/impl/tags.hpp create mode 100644 triqs/arrays/impl/traits.hpp create mode 100644 triqs/arrays/indexmaps/common.hpp create mode 100644 triqs/arrays/indexmaps/cuboid/domain.hpp create mode 100644 triqs/arrays/indexmaps/cuboid/foreach.hpp create mode 100644 triqs/arrays/indexmaps/cuboid/group_indices.hpp create mode 100644 triqs/arrays/indexmaps/cuboid/map.hpp create mode 100644 triqs/arrays/indexmaps/cuboid/mem_layout.hpp create mode 100644 triqs/arrays/indexmaps/cuboid/slice.hpp create mode 100644 triqs/arrays/indexmaps/cuboid/slice_traversal_order.hpp create mode 100644 triqs/arrays/indexmaps/permutation.hpp create mode 100644 triqs/arrays/indexmaps/range.hpp create mode 100644 triqs/arrays/linalg/a_x_ty.hpp create mode 100644 triqs/arrays/linalg/cross_product.hpp create mode 100644 triqs/arrays/linalg/det_and_inverse.hpp create mode 100644 triqs/arrays/linalg/determinant.hpp create mode 100644 triqs/arrays/linalg/eigenelements.hpp create mode 100644 triqs/arrays/linalg/inverse.hpp create mode 100644 triqs/arrays/linalg/mat_vec_mul.hpp create mode 100644 triqs/arrays/linalg/matmul.hpp create mode 100644 triqs/arrays/make_immutable_array.hpp create mode 100644 triqs/arrays/mapped_functions.hpp create mode 100644 triqs/arrays/matrix.hpp create mode 100644 triqs/arrays/matrix_stack_view.hpp create mode 100644 triqs/arrays/matrix_view_proxy.hpp create mode 100644 triqs/arrays/matrix_view_proxy_DEBUG.hpp create mode 100644 triqs/arrays/python/array_view_to_python.hpp create mode 100644 triqs/arrays/python/numpy_extractor.hpp create mode 100644 triqs/arrays/storages/basic_block.hpp create mode 100644 triqs/arrays/storages/mem_block.hpp create mode 100644 triqs/arrays/storages/memcopy.hpp create mode 100644 triqs/arrays/storages/shared_block.hpp create mode 100644 triqs/arrays/vector.hpp create mode 100644 triqs/clef.hpp create mode 100644 triqs/clef/CMakeLists.txt create mode 100644 triqs/clef/adapters/math.hpp create mode 100644 triqs/clef/adapters/vector.hpp create mode 100644 triqs/clef/clef.hpp create mode 100644 triqs/clef/io.hpp create mode 100644 triqs/det_manip/CMakeLists.txt create mode 100644 triqs/det_manip/det_manip.hpp create mode 100644 triqs/gf/CMakeLists.txt create mode 100644 triqs/gf/block.hpp create mode 100644 triqs/gf/data_proxies.hpp create mode 100644 triqs/gf/domains/R.hpp create mode 100644 triqs/gf/domains/discrete.hpp create mode 100644 triqs/gf/domains/legendre.hpp create mode 100644 triqs/gf/domains/matsubara.hpp create mode 100644 triqs/gf/domains/product.hpp create mode 100644 triqs/gf/gf.hpp create mode 100644 triqs/gf/gf_expr.hpp create mode 100644 triqs/gf/imfreq.hpp create mode 100644 triqs/gf/imtime.hpp create mode 100644 triqs/gf/legendre.hpp create mode 100644 triqs/gf/local/CMakeLists.txt create mode 100644 triqs/gf/local/fourier_base.cpp create mode 100644 triqs/gf/local/fourier_base.hpp create mode 100644 triqs/gf/local/fourier_matsubara.cpp create mode 100644 triqs/gf/local/fourier_matsubara.hpp create mode 100644 triqs/gf/local/fourier_real.cpp create mode 100644 triqs/gf/local/fourier_real.hpp create mode 100644 triqs/gf/local/functions.cpp create mode 100644 triqs/gf/local/functions.hpp create mode 100644 triqs/gf/local/legendre_matsubara.cpp create mode 100644 triqs/gf/local/legendre_matsubara.hpp create mode 100644 triqs/gf/local/pade.cpp create mode 100644 triqs/gf/local/pade.hpp create mode 100644 triqs/gf/local/tail.hpp create mode 100644 triqs/gf/meshes/discrete.hpp create mode 100644 triqs/gf/meshes/linear.hpp create mode 100644 triqs/gf/meshes/mesh_tools.hpp create mode 100644 triqs/gf/meshes/product.hpp create mode 100644 triqs/gf/refreq.hpp create mode 100644 triqs/gf/retime.hpp create mode 100644 triqs/gf/tools.hpp create mode 100644 triqs/gf/two_real_times.hpp create mode 100644 triqs/h5.hpp create mode 100644 triqs/h5/base.hpp create mode 100644 triqs/h5/group.cpp create mode 100644 triqs/h5/group.hpp create mode 100644 triqs/h5/h5_boost_python_exceptions.hpp create mode 100644 triqs/h5/h5_extractor.hpp create mode 100644 triqs/h5/make_h5_read_write.hpp create mode 100644 triqs/h5/scalar.hpp create mode 100644 triqs/h5/string.hpp create mode 100644 triqs/h5/vector.hpp create mode 100644 triqs/lattice/bravais_lattice_and_brillouin_zone.cpp create mode 100644 triqs/lattice/bravais_lattice_and_brillouin_zone.hpp create mode 100644 triqs/lattice/concepts.rst create mode 100644 triqs/lattice/functors.hpp create mode 100644 triqs/lattice/grid_generator.hpp create mode 100644 triqs/lattice/tight_binding.cpp create mode 100644 triqs/lattice/tight_binding.cpp.new create mode 100644 triqs/lattice/tight_binding.hpp create mode 100644 triqs/mc_tools/MersenneRNG.cpp create mode 100644 triqs/mc_tools/MersenneRNG.hpp create mode 100644 triqs/mc_tools/full_update_mechanism.hpp create mode 100644 triqs/mc_tools/generator.hpp create mode 100644 triqs/mc_tools/histograms.hpp create mode 100644 triqs/mc_tools/impl_tools.hpp create mode 100644 triqs/mc_tools/mc_basic_step.hpp create mode 100644 triqs/mc_tools/mc_generic.hpp create mode 100644 triqs/mc_tools/mc_measure_set.hpp create mode 100644 triqs/mc_tools/mc_move_set.hpp create mode 100644 triqs/mc_tools/random_generator.cpp create mode 100644 triqs/mc_tools/random_generator.hpp create mode 100644 triqs/mc_tools/v1/mc_measure_set.hpp create mode 100644 triqs/mc_tools/v1/mc_move_set.hpp create mode 100644 triqs/parameters.hpp create mode 100644 triqs/parameters/CMakeLists.txt create mode 100644 triqs/parameters/defaults.cpp create mode 100644 triqs/parameters/defaults.hpp create mode 100644 triqs/parameters/opaque_object_h5.cpp create mode 100644 triqs/parameters/opaque_object_h5.hpp create mode 100644 triqs/parameters/parameters.cpp create mode 100644 triqs/parameters/parameters.hpp create mode 100644 triqs/python_tools/CMakeLists.txt create mode 100644 triqs/python_tools/array_interface.hpp create mode 100644 triqs/python_tools/boost_object.hpp create mode 100644 triqs/python_tools/cython_proxy.hpp create mode 100644 triqs/python_tools/inserter_in_map.hpp create mode 100644 triqs/utility/CMakeLists.txt create mode 100644 triqs/utility/callbacks.cpp create mode 100644 triqs/utility/callbacks.hpp create mode 100644 triqs/utility/compiler_details.hpp create mode 100644 triqs/utility/complex_ops.hpp create mode 100644 triqs/utility/concept_tools.hpp create mode 100644 triqs/utility/count_type_occurrence.hpp create mode 100644 triqs/utility/crash_logger.hpp create mode 100644 triqs/utility/draft/value_view.hpp create mode 100644 triqs/utility/dressed_iterator.hpp create mode 100644 triqs/utility/exceptions.hpp create mode 100644 triqs/utility/expression_template_tools.hpp create mode 100644 triqs/utility/factory.hpp create mode 100644 triqs/utility/first_include.hpp create mode 100644 triqs/utility/formatted_output.hpp create mode 100644 triqs/utility/fortran_mangling.hpp create mode 100644 triqs/utility/function_arg_ret_type.hpp create mode 100644 triqs/utility/has_traits.hpp create mode 100644 triqs/utility/legendre.hpp create mode 100644 triqs/utility/macros.hpp create mode 100644 triqs/utility/mini_vector.hpp create mode 100644 triqs/utility/pade_approximants.hpp create mode 100644 triqs/utility/python/extractor.hpp create mode 100644 triqs/utility/report_stream.hpp create mode 100644 triqs/utility/scope_guard.hpp create mode 100644 triqs/utility/serialization.hpp create mode 100644 triqs/utility/signal_handler.cpp create mode 100644 triqs/utility/signal_handler.hpp create mode 100644 triqs/utility/stack_trace.cpp create mode 100644 triqs/utility/stack_trace.hpp create mode 100644 triqs/utility/std_vector_expr_template.hpp create mode 100644 triqs/utility/time_pt.hpp create mode 100644 triqs/utility/timer.hpp create mode 100644 triqs/utility/tuple_tools.hpp create mode 100644 triqs/utility/typeid_name.hpp create mode 100644 triqs/utility/view_tools.hpp diff --git a/CITATIONS.bib b/CITATIONS.bib new file mode 100644 index 00000000..4fcdd15f --- /dev/null +++ b/CITATIONS.bib @@ -0,0 +1,99 @@ + +TRIQS is a part of our scientific work and we would appreciate if projects +using it will include a citation to TRIQS. In order to help you, we provide this +BibTeX digest of the papers relevant for the various TRIQS modules. + +-------------------------------------------------------------------------------- +THE TRIQS PROJECT BASIC COMPONENTS (Green's functions, HDF archives, ...) +-------------------------------------------------------------------------------- + +A companion paper will be published soon +@Misc{triqs_project, + author = {Ferrero, Michel and Parcollet, Olivier}, + title = {{TRIQS}: a {T}oolbox for {R}esearch in {I}nteracting {Q}uantum {S}ystems}, + url = {http://ipht.cea.fr/triqs} +} + + +-------------------------------------------------------------------------------- +EXTENSION MODULES: Hybridization Quantum Monte Carlo +-------------------------------------------------------------------------------- + +@Article{triqs_ctqmc_solver_boehnke, + volume = {84}, + month = {Aug}, + numpages = {13}, + author = {Boehnke, Lewin and Hafermann, Hartmut and Ferrero, Michel and Lechermann, Frank and Parcollet, Olivier}, + year = {2011}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.84.075145}, + doi = {10.1103/PhysRevB.84.075145}, + issue = {7}, + title = {Orthogonal polynomial representation of imaginary-time Green's functions}, + publisher = {American Physical Society}, + pages = {075145}, + journal = {Phys. Rev. B} +} + +@Article{triqs_ctqmc_solver_werner1, + volume = {97}, + month = {Aug}, + numpages = {4}, + author = {Werner, Philipp and Comanac, Armin and de' Medici, Luca and Troyer, Matthias and Millis, Andrew J.}, + year = {2006}, + url = {http://link.aps.org/doi/10.1103/PhysRevLett.97.076405}, + doi = {10.1103/PhysRevLett.97.076405}, + issue = {7}, + title = {Continuous-Time Solver for Quantum Impurity Models}, + publisher = {American Physical Society}, + pages = {076405}, + journal = {Phys. Rev. Lett.} +} + +@Article{triqs_ctqmc_solver_werner2, + volume = {74}, + month = {Oct}, + numpages = {13}, + author = {Werner, Philipp and Millis, Andrew J.}, + year = {2006}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.74.155107}, + doi = {10.1103/PhysRevB.74.155107}, + issue = {15}, + title = {Hybridization expansion impurity solver: General formulation and application to Kondo lattice and two-orbital models}, + publisher = {American Physical Society}, + pages = {155107}, + journal = {Phys. Rev. B} +} + +-------------------------------------------------------------------------------- +EXTENSION MODULES: Wien2K interface +-------------------------------------------------------------------------------- + +@Article{triqs_wien2k_interface, + volume = {80}, + month = {Aug}, + numpages = {15}, + author = {Aichhorn, Markus and Pourovskii, Leonid and Vildosola, Veronica and Ferrero, Michel and Parcollet, Olivier and Miyake, Takashi and Georges, Antoine and Biermann, Silke}, + year = {2009}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.80.085101}, + doi = {10.1103/PhysRevB.80.085101}, + issue = {8}, + title = {Dynamical mean-field theory within an augmented plane-wave framework: Assessing electronic correlations in the iron pnictide LaFeAsO}, + publisher = {American Physical Society}, + pages = {085101}, + journal = {Phys. Rev. B} +} + +@Article{triqs_wien2k_full_charge_SC, + doi = {10.1103/PhysRevB.84.054529}, + month = {Aug}, + issue = {5}, + author = {Aichhorn, Markus and Pourovskii, Leonid and Georges, Antoine}, + year = {2011}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.84.054529}, + publisher = {American Physical Society}, + title = {Importance of electronic correlations for structural and magnetic properties of the iron pnictide superconductor LaFeAsO}, + pages = {054529}, + journal = {Phys. Rev. B}, + volume = {84}, + numpages = {7} +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..66ba1449 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,474 @@ +################################################################################### +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2013 by O. Parcollet, M. Ferrero, A. Antipov +# +# 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 . +# +################################################################################### + +#version number of the library +set (TRIQS_VERSION "1.0.0") + +# Path for local cmake modules +list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + +# Where is triqs source +set(TRIQS_SOURCE_DIR "${CMAKE_SOURCE_DIR}") + +# a default version : by default installation in the build dir : +# useful for developer : everything is at the same place, easy to clean. +# pass -DCMAKE_INSTALL_PREFIX to overrule +set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/INSTALL_DIR" CACHE PATH "TRIQS install prefix" ) +message(STATUS "Installation directory is ${CMAKE_INSTALL_PREFIX}") + +# Forbid compilation in the source dir... to force good practice +# and because I have not checked it (copy of various file before compilation may mess it up) +if (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) + message(FATAL_ERROR "I am sorry, the on-site compilation is disabled at the moment. Use another directory") +endif (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) + +# nasty policy for escaping in string.... +cmake_policy(SET CMP0011 OLD) +cmake_policy(SET CMP0005 NEW) +cmake_policy(SET CMP0003 NEW) #cmake --help-policy CMP0003 + +cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR) +project (AllPrograms C CXX Fortran) + +## C & C++ Headers +include(CheckIncludeFile) +include(CheckIncludeFileCXX) + +# Make sure the rpath is set fine after installation +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +# First check the C++ compiler +find_package(CompilerCheck) + +# Include TRIQS cmake macros +find_package(TriqsMacros) + +# Static built ? TO BE RECHECKED ... +option(BUILD_SHARED_LIBS "Build shared libraries" ON) +string(COMPARE EQUAL ${BUILD_SHARED_LIBS} "OFF" TRIQS_BUILD_STATIC) +if (TRIQS_BUILD_STATIC) + message(STATUS "STATIC Built ") +else (TRIQS_BUILD_STATIC) + message(STATUS "DYNAMIC Built ") +endif (TRIQS_BUILD_STATIC) + +# RPATH setting (before compiling boost) +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib") +else() + set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") + set(CMAKE_SKIP_BUILD_RPATH FALSE) + set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +endif() + +# ################################# +# Python support +# ################################# +# TEST AND DEBUG THE OFF OPTION +# option is set first time, once for all. No change. +#option(PythonSupport "Build with Python support (i.e. pytriqs, etc..) : OFF NOT TESTED ?" ON) +set(PythonSupport NOT WithoutPython) +if (PythonSupport) + + set(TRIQS_WITH_PYTHON_SUPPORT 1) # for the triqs_config.h file configuration + + find_package(Python REQUIRED) + if (NOT PYTHONLIBS_FOUND) + message (FATAL_ERROR "Can not find python. You can use -DWithoutPython to build a pure C++ version.") + endif() + + set (TRIQS_LIBRARY_PYTHON ${PYTHON_LIBRARY} ${PYTHON_EXTRA_LIBS}) + set (TRIQS_INCLUDE_PYTHON ${PYTHON_INCLUDE_DIRS} ${PYTHON_NUMPY_INCLUDE_DIR}) + + include_directories(SYSTEM ${TRIQS_INCLUDE_PYTHON} ) + #include_directories(SYSTEM ${PYTHON_NUMPY_INCLUDE_DIR} ${PYTHON_INCLUDE_DIRS}) + link_libraries( ${TRIQS_LIBRARY_PYTHON}) + + message (STATUS "Numpy include in ${PYTHON_NUMPY_INCLUDE_DIR}") + + # The C API of numpy has changed with 1.7.0, the macro is a version switch in a few files of the libs. + if (PYTHON_NUMPY_VERSION VERSION_LESS "1.7.0") + set(TRIQS_NUMPY_VERSION_LT_17 1) + endif() + + # Installation : Final destination of the python modules + string(REGEX REPLACE ".*/lib" "lib" TRIQS_PYTHON_LIB_DEST_ROOT ${PYTHON_SITE_PKG} ) + set( TRIQS_PYTHON_LIB_DEST ${TRIQS_PYTHON_LIB_DEST_ROOT}/pytriqs ) + message(STATUS "Python modules will be installed in ${CMAKE_INSTALL_PREFIX}/${TRIQS_PYTHON_LIB_DEST}") + + # build pytriqs scripts + add_subdirectory(shells bin) + +endif (PythonSupport) + +# ################################# +# MPI +# ################################# + +message( STATUS "-------- MPI detection -------------") +find_package(MPI) +if (NOT MPI_CXX_FOUND) + message(FATAL_ERROR "TRIQS requires MPI") +endif() +set(TRIQS_CXX_DEFINITIONS ${TRIQS_CXX_DEFINITIONS} ${MPI_CXX_COMPILE_FLAGS} ${MPI_C_COMPILE_FLAGS}) +#add_definitions( ${MPI_CXX_COMPILE_FLAGS} ${MPI_C_COMPILE_FLAGS}) +include_directories(SYSTEM ${MPI_CXX_INCLUDE_PATH}) +link_libraries( ${MPI_CXX_LIBRARIES}) +set(TRIQS_LIBRARY_MPI ${MPI_CXX_LIBRARIES}) +set(TRIQS_INCLUDE_MPI ${MPI_CXX_INCLUDE_PATH}) +set(TRIQS_COMPILE_FLAGS_MPI ${MPI_CXX_COMPILE_FLAGS} ${MPI_C_COMPILE_FLAGS}) +message(STATUS "MPI CXX compiler : ${MPI_CXX_COMPILER}") +message(STATUS "MPI_COMPILE_FLAGS : ${TRIQS_COMPILE_FLAGS_MPI} ") +message(STATUS "MPI_CXX_INCLUDE_PATH : ${MPI_CXX_INCLUDE_PATH}") + +# ################################# +# Boost detection +# ################################# + +message( STATUS "-------- Boost detection -------------") +# Check user input for BOOST_SOURCE_DIR +if(BOOST_SOURCE_DIR) + if(NOT IS_ABSOLUTE ${BOOST_SOURCE_DIR}) + Message(FATAL_ERROR "You must specify an absolute path for BOOST_SOURCE_DIR.") + endif(NOT IS_ABSOLUTE ${BOOST_SOURCE_DIR}) + STRING(REGEX MATCH "~\\/" TILDE "${BOOST_SOURCE_DIR}") + if(TILDE) + Message(FATAL_ERROR "You should not use the tilde symbol ~. Please write the full absolute path for BOOST_SOURCE_DIR.") + endif(TILDE) + + # compile boost if necessary + set(ALPS_BOOST_LIBRARY_NAME "boost_for_triqs" ) + set(ALPS_HAVE_MPI 1) + set(ALPS_HAVE_BOOST_MPI 1) + set(BUILD_BOOST_MPI TRUE) + set(BUILD_BOOST_PYTHON TRUE) + add_subdirectory(foreignlibs/boost) + include_directories(SYSTEM ${BOOST_INCLUDE_DIR}) + +else(BOOST_SOURCE_DIR) + + if (NOT Boost_ROOT_DIR_found) + set( Boost_ROOT_DIR ${BOOST_ROOT_DIR}) + endif (NOT Boost_ROOT_DIR_found) + + # if static build, request static lib + if(TRIQS_BUILD_STATIC) + set(Boost_USE_STATIC_LIBS ON) + else() + set(Boost_USE_STATIC_LIBS OFF) + endif() + # icc requires a higher version + if(CMAKE_COMPILER_IS_ICC) + set(BOOST_VERSION 1.53) + else() + set(BOOST_VERSION 1.46) + endif() + if (PythonSupport) + find_package(Boost ${BOOST_VERSION} REQUIRED COMPONENTS mpi python serialization ) #filesystem ) + Else() + find_package(Boost ${BOOST_VERSION} REQUIRED COMPONENTS mpi serialization ) #filesystem ) + endif() + if (NOT Boost_FOUND) + message(FATAL_ERROR "Boost not found") + endif() + message(STATUS "BOOST has been detected") + include_directories(${Boost_INCLUDE_DIRS}) + #include_directories(${BOOST_INSTALL_ROOT_DIR}/include) + set(BOOST_LIBRARY ${Boost_LIBRARIES}) #${BOOST_PYTHON_LIB} ${BOOST_SERIALIZATION_LIB} ${BOOST_FILESYSTEM_LIB} ${BOOST_MPI_LIB}) + set(BOOST_INCLUDE_DIR ${Boost_INCLUDE_DIRS}) +endif(BOOST_SOURCE_DIR) + +message(STATUS "Boost include dir : ${BOOST_INCLUDE_DIR}") +message(STATUS "Boost libraries : ${BOOST_LIBRARY}") + +#------------------------ +# copy boost into pytriqs/boost +#------------------------ +if (PythonSupport) + if(NOT BOOST_SOURCE_DIR) + if(NOT BOOST_MODULE_DIR) + EXEC_PYTHON_SCRIPT ("import boost; print boost.__path__[0]" BOOST_MODULE_DIR) + endif(NOT BOOST_MODULE_DIR) + # first create the dir, since pytriqs will be configured later + execute_process(COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/pytriqs/ ) + execute_process(COMMAND ln -fs ${BOOST_MODULE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/pytriqs/) + install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pytriqs/boost DESTINATION ${TRIQS_PYTHON_LIB_DEST}) + endif(NOT BOOST_SOURCE_DIR) +endif (PythonSupport) + +# on 64 bit machines +if (CMAKE_SIZEOF_VOID_P EQUAL 8) # for 64 bits machines + message( STATUS "64 bit machine : Adding -fpic ") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpic" ) + set(TRIQS_CXX_DEFINITIONS ${TRIQS_CXX_DEFINITIONS} -fpic) +endif (CMAKE_SIZEOF_VOID_P EQUAL 8) + +# ################################# +# Lapack +# ################################# +message( STATUS "-------- Lapack detection -------------") +#option(LAPACK_64_BIT "Use 64-bit version of LAPACK" OFF) +#set (BIND_FORTRAN_INTEGER_8 ${LAPACK_64_BIT}) +if (NOT LAPACK_FOUND) + find_package(Lapack) +endif (NOT LAPACK_FOUND) +if (REQUIRE_PTHREAD) + set(LAPACK_LIBRARY "${LAPACK_LIBRARY};${PTHREAD_LIBRARY}") + set(LAPACK_LIBRARIES "${LAPACK_LIBRARIES};${PTHREAD_LIBRARY}") +endif (REQUIRE_PTHREAD) + +set(LAPACK_LIBS ${LAPACK_LIBRARY} ${BLAS_LIBRARY} ${LAPACK_LINKER_FLAGS} CACHE STRING "Flags to link Lapack and Blas") + +set(TRIQS_LIBRARY_LAPACK ${LAPACK_LIBS}) +if(MAC_VECLIB) + set(TRIQS_LIBRARY_LAPACK "-framework vecLib ${TRIQS_LIBRARY_LAPACK}") +endif(MAC_VECLIB) +message(STATUS "Lapack libraries : ${TRIQS_LIBRARY_LAPACK}") +link_libraries(${TRIQS_LIBRARY_LAPACK}) + +# ################################# +# HDF5 +# ################################# +message( STATUS "-------- HDF5 detection -------------") +# on weiss, it is 2.8.2 and we should not put HL, on 12.04 we need to put it... +if ( ${CMAKE_VERSION} VERSION_LESS "2.8.6") # CHECK THIS BOUND, where are the cmake changelogs ?? + find_package(HDF5 REQUIRED C CXX ) +else(${CMAKE_VERSION} VERSION_LESS "2.8.6") + find_package(HDF5 REQUIRED C CXX HL ) +endif(${CMAKE_VERSION} VERSION_LESS "2.8.6") +if(NOT HDF5_FOUND) + message(FATAL_ERROR "Require hdf5 1.8.2 or higher. Set HDF5_HOME") +endif() +if(HDF5_IS_PARALLEL) + message(FATAL "parallel(MPI) hdf5 is detected. The standard version is preferred.") +endif(HDF5_IS_PARALLEL) +message( STATUS " HDF5_LIBRARIES = ${HDF5_LIBRARIES} ") +mark_as_advanced(HDF5_DIR) # defined somewhere else ? what is it ? + +include_directories (SYSTEM ${HDF5_INCLUDE_DIR}) +link_libraries (${HDF5_LIBRARIES} ) #${HDF5_CXX_LIBRARIES} ) +set(TRIQS_LIBRARY_HDF5 ${HDF5_LIBRARIES}) +set(TRIQS_INCLUDE_HDF5 ${HDF5_INCLUDE_DIR}) +set(TRIQS_CXX_DEFINITIONS ${TRIQS_CXX_DEFINITIONS} ${HDF5_DEFINITIONS}) +set(TRIQS_HDF5_DIFF_EXECUTABLE ${HDF5_DIFF_EXECUTABLE}) + +# ################################# +# Other libs +# ################################# +# GMP +message( STATUS "-------- GMP detection -------------") +find_package(GMP) +include_directories(SYSTEM ${GMP_INCLUDE_DIR}) +link_libraries(${GMP_LIBRARIES}) +set(TRIQS_LIBRARY_GMP ${GMP_LIBRARIES} ${GMPXX_LIBRARIES}) +set(TRIQS_INCLUDE_GMP ${GMP_INCLUDE_DIR}) + +# FFTW +message( STATUS "-------- FFTW detection -------------") +find_package(FFTW) +include_directories(SYSTEM ${FFTW_INCLUDE_DIR}) +link_libraries( ${FFTW_LIBRARIES}) +set(TRIQS_LIBRARY_FFTW ${FFTW_LIBRARIES}) +set(TRIQS_INCLUDE_FFTW ${FFTW_INCLUDE_DIR}) + +# remove the possible horrible pthread bug on os X !!( on gcc, old, before clang... is it really needed now ???) +# check for clang compiler ?? on gcc, os X snow leopard, it MUST be set +# since _REENTRANT is mysteriously set and this leads to random stalling of the code.... +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(TRIQS_CXX_DEFINITIONS ${TRIQS_CXX_DEFINITIONS} -pthread ) +endif( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + +# +## Remove the test from the build ? +option(Build_Triqs_General_Tools_Test "Build the test of the general tool ? ( array class , ... ) " ON) + +# 64 bits machine ? +#if(CMAKE_SIZEOF_VOID_P EQUAL 8 OR CMAKE_GENERATOR MATCHES Win64) +# set (TRIQS_64BIT ON) +#endif(CMAKE_SIZEOF_VOID_P EQUAL 8 OR CMAKE_GENERATOR MATCHES Win64) + +# is it useful ? +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Type of build" FORCE) + mark_as_advanced(CMAKE_BUILD_TYPE) +endif(NOT CMAKE_BUILD_TYPE) +message(STATUS "Build type: " ${CMAKE_BUILD_TYPE}) + +# Fortran bindings +option(BIND_FORTRAN_LOWERCASE "FORTRAN functions are compiled WITHOUT a trailing underscore" OFF) +mark_as_advanced(BIND_FORTRAN_LOWERCASE) +if (BIND_FORTRAN_LOWERCASE) + set(TRIQS_BIND_FORTRAN_LOWERCASE OFF ) +endif (BIND_FORTRAN_LOWERCASE) + +message( STATUS "-------- git and hash detection -------------") +# git +Find_package(Git3) # our local version of FindGit... +if (GIT_FOUND) + GIT_TREE_INFO ( ${CMAKE_SOURCE_DIR} "GIT") + message(STATUS "Git hash ${GIT_HASH}") + message(STATUS "Git branch : ${GIT_BRANCHES}") + set (TRIQS_GIT_HASH ${GIT_HASH}) +endif (GIT_FOUND) + +# Compute WhoAmI and hostname +# Change this : make a version module +EXECUTE_PROCESS(COMMAND hostname OUTPUT_VARIABLE myHostName RESULT_VARIABLE returncode OUTPUT_STRIP_TRAILING_WHITESPACE) +EXECUTE_PROCESS(COMMAND id -un OUTPUT_VARIABLE WhoAmI RESULT_VARIABLE returncode OUTPUT_STRIP_TRAILING_WHITESPACE) +set(TRIQS_HOSTNAME ${myHostName}) +set(TRIQS_COMPILEDBY ${WhoAmI}) + +# TRIQS cmake file and config.h +message( STATUS "-------- Making TRIQSConfig.cmake -------------") +get_property(ALL_DEFS GLOBAL PROPERTY TRIQS_COMPIL_DEFINITIONS) +configure_file(./cmake/triqs_config.h.in Config/triqs_config.h @ONLY) +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + configure_file(./cmake/TRIQSConfig.cmake.in Config/TRIQSConfig.cmake @ONLY) +else() + configure_file(./cmake/TRIQSConfig.cmake.in Config/TRIQSConfig1.cmake @ONLY ) + EXEC_PYTHON_SCRIPT( "import re;open('${CMAKE_CURRENT_BINARY_DIR}/Config/TRIQSConfig.cmake','w').write(re.sub(r';*\\s*-framework\\s+([a-zA-Z_][a-zA-Z_0-9]*)',r' \"-framework \\1\"',open('${CMAKE_CURRENT_BINARY_DIR}/Config/TRIQSConfig1.cmake').read()))", ConfigFile) +endif() + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Config/TRIQSConfig.cmake DESTINATION share/triqs/cmake) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Config/triqs_config.h DESTINATION include/triqs) +install(FILES ${CMAKE_SOURCE_DIR}/cmake/FindTRIQS.cmake DESTINATION share/triqs/cmake) + +configure_file(./cmake/FindTriqsTest.cmake.in Config//FindTriqsTest.cmake @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Config/FindTriqsTest.cmake DESTINATION share/triqs/cmake) +install(FILES ${CMAKE_SOURCE_DIR}/cmake/run_test.cmake DESTINATION share/triqs/cmake) + +# +enable_testing() + +##------------------------ +# Documentation +##------------------------ +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} + ${FFTW_LIBRARIES} + ${BOOST_LIBRARY} + ${LAPACK_LIBS} + ${GMP_LIBRARIES} ${GMPXX_LIBRARIES} + ) + +# General include header +# remove this dep to C++ +include_directories(${TRIQS_SOURCE_DIR}) + +#------------------------ +# General triqs libraries +#------------------------ + +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) +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 Cython modules -------------") + add_subdirectory(${TRIQS_SOURCE_DIR}/pytriqs ) +endif (PythonSupport) + +#------------------------ +# tests +#------------------------ +add_subdirectory(${TRIQS_SOURCE_DIR}/test ) + +#------------------------ +# Documentation +#------------------------ + +if (Build_Documentation) +message( STATUS "-------- Prepare documentation -------------") + add_subdirectory (${TRIQS_SOURCE_DIR}/doc ) + #add_dependencies(docs_sphinx py_sources) +message( STATUS "----------------------------------------") +endif (Build_Documentation) + +#------------------------ +# FindTRIQS needs to be configured and installed +#------------------------ + +install (FILES ${CMAKE_SOURCE_DIR}/cmake/FindTRIQS.cmake DESTINATION share/triqs/cmake) + +#------------------------ +# Packaging +#------------------------ + +# make the source package +set(TAR_SRC_FILE ${CMAKE_CURRENT_BINARY_DIR}/triqs_src.tgz) +set(TAR_SRC_DIRBUILD ${CMAKE_CURRENT_BINARY_DIR}/triqs_src_tgz_build) +add_custom_command( OUTPUT ${TAR_SRC_FILE} COMMAND mkdir -p ${TAR_SRC_DIRBUILD} && cd ${TAR_SRC_DIRBUILD} && ${Subversion_SVN_EXECUTABLE} export --force ${Project_WC_URL} triqs_src && tar cvzf ${TAR_SRC_FILE} triqs_src) +add_custom_target(src_tgz DEPENDS ${TAR_SRC_FILE}) + +# .deb and dmg +INCLUDE(InstallRequiredSystemLibraries) + +# Prepare the postinstall and preremoval for debian +configure_file(${TRIQS_SOURCE_DIR}/cmake/prerm.in ${CMAKE_CURRENT_BINARY_DIR}/prerm) +configure_file(${TRIQS_SOURCE_DIR}/cmake/postinst.in ${CMAKE_CURRENT_BINARY_DIR}/postinst) + +set(CPACK_PACKAGE_NAME "triqs") +set(CPACK_PACKAGE_FILE_NAME "triqs") +set(CPACK_PACKAGE_VENDOR "The TRIQS collaboration") +set(CPACK_DEBIAN_PACKAGE_SECTION "Science") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "TRIQS, a Toolbox for Research in Quantum Interacting Systems") +set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.txt") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt") +set(CPACK_PACKAGE_CONTACT "Olivier Parcollet ") +set(CPACK_PACKAGE_VERSION_MAJOR "0") +set(CPACK_PACKAGE_VERSION_MINOR "9") +set(CPACK_PACKAGE_VERSION_PATCH "1-2") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "TRIQS_${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") +set(CPACK_STRIP_FILES "bin/pytriqs") +set(CPACK_SOURCE_STRIP_FILES "") +set(CPACK_PACKAGE_EXECUTABLES "pytriqs" "pytriqs") +set(CPACK_DEBIAN_PACKAGE_DEPENDS "openmpi-bin(>=1.4), libblas-dev (>=1.2), ipython (>=0.12), libfftw3-dev (>=3.2), hdf5-tools (>=1.8), python-matplotlib (>=1.1) ") +set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA ${CMAKE_CURRENT_BINARY_DIR}/prerm;${CMAKE_CURRENT_BINARY_DIR}/postinst) +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(CPACK_GENERATOR TGZ DEB) +endif(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + +INCLUDE(CPack) + diff --git a/COPYING.txt b/COPYING.txt new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/COPYING.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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. + + This program 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 this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..51f86613 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,18 @@ + +TRIQS: a Toolbox for Research in Interacting Quantum Systems + +Copyright (C) 2011 by M. Ferrero, 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 (in the file COPYING.txt in this directory). If not, see +. + diff --git a/README.txt b/README.txt new file mode 100644 index 00000000..1d080ac7 --- /dev/null +++ b/README.txt @@ -0,0 +1,13 @@ + +The TRIQS website is under http://ipht.cea.fr/triqs. Start there +to learn about TRIQS. + +To install TRIQS, follow the installation steps given under +http://ipht.cea.fr/triqs/doc/user_manual/install/install.html + +Before you proceed, make sure you have read the LICENSE.txt file. + +Enjoy! + +The TRIQS team + diff --git a/cmake/BuildSphinx.cmake b/cmake/BuildSphinx.cmake new file mode 100644 index 00000000..8042b556 --- /dev/null +++ b/cmake/BuildSphinx.cmake @@ -0,0 +1,47 @@ +# Copyright Olivier Parcollet 2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# This module looks for sphinx documentation tool +# and define a function that prepares the Makefile for sphinx-build + +FIND_PROGRAM(SPHINXBUILD_EXECUTABLE + NAMES sphinx-build sphinx-build-2.6 + PATHS $ENV{HOME}/bin /usr/bin /opt/local/bin + PATH_SUFFIXES bin + ) + +if (NOT SPHINXBUILD_EXECUTABLE) + MESSAGE(FATAL_ERROR "I can not find sphinx to build the triqs documentation") +else (NOT SPHINXBUILD_EXECUTABLE) + MESSAGE(STATUS "sphinx-build program found at ${SPHINXBUILD_EXECUTABLE} ") +endif (NOT SPHINXBUILD_EXECUTABLE) + +# a little hack to make the doc being compiled by pytriqs itself ! +# so that autodoc loading works... +if (TRIQS_BUILD_STATIC) + SET(SPHINXBUILD_EXECUTABLE PYTHONPATH=${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}/bin/pytriqs ${SPHINXBUILD_EXECUTABLE}) +else (TRIQS_BUILD_STATIC) + SET(SPHINXBUILD_EXECUTABLE ${CMAKE_BINARY_DIR}/run_pytriqs_for_test.sh ${SPHINXBUILD_EXECUTABLE}) +endif (TRIQS_BUILD_STATIC) + +# handle the QUIETLY and REQUIRED arguments and set SPHINXBUILD_FOUND to TRUE if +# all listed variables are TRUE + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SPHINX DEFAULT_MSG SPHINXBUILD_EXECUTABLE) + +MARK_AS_ADVANCED( SPHINXBUILD_EXECUTABLE ) + +SET(sphinx_top ${CMAKE_CURRENT_BINARY_DIR}/html/contents.html) +add_custom_command(OUTPUT ${sphinx_top} DEPENDS ${SOURCES} COMMAND ${SPHINXBUILD_EXECUTABLE} -c . -b html ${DOC_SOURCE} html) +add_custom_target(docs_sphinx${DOC_EXT} ALL DEPENDS ${sphinx_top} ${DOC_SOURCE}) + +if (Build_PDF_Documentation) + SET(sphinx_top_pdf ${CMAKE_CURRENT_BINARY_DIR}/latex/TRIQS.pdf) + add_custom_command(OUTPUT ${sphinx_top_pdf} DEPENDS ${SOURCES} COMMAND ${SPHINXBUILD_EXECUTABLE} -c . -b latex ${DOC_SOURCE} latex && cd latex + && pdflatex -interaction=nonstopmode TRIQS.tex && pdflatex -interaction=nonstopmode TRIQS.tex) + add_custom_target(docs_sphinx_pdf${DOC_EXT} ALL DEPENDS ${sphinx_top_pdf} ${DOC_SOURCE}) +endif() + diff --git a/cmake/CompileBoost.cmake b/cmake/CompileBoost.cmake new file mode 100644 index 00000000..472a5bb4 --- /dev/null +++ b/cmake/CompileBoost.cmake @@ -0,0 +1,302 @@ +# Copyright Olivier Parcollet 2011 : modified to remove pyalps install +# Copyright Matthias Troyer 2009 - 2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# +# libboost +# + +set (Boost_ROOT_DIR ${BOOST_SOURCE_DIR}) + +set(BOOST_SOURCES "") +set(BOOST_MPI_PYTHON_SOURCES "") +set(BOOST_LINK_LIBS "") + +# Boost.Date_Time +if(BUILD_BOOST_DATE_TIME) + set(DIRECTORY "${Boost_ROOT_DIR}/libs/date_time/src") + set(SOURCES gregorian/date_generators.cpp gregorian/greg_month.cpp gregorian/greg_weekday.cpp + gregorian/gregorian_types.cpp posix_time/posix_time_types.cpp) + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(BOOST_SOURCES ${BOOST_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) +endif(BUILD_BOOST_DATE_TIME) + +# Boost.Filesystem +if(BUILD_BOOST_FILESYSTEM) + set(DIRECTORY "${Boost_ROOT_DIR}/libs/filesystem") + set(SOURCES + codecvt_error_category.cpp operations.cpp path.cpp path_traits.cpp + portability.cpp unique_path.cpp utf8_codecvt_facet.cpp + windows_file_codecvt.cpp v2_operations.cpp v2_path.cpp v2_portability.cpp) + foreach (D ${DIRECTORY}/src ${DIRECTORY}/v2/src ${DIRECTORY}/v3/src) + foreach(S ${SOURCES}) + if(EXISTS ${D}/${S}) + set(BOOST_SOURCES ${BOOST_SOURCES} ${D}/${S}) + endif(EXISTS ${D}/${S}) + endforeach(S) + endforeach(D) +endif(BUILD_BOOST_FILESYSTEM) + +# Boost.ProgramOptions +if(BUILD_BOOST_PROGRAM_OPTIONS) + set(DIRECTORY "${Boost_ROOT_DIR}/libs/program_options/src") + set(SOURCES cmdline.cpp config_file.cpp options_description.cpp parsers.cpp + variables_map.cpp value_semantic.cpp positional_options.cpp utf8_codecvt_facet.cpp + convert.cpp winmain.cpp) + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(BOOST_SOURCES ${BOOST_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) +endif(BUILD_BOOST_PROGRAM_OPTIONS) + +# Boost.Regex +if(BUILD_BOOST_REGEX) + set(DIRECTORY "${Boost_ROOT_DIR}/libs/regex/src") + set(SOURCES c_regex_traits.cpp cpp_regex_traits.cpp cregex.cpp fileiter.cpp icu.cpp + instances.cpp posix_api.cpp regex.cpp regex_debug.cpp regex_raw_buffer.cpp + regex_traits_defaults.cpp static_mutex.cpp usinstances.cpp w32_regex_traits.cpp + wc_regex_traits.cpp wide_posix_api.cpp winstances.cpp) + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(BOOST_SOURCES ${BOOST_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) +endif(BUILD_BOOST_REGEX) + + +# Boost.Serialization +if(BUILD_BOOST_SERIALIZATION) + set(DIRECTORY "${Boost_ROOT_DIR}/libs/serialization/src") + set(SOURCES archive_exception.cpp basic_archive.cpp + basic_iarchive.cpp basic_iserializer.cpp basic_oarchive.cpp + basic_oserializer.cpp basic_pointer_iserializer.cpp + basic_pointer_oserializer.cpp basic_serializer_map.cpp + basic_text_iprimitive.cpp basic_text_oprimitive.cpp + basic_text_wiprimitive.cpp basic_text_woprimitive.cpp + basic_xml_archive.cpp binary_iarchive.cpp binary_oarchive.cpp + binary_wiarchive.cpp binary_woarchive.cpp codecvt_null.cpp + extended_type_info.cpp extended_type_info_no_rtti.cpp + extended_type_info_typeid.cpp polymorphic_iarchive.cpp + polymorphic_oarchive.cpp shared_ptr_helper.cpp stl_port.cpp + text_iarchive.cpp text_oarchive.cpp text_wiarchive.cpp + text_woarchive.cpp utf8_codecvt_facet.cpp void_cast.cpp + xml_archive_exception.cpp xml_grammar.cpp xml_iarchive.cpp + xml_oarchive.cpp xml_wgrammar.cpp xml_wiarchive.cpp + xml_woarchive.cpp) + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(BOOST_SOURCES ${BOOST_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) +endif(BUILD_BOOST_SERIALIZATION) + +# Boost.Python +if(BUILD_BOOST_PYTHON) + set(BOOST_LINK_LIBS ${BOOST_LINK_LIBS} ${PYTHON_LIBRARY} ${PYTHON_EXTRA_LIBS}) + set(DIRECTORY "${Boost_ROOT_DIR}/libs/python/src") + set(SOURCES dict.cpp errors.cpp exec.cpp import.cpp list.cpp long.cpp + module.cpp numeric.cpp object_operators.cpp object_protocol.cpp slice.cpp + str.cpp tuple.cpp wrapper.cpp converter/arg_to_python_base.cpp + converter/builtin_converters.cpp converter/from_python.cpp + converter/registry.cpp converter/type_id.cpp object/class.cpp + object/enum.cpp object/function.cpp object/function_doc_signature.cpp + object/inheritance.cpp object/iterator.cpp object/life_support.cpp + object/pickle_support.cpp object/stl_iterator.cpp + ) + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(BOOST_SOURCES ${BOOST_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) + add_definitions(-DBOOST_PYTHON_SOURCE) +endif(BUILD_BOOST_PYTHON) + +# Boost.System +if(BUILD_BOOST_SYSTEM) + set(DIRECTORY "${Boost_ROOT_DIR}/libs/system/src") + set(SOURCES error_code.cpp) + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(BOOST_SOURCES ${BOOST_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) +endif(BUILD_BOOST_SYSTEM) + +# Boost.MPI +if(BUILD_BOOST_MPI) + IF(NOT WIN32) + set(BOOST_LINK_LIBS ${BOOST_LINK_LIBS} ${MPI_LIBRARIES}) + ENDIF(NOT WIN32) + set(DIRECTORY "${Boost_ROOT_DIR}/libs/mpi/src") + set(SOURCES broadcast.cpp communicator.cpp computation_tree.cpp + content_oarchive.cpp environment.cpp exception.cpp graph_communicator.cpp + group.cpp intercommunicator.cpp mpi_datatype_cache.cpp + mpi_datatype_oarchive.cpp packed_iarchive.cpp packed_oarchive.cpp + packed_skeleton_iarchive.cpp packed_skeleton_oarchive.cpp + point_to_point.cpp request.cpp timer.cpp + ) + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(BOOST_SOURCES ${BOOST_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) +endif(BUILD_BOOST_MPI) + +# Boost.Thread +if(BUILD_BOOST_THREAD) + if (NOT WIN32) + set(BOOST_LINK_LIBS ${BOOST_LINK_LIBS} ${PTHREAD_LIBRARY}) + endif (NOT WIN32) + set(DIRECTORY "${Boost_ROOT_DIR}/libs/thread/src") + if (WIN32) + set(SOURCES win32/thread.cpp win32/tss_dll.cpp win32/tss_pe.cpp) + else (WIN32) + set(SOURCES pthread/once.cpp pthread/thread.cpp) + endif(WIN32) + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(BOOST_SOURCES ${BOOST_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) +endif(BUILD_BOOST_THREAD) + + +# Boost.MPI Python bindings +if (BUILD_BOOST_MPI AND BUILD_BOOST_PYTHON AND NOT ALPS_BUILD_SOURCE AND Boost_ROOT_DIR) + + set(DIRECTORY "${Boost_ROOT_DIR}/libs/mpi/src/python") + set(SOURCES collectives.cpp py_communicator.cpp datatypes.cpp + documentation.cpp py_environment.cpp py_nonblocking.cpp py_exception.cpp + module.cpp py_request.cpp skeleton_and_content.cpp status.cpp py_timer.cpp + serialize.cpp + ) + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(BOOST_MPI_PYTHON_SOURCES ${BOOST_MPI_PYTHON_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) + + if (BOOST_MPI_PYTHON_SOURCES) + python_add_module(mpi ${BOOST_MPI_PYTHON_SOURCES}) + if(BUILD_SHARED_LIBS) + set_target_properties(mpi PROPERTIES COMPILE_DEFINITIONS "${ALPS_SHARED_CPPFLAGS}") + if(WIN32 AND NOT UNIX) + set_target_properties(mpi PROPERTIES SUFFIX ".pyd") + endif(WIN32 AND NOT UNIX) + endif (BUILD_SHARED_LIBS) + + set_target_properties(mpi PROPERTIES PREFIX "") + target_link_libraries(mpi ${ALPS_BOOST_LIBRARY_NAME} ${BOOST_LINK_LIBS}) + + endif(BOOST_MPI_PYTHON_SOURCES) + +endif (BUILD_BOOST_MPI AND BUILD_BOOST_PYTHON AND NOT ALPS_BUILD_SOURCE AND Boost_ROOT_DIR) + + +####################################################################### +# install +####################################################################### + +# Setting "boost" target not needed when precompiled Boost libraries found. + +if (NOT Boost_FOUND) + add_library(${ALPS_BOOST_LIBRARY_NAME} ${BOOST_SOURCES}) + target_link_libraries(${ALPS_BOOST_LIBRARY_NAME} ${BOOST_LINK_LIBS}) + + # Boost.Test + if(BUILD_BOOST_TEST AND NOT ALPS_FOR_VISTRAILS) + set(DIRECTORY "${Boost_ROOT_DIR}/libs/test/src") + + set(SOURCES compiler_log_formatter.cpp debug.cpp + execution_monitor.cpp framework.cpp + interaction_based.cpp logged_expectations.cpp plain_report_formatter.cpp + progress_monitor.cpp results_collector.cpp results_reporter.cpp + test_tools.cpp unit_test_log.cpp unit_test_main.cpp + unit_test_monitor.cpp unit_test_parameters.cpp unit_test_suite.cpp + xml_log_formatter.cpp xml_report_formatter.cpp + ) + set (TEST_EXEC_MON_SOURCES "") + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(TEST_EXEC_MON_SOURCES ${TEST_EXEC_MON_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) + + set(SOURCES ${SOURCES} exception_safety.cpp) + set (UTF_SOURCES "") + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(UTF_SOURCES ${UTF_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) + + set(SOURCES execution_monitor.cpp debug.cpp cpp_main.cpp ) + set (PRG_EXEC_MON_SOURCES "") + foreach(S ${SOURCES}) + if(EXISTS ${DIRECTORY}/${S}) + set(PRG_EXEC_MON_SOURCES ${PRG_EXEC_MON_SOURCES} ${DIRECTORY}/${S}) + endif(EXISTS ${DIRECTORY}/${S}) + endforeach(S) + + add_library(boost_unit_test_framework ${UTF_SOURCES}) + add_library(boost_test_exec_monitor ${TEST_EXEC_MON_SOURCES}) + add_library(boost_prg_exec_monitor ${PRG_EXEC_MON_SOURCES}) + + if(BUILD_SHARED_LIBS) + set_target_properties(boost_unit_test_framework PROPERTIES COMPILE_DEFINITIONS BOOST_TEST_DYN_LINK=1) + set_target_properties(boost_test_exec_monitor PROPERTIES COMPILE_DEFINITIONS BOOST_TEST_DYN_LINK=1) + set_target_properties(boost_prg_exec_monitor PROPERTIES COMPILE_DEFINITIONS BOOST_TEST_DYN_LINK=1) + endif(BUILD_SHARED_LIBS) + + endif(BUILD_BOOST_TEST AND NOT ALPS_FOR_VISTRAILS) + + + if(WIN32) + if(BUILD_SHARED_LIBS) + set_target_properties(boost PROPERTIES COMPILE_DEFINITIONS BOOST_THREAD_BUILD_DLL=1) + else(BUILD_SHARED_LIBS) + set_target_properties(boost PROPERTIES COMPILE_DEFINITIONS BOOST_THREAD_BUILD_LIB=1) + endif(BUILD_SHARED_LIBS) + endif(WIN32) + + if (NOT ALPS_BUILD_SOURCE) + if(MSVC) + get_target_property(LIB_NAME ${ALPS_BOOST_LIBRARY_NAME} LOCATION) + add_custom_command(TARGET ${ALPS_BOOST_LIBRARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${LIB_NAME} ${PROJECT_BINARY_DIR}/bin) + endif(MSVC) + + if (ALPS_FOR_VISTRAILS) + SET_TARGET_PROPERTIES(${ALPS_BOOST_LIBRARY_NAME} + PROPERTIES BUILD_WITH_INSTALL_RPATH ON + INSTALL_NAME_DIR "@executable_path/../Frameworks" + ) + endif (ALPS_FOR_VISTRAILS) + + if (ALPS_INSTALL_VISTRAILS_PACKAGES) + install(TARGETS ${ALPS_BOOST_LIBRARY_NAME} COMPONENT vistrails + RUNTIME DESTINATION ${VISTRAILS_DYLIB_DIR} + ARCHIVE DESTINATION ${VISTRAILS_DYLIB_DIR} + LIBRARY DESTINATION ${VISTRAILS_DYLIB_DIR}) + endif (ALPS_INSTALL_VISTRAILS_PACKAGES) + if (NOT ALPS_FOR_VISTRAILS) + install(TARGETS ${ALPS_BOOST_LIBRARY_NAME} COMPONENT libraries + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) + if (ALPS_INSTALL_BOOST_TEST) + install(TARGETS boost_unit_test_framework boost_test_exec_monitor boost_prg_exec_monitor + COMPONENT libraries + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) + endif(ALPS_INSTALL_BOOST_TEST) + endif (NOT ALPS_FOR_VISTRAILS) + endif (NOT ALPS_BUILD_SOURCE) +endif (NOT Boost_FOUND) diff --git a/cmake/Doxyfile.in b/cmake/Doxyfile.in new file mode 100644 index 00000000..7dc83a2d --- /dev/null +++ b/cmake/Doxyfile.in @@ -0,0 +1,1290 @@ +# Doxyfile 1.5.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +#ALIASES = +ALIASES = "rst=\verbatim embed:rst" +ALIASES += "endrst=\endverbatim" + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = NO + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = NO + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @DOXYGEN_SOURCES_LIST@ + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = *::*details::*, *impl* + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = @DOXYGEN_HTML_OUTPUT@ + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = doxy.tag +#GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/cmake/FindBuildF2pyModule.cmake b/cmake/FindBuildF2pyModule.cmake new file mode 100644 index 00000000..01045544 --- /dev/null +++ b/cmake/FindBuildF2pyModule.cmake @@ -0,0 +1,38 @@ +# +# This macro builds the f2py module +# - target_name +# - +# +macro (BuildF2pyModule target_name modulename module_pyf_name filelist1) + + set(filelist ${filelist1} ${ARGN}) + set(filename temp_script.py) + # Copy all the files + EXECUTE_PROCESS(COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/${module_pyf_name} ${CMAKE_CURRENT_BINARY_DIR} ) + FOREACH( f ${filelist}) + EXECUTE_PROCESS(COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/${f} ${CMAKE_CURRENT_BINARY_DIR} ) + ENDFOREACH(f) + # write the script that will build the f2py extension + SET(filename ${CMAKE_CURRENT_BINARY_DIR}/${filename} ) + FILE(WRITE ${filename} "import sys\n") + FILE(APPEND ${filename} "from numpy.f2py import main\n") + FILE(APPEND ${filename} "sys.argv = [''] +'-c --f77exec=${CMAKE_Fortran_COMPILER} --f90exec=${CMAKE_Fortran_COMPILER} -m ${modulename} ${modulename}.pyf ${filelist} -llapack'.split()\n") + FILE(APPEND ${filename} "main()\n") + + # We had the normal target of the module + add_custom_target(${target_name} ALL DEPENDS ${modulename}.so) + + # TODO : to be corrected with the filelist is more than one file. + # ... and a special target to build vertex.so, that depends on the sources files + add_custom_command(OUTPUT ${modulename}.so + COMMAND echo See `pwd`/f2pyBuild.log for logs + COMMAND ${PYTHON_INTERPRETER} temp_script.py > f2pyBuild.log 2>&1 + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${filelist} ${CMAKE_CURRENT_SOURCE_DIR}/${module_pyf_name} + ) + + #FILE(RELATIVE_PATH rel ${CMAKE_SOURCE_DIR}/Modules ${CMAKE_CURRENT_SOURCE_DIR}/) + #install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${modulename}.so + # DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${ExecutableName}/triqs/${rel}/..) + +endmacro (BuildF2pyModule) + diff --git a/cmake/FindCompilerCheck.cmake b/cmake/FindCompilerCheck.cmake new file mode 100644 index 00000000..ea676b77 --- /dev/null +++ b/cmake/FindCompilerCheck.cmake @@ -0,0 +1,91 @@ +# Copyright Olivier Parcollet 2012 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# +# +# Compilers are sorted by group of interoperability +# group 1 : fully compliant C++11 compiler +# gcc 4.8.1 and higher, clang >= 3.3 +# group 1 : older gcc, ok with workaround +# group 2 : Intel 14.0 : almost C++11, but with Intel workaround +# group 3 : Intel 13.0 : messy compiler... +# group 0 : other + +if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") + + EXECUTE_PROCESS(COMMAND ${CMAKE_CXX_COMPILER} --version + OUTPUT_VARIABLE _compiler_output RESULT_VARIABLE returncode OUTPUT_STRIP_TRAILING_WHITESPACE) + set(compiler_version_min "4.6.3") + set(compiler_name "gcc") + set(compiler_group 1) + string(REGEX REPLACE ".*([2-5]\\.[0-9]\\.[0-9]).*" "\\1" compiler_version ${_compiler_output}) + +elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + + EXECUTE_PROCESS(COMMAND ${CMAKE_CXX_COMPILER} --version + OUTPUT_VARIABLE _compiler_output RESULT_VARIABLE returncode OUTPUT_STRIP_TRAILING_WHITESPACE) + set(CMAKE_COMPILER_IS_CLANG TRUE ) + set(compiler_name "clang") + set(compiler_group 1) + IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + # Apple which does not has the official clang version number ... + string(REGEX REPLACE ".*LLVM ([2-5]\\.[0-9]).*" "\\1" compiler_version ${_compiler_output}) + #set( compiler_version_min "3.2") + else() + string(REGEX REPLACE ".*([2-5]\\.[0-9]).*" "\\1" compiler_version ${_compiler_output}) + endif() + set( compiler_version_min "3.2") + +elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Intel") + + EXECUTE_PROCESS(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion + OUTPUT_VARIABLE compiler_version RESULT_VARIABLE returncode OUTPUT_STRIP_TRAILING_WHITESPACE) + set(CMAKE_COMPILER_IS_ICC TRUE ) + set(compiler_version_min "13.0.0") + set(compiler_name "Intel icc") + set(compiler_group 3) + #string(REGEX REPLACE "[^0-9]*([0-9]+\\.[0-9]\\.[0-9]).*" "\\1" compiler_version ${_compiler_output}) + + # for intel 14.0 /test + link_libraries( -lomp_db ) + +else () + set(compiler_version_min "0.0") + set(compiler_group 0) + set(line_of_star "\n************************** WARNING ************************************\n") + MESSAGE( WARNING "${line_of_star} Compiler not recognized by TRIQS : TRIQS may compile .. or not ${line_of_star}") + #message(FATAL_ERROR "Your C++ compiler does not support C++11.") +endif () + + +MESSAGE( STATUS "Compiler is ${compiler_name} with version ${compiler_version}") + +# Check version +if(compiler_version VERSION_LESS ${compiler_version_min} ) + set(line_of_star "\n************************** FATAL ERROR ************************************\n") + MESSAGE( FATAL_ERROR "${line_of_star}You are using the ${compiler_name} compiler but your compiler is too old :\n TRIQS requires version >= ${compiler_version_min} while you have ${compiler_version}\n ${line_of_star}") +endif(compiler_version VERSION_LESS ${compiler_version_min} ) + +# Now add some definitions ... + +# on OS X : for clang, add the infamous -stdlib=libc++ +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + if (CMAKE_COMPILER_IS_CLANG) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ ") + MESSAGE(STATUS "Adding compilation flags -stdlib=libc++ ") + else (CMAKE_COMPILER_IS_CLANG) + MESSAGE( WARNING "${line_of_star}You are on Os X but your are not using clang. This is NOT recommended...${line_of_star}") + endif (CMAKE_COMPILER_IS_CLANG) +ENDIF( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + +# for icc, add the very infamous flags or calculation of boost::math bessel function are wrong !! +# tested on boost 1.53 +IF(CMAKE_COMPILER_IS_ICC) + set(TRIQS_CXX_DEFINITIONS ${TRIQS_CXX_DEFINITIONS} -DTRIQS_WORKAROUND_INTEL_COMPILER_BUGS -DBOOST_MATH_DISABLE_STD_FPCLASSIFY) + #add_definitions( -DTRIQS_WORKAROUND_INTEL_COMPILER_BUGS -DBOOST_MATH_DISABLE_STD_FPCLASSIFY) + MESSAGE(STATUS " Adding compilation flags -DTRIQS_WORKAROUND_INTEL_COMPILER_BUGS -DBOOST_MATH_DISABLE_STD_FPCLASSIFY") +ENDIF(CMAKE_COMPILER_IS_ICC) + + diff --git a/cmake/FindCythonModuleMacro.cmake b/cmake/FindCythonModuleMacro.cmake new file mode 100644 index 00000000..7da843f9 --- /dev/null +++ b/cmake/FindCythonModuleMacro.cmake @@ -0,0 +1,35 @@ + +# Compile and link with python +#link_libraries(${PYTHON_LIBRARY} ${PYTHON_EXTRA_LIBS} ) +include_directories(${PYTHON_INCLUDE_DIRS} ${PYTHON_NUMPY_INCLUDE_DIR}) + +function (python_register_dynamic_module NickName) + set_property (GLOBAL APPEND PROPERTY DEPENDANCE_TO_ADD triqs_${NickName} ) + set_property (GLOBAL APPEND PROPERTY Modules_actually_compiled ${NickName} ) +endfunction (python_register_dynamic_module NickName) + +# This function add the target to build a python module +# +# NickName = +# ModuleName = the python name of the module +# ModuleDest = path in the pytriqs tree [ FOR INSTALLATION ONLY] IMPROVE MAKE THIS OPTIONAL (for test) +macro (cython_module NickName ModuleName) + MESSAGE(STATUS "Preparing cython module ${NickName} ") + get_filename_component(CYTHON_EXECUTABLE_PATH ${PYTHON_INTERPRETER} PATH) + SET(CYTHON_EXECUTABLE ${CYTHON_EXECUTABLE_PATH}/cython CACHE STRING "Path to the cython executable") + SET(cython_src ${CMAKE_CURRENT_SOURCE_DIR}/${ModuleName}.pyx ) + FILE(GLOB all_pyx_src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.pyx *.pxd ) + SET(cython_wrap ${CMAKE_CURRENT_BINARY_DIR}/wrap_${NickName}_by_cython.cpp) + add_custom_command (OUTPUT ${cython_wrap} DEPENDS ${all_pyx_src} COMMAND ${CYTHON_EXECUTABLE} ${cython_src} -I ${CMAKE_CURRENT_SOURCE_DIR}/ -I${CMAKE_SOURCE_DIR}/pytriqs/pxd -X embedsignature=True --cplus -o ${cython_wrap} ) + add_custom_target(cython_${NickName} ALL DEPENDS ${cython_wrap}) + + add_library(${ModuleName} MODULE ${cython_wrap} ) + 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 "") + install (TARGETS ${ModuleName} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/${ARGN} ) + endif (${ARGN} MATCHES "") + set_property (GLOBAL APPEND PROPERTY DEPENDANCE_TO_ADD triqs_${NickName} ) + +endmacro (cython_module) + diff --git a/cmake/FindFFTW.cmake b/cmake/FindFFTW.cmake new file mode 100644 index 00000000..c53a1a58 --- /dev/null +++ b/cmake/FindFFTW.cmake @@ -0,0 +1,38 @@ +# Copyright Olivier Parcollet 2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# +# This module looks for fftw. +# It sets up : FFTW_INCLUDE_DIR, FFTW_LIBRARIES +# + +SET(TRIAL_PATHS + $ENV{FFTW_ROOT}/include + ${FFTW_ROOT}/include + /usr/include + /usr/local/include + /opt/local/include + /sw/include + ) +FIND_PATH(FFTW_INCLUDE_DIR fftw3.h ${TRIAL_PATHS} DOC "Include for FFTW") + +SET(TRIAL_LIBRARY_PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + $ENV{FFTW_ROOT}/lib + ${FFTW_ROOT}/lib + ) + +SET(FFTW_LIBRARIES "FFTW_LIBRARIES-NOTFOUND" CACHE STRING "FFTW library") +# Try to detect the lib +FIND_LIBRARY(FFTW_LIBRARIES fftw3 ${TRIAL_LIBRARY_PATHS} DOC "FFTW library") + +mark_as_advanced(FFTW_INCLUDE_DIR) +mark_as_advanced(FFTW_LIBRARIES) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFTW DEFAULT_MSG FFTW_LIBRARIES FFTW_INCLUDE_DIR) + diff --git a/cmake/FindGMP.cmake b/cmake/FindGMP.cmake new file mode 100644 index 00000000..f3e04b8b --- /dev/null +++ b/cmake/FindGMP.cmake @@ -0,0 +1,24 @@ +# Try to find the GMP librairies +# GMP_FOUND - system has GMP lib +# GMP_INCLUDE_DIR - the GMP include directory +# GMP_LIBRARIES - Libraries needed to use GMP + +# Copyright (c) 2006, Laurent Montel, +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (GMP_INCLUDE_DIR AND GMP_LIBRARIES) + # Already in cache, be silent + set(GMP_FIND_QUIETLY TRUE) +endif (GMP_INCLUDE_DIR AND GMP_LIBRARIES) + +find_path(GMP_INCLUDE_DIR NAMES gmp.h ) +find_library(GMP_LIBRARIES NAMES gmp libgmp ) +find_library(GMPXX_LIBRARIES NAMES gmpxx libgmpxx ) +MESSAGE(STATUS "GMP libs: " ${GMP_LIBRARIES} " " ${GMPXX_LIBRARIES} ) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMP DEFAULT_MSG GMP_INCLUDE_DIR GMP_LIBRARIES) + +mark_as_advanced(GMP_INCLUDE_DIR GMP_LIBRARIES GMPXX_LIBRARIES) diff --git a/cmake/FindGSL.cmake b/cmake/FindGSL.cmake new file mode 100644 index 00000000..7e49d9cd --- /dev/null +++ b/cmake/FindGSL.cmake @@ -0,0 +1,38 @@ +# Copyright Olivier Parcollet 2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# +# This module looks for fftw. +# It sets up : GSL_INCLUDE_DIR, GSL_LIBRARIES +# + +SET(TRIAL_PATHS + $ENV{GSL_ROOT}/include + ${GSL_ROOT}/include + /usr/include + /usr/local/include + /opt/local/include + /sw/include + ) +FIND_PATH(GSL_INCLUDE_DIR gsl/gsl_math.h ${TRIAL_PATHS} DOC "Include for GSL") + +SET(TRIAL_LIBRARY_PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + $ENV{GSL_ROOT}/lib + ${GSL_ROOT}/lib + ) + +SET(GSL_LIBRARIES "GSL_LIBRARIES-NOTFOUND" CACHE STRING "GSL library") +# Try to detect the lib +FIND_LIBRARY(GSL_LIBRARIES gsl ${TRIAL_LIBRARY_PATHS} DOC "GSL library") + +mark_as_advanced(GSL_INCLUDE_DIR) +mark_as_advanced(GSL_LIBRARIES) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GSL DEFAULT_MSG GSL_LIBRARIES GSL_INCLUDE_DIR) + diff --git a/cmake/FindGit3.cmake b/cmake/FindGit3.cmake new file mode 100644 index 00000000..21906d04 --- /dev/null +++ b/cmake/FindGit3.cmake @@ -0,0 +1,79 @@ +# +#Find a Git SCM client. +# +#GIT_FOUND - True if Git was found. +#GIT_EXECUTABLE - Path to the git binary. +#GIT_VERSION - Version of found git binary. +# +#If Git is found, then following function(s) are defined: +#GIT_TREE_INFO( DIR PREFIX ) +# Extracts info from given tree. +# Arguments: +# DIR - Where the git tree is. +# PREFIX - A prefix for defined variables. +# Defined variables: +# ${PREFIX}_HASH - A hash of HEAD revision. +# ${PREFIX}_HASH_SHORT - An abbreviation of the hash. +# + +IF( GIT_EXECUTABLE ) + # Already in cache, be silent + SET( Git_FIND_QUIETLY TRUE ) +ENDIF( GIT_EXECUTABLE ) + +FIND_PROGRAM( GIT_EXECUTABLE git + DOC "Path to the git binary." ) + +# handle the QUIETLY and REQUIRED arguments and set GIT_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE( FindPackageHandleStandardArgs ) +FIND_PACKAGE_HANDLE_STANDARD_ARGS( Git DEFAULT_MSG GIT_EXECUTABLE ) + +MARK_AS_ADVANCED( GIT_EXECUTABLE GIT_VERSION ) + +IF( GIT_FOUND ) + EXECUTE_PROCESS( COMMAND "${GIT_EXECUTABLE}" --version + OUTPUT_VARIABLE GIT_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE ) + STRING( REPLACE "git version " "" GIT_VERSION + "${GIT_VERSION}" ) + + FUNCTION( GIT_TREE_INFO DIR PREFIX ) + EXECUTE_PROCESS( COMMAND "${GIT_EXECUTABLE}" rev-parse HEAD + WORKING_DIRECTORY "${DIR}" + RESULT_VARIABLE GIT_RESULT + OUTPUT_VARIABLE "${PREFIX}_HASH" + ERROR_VARIABLE GIT_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE ) + + IF( NOT ${GIT_RESULT} EQUAL 0 ) + MESSAGE( STATUS "This is not a git clone" ) + #MESSAGE( STATUS " in more details : ... command '${GIT_EXECUTABLE} rev-parse HEAD' failed with following output:\n ..... ${GIT_ERROR}" ) + ENDIF( NOT ${GIT_RESULT} EQUAL 0 ) + + EXECUTE_PROCESS( COMMAND "${GIT_EXECUTABLE}" rev-parse --short HEAD + WORKING_DIRECTORY "${DIR}" + RESULT_VARIABLE GIT_RESULT + OUTPUT_VARIABLE "${PREFIX}_HASH_SHORT" + ERROR_VARIABLE GIT_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE ) + + IF( NOT ${GIT_RESULT} EQUAL 0 ) + #MESSAGE( STATUS " Not a git clone" ) + #MESSAGE( SEND_ERROR "Command '${GIT_EXECUTABLE} rev-parse --short HEAD' failed with following output:\n${GIT_ERROR}" ) + ENDIF( NOT ${GIT_RESULT} EQUAL 0 ) + + EXECUTE_PROCESS( COMMAND "${GIT_EXECUTABLE}" rev-parse --abbrev-ref HEAD + #EXECUTE_PROCESS( COMMAND "${GIT_EXECUTABLE}" branch | grep \\* + WORKING_DIRECTORY "${DIR}" + RESULT_VARIABLE GIT_RESULT + OUTPUT_VARIABLE "${PREFIX}_BRANCHES" + ERROR_VARIABLE GIT_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE ) + + + SET( "${PREFIX}_HASH" "${${PREFIX}_HASH}" PARENT_SCOPE ) + SET( "${PREFIX}_HASH_SHORT" "${${PREFIX}_HASH_SHORT}" PARENT_SCOPE ) + SET( "${PREFIX}_BRANCHES" "${${PREFIX}_BRANCHES}" PARENT_SCOPE ) + ENDFUNCTION( GIT_TREE_INFO ) +ENDIF( GIT_FOUND ) diff --git a/cmake/FindLapack.cmake b/cmake/FindLapack.cmake new file mode 100644 index 00000000..dc92f7ac --- /dev/null +++ b/cmake/FindLapack.cmake @@ -0,0 +1,290 @@ +# - FindLapack.cmake +# Find LAPACK/BLAS (and compatible) numerical libraries +# +# This module will define the following values: +# LAPACK_LIBRARY +# BLAS_LIBRARY +# +# 0) check if BLAS_LIBRARY and LAPACK_LIBRARY have already been set on command line, if so: take these values. +# 1) search ENV MKL +# 2) search MKL in usual paths +# 3) search ENV ATLAS +# 4) search generic lapack/blas using CMake-provided FindLAPACK.cmake +# if BLA_VENDOR is set, try to use that vendor's LAPACK implementation +# 5) if build is on cray use hardcoded path +# 6) give up + +# Copyright (C) 2009-2010 Matthias Troyer +# Copyright (C) 2009-2010 Synge Todo +# Copyright (C) 2009-2010 Bela Bauer +# Copyright (C) 2009-2010 Brigitte Surer +# Copyright (C) 2009-2010 Lukas Gamper +# Copyright (C) 2009-2010 Ryo IGARASHI +# Copyright (C) 2010 Emanuel Gull +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +SET(MKL_PATHS "/usr/local/lib /usr/lib") + +#IF(NOT QMC_BUILD_STATIC) + +IF(BLAS_LIBRARY AND LAPACK_LIBRARY) + SET(LAPACK_LIBRARY_INIT 1) + SET(BLAS_LIBRARY_INIT 1) +ENDIF(BLAS_LIBRARY AND LAPACK_LIBRARY) + + +IF($ENV{MKL} MATCHES "mkl") + MESSAGE(STATUS "Using intel/mkl library: $ENV{MKL}") + #look for the path where the mkl is installed + STRING(REGEX MATCHALL "[-][L]([^ ;])+" MKL_PATH_WITH_PREFIX "$ENV{MKL}") + STRING(REGEX REPLACE "[-][L]" "" MKL_PATHS ${MKL_PATH_WITH_PREFIX}) +ENDIF($ENV{MKL} MATCHES "mkl") + +SET(MKL_PATHS + $ENV{MKL_HOME}/lib/em${QMC_BITS}t + $ENV{MKL_HOME}/lib/${QMC_BITS} + $ENV{MKL_HOME}/lib + ${MKL_PATHS} + ) +# MESSAGE(STATUS "Looking for intel/mkl library in ${MKL_PATHS}") + +STRING(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" MKL_VERSION "$ENV{MKL_HOME}") +SET(LINK_LAPACK_DEFAULT 1) +IF(${MKL_VERSION} MATCHES "10\\.0\\.[0-2]") + SET(LINK_LAPACK_DEFAULT 0) +ENDIF(${MKL_VERSION} MATCHES "10\\.0\\.[0-2]") + +IF(NOT LAPACK_LIBRARY_INIT) + IF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64") + IF(LINK_LAPACK_DEFAULT) + FIND_LIBRARY(LAPACK_LIBRARY NAMES mkl_lapack PATHS ${MKL_PATHS}) + FIND_LIBRARY(BLAS_LIBRARY NAMES mkl PATHS ${MKL_PATHS}) + ELSE(LINK_LAPACK_DEFAULT) + FIND_LIBRARY(LAPACK_LIBRARY STATIC NAMES mkl_lapack PATHS ${MKL_PATHS}) + FIND_LIBRARY(BLAS_LIBRARY NAMES mkl_em64t PATHS ${MKL_PATHS}) + MESSAGE("-- mkl 10.0.[0-2] warning for EM64T") + MESSAGE("-- Replace libmkl_lapack.so in CMakeCache.txt by libmkl_lapack.a") + ENDIF(LINK_LAPACK_DEFAULT) + ELSE(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64") + FIND_LIBRARY(LAPACK_LIBRARY + NAMES mkl_lapack + PATHS ${MKL_PATHS} + ) + FIND_LIBRARY(BLAS_LIBRARY + NAMES mkl + PATHS ${MKL_PATHS} + ) + ENDIF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64") + + FIND_LIBRARY(INTEL_GUIDE_LIBRARY + NAMES guide + PATHS ${MKL_PATHS} + ) + MARK_AS_ADVANCED(INTEL_GUIDE_LIBRARY) + IF(NOT INTEL_GUIDE_LIBRARY MATCHES "NOTFOUND") + SET(REQUIRE_PTHREAD TRUE) + FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthread) + ENDIF(NOT INTEL_GUIDE_LIBRARY MATCHES "NOTFOUND") + IF(NOT BLAS_guide_LIBRARY MATCHES "NOTFOUND") + SET(REQUIRE_PTHREAD TRUE) + FIND_LIBRARY(PTHREAD_LIBRARY NAMES pthread) + ENDIF(NOT BLAS_guide_LIBRARY MATCHES "NOTFOUND") + + IF(LAPACK_LIBRARY MATCHES "mkl") + MESSAGE(STATUS "Found intel/mkl library") + SET(LAPACK_LIBRARY_INIT 1) + SET(BLAS_LIBRARY_INIT 1) + SET(HAVE_MKL 1) # CACHE BOOL "HAVE_MKL is set to 1") + SET(MKL_INC_PATHS $ENV{MKL_HOME}/include ${MKL_PATHS}) + FIND_PATH(MKL_INCLUDE_DIR mkl.h ${MKL_INC_PATHS}) + INCLUDE_DIRECTORIES(${MKL_INCLUDE_DIR}) + ENDIF(LAPACK_LIBRARY MATCHES "mkl") + +ENDIF(NOT LAPACK_LIBRARY_INIT) + +IF(NOT HAVE_MKL) + IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -framework vecLib") + SET(LAPACK_LIBRARY_INIT 1) + SET(MAC_VECLIB 1 CACHE BOOL "use Mac Framework") + SET(LAPACK_LIBRARY "") + MESSAGE(STATUS "Using Framework on Darwin.") + + ## check goto library: does not work so well + #FIND_LIBRARY(BLAS_LIBRARY NAMES goto + # PATHS + # $ENV{GOTOBLAS_HOME} + # /usr/lib + # /usr/local/lib + # /sw/lib + # ) + SET(BLAS_LIBRARY "") + SET(BLAS_LIBRARY_INIT 1) + ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +ENDIF(NOT HAVE_MKL) + +IF($ENV{ATLAS} MATCHES "atlas") + IF($ENV{ATLAS} MATCHES "lapack") + SET(LAPACK_LIBRARY_INIT 1) + ENDIF($ENV{ATLAS} MATCHES "lapack") + SET(BLAS_LIBRARY $ENV{ATLAS}) + SET(BLAS_LIBRARY_INIT 1) +ENDIF($ENV{ATLAS} MATCHES "atlas") + +IF($ENV{LAPACK} MATCHES "lapack") + SET(LAPACK_LIBRARY $ENV{LAPACK}) + SET(LAPACK_LIBRARY_INIT 1) +ENDIF($ENV{LAPACK} MATCHES "lapack") + +#IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +# SET(LAPACK_LIBRARY $ENV{LAPACK}) +# SET(LAPACK_LIBRARY_INIT 1) +#ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + +IF(${CMAKE_SYSTEM_NAME} MATCHES "AIX") + SET(ELIB essl) + IF(ENABLE_OMP) + SET(ELIB esslsmp) + ENDIF(ENABLE_OMP) + + IF(NOT LAPACK_LIBRARY_INIT) + SET(LLIB lapack-SP4_${QMC_BITS} lapack) + FIND_LIBRARY(LAPACK_LIBRARY + NAMES ${LLIB} + PATHS /usr/apps/math/lapack/LAPACK + lib + ) + FIND_LIBRARY(BLAS_LIBRARY ${ELIB} + /usr/lib + ) + ENDIF(NOT LAPACK_LIBRARY_INIT) + + SET(LAPACK_LIBRARY_INIT 1) + SET(BLAS_LIBRARY_INIT 1) + MESSAGE(STATUS "Found lapack/blas on AIX system") +ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "AIX") + +# for clapack on Windows +IF(NOT LAPACK_LIBRARY_INIT) + if(WIN32 AND NOT UNIX) + set(TRIAL_PATHS "$ENV{HOMEDRIVE}$ENV{HOMEPATH}/opt/lib") + find_library(LAPACK_LIBRARY lapack ${TRIAL_PATHS}) + find_library(BLAS_LIBRARY blas ${TRIAL_PATHS}) + if(LAPACK_LIBRARY AND BLAS_LIBRARY) + SET(LAPACK_LIBRARY_INIT 1) + SET(BLAS_LIBRARY_INIT 1) + set(LAPACK_DEFINITIONS "-DBOOST_NUMERIC_BINDINGS_USE_CLAPACK=1" CACHE STRING "Lapack definitions") + MARK_AS_ADVANCED(LAPACK_DEFINITIONS) + MESSAGE(STATUS "Found Lapack: ${LAPACK_LIBRARY} ${BLAS_LIBRARY}") + endif(LAPACK_LIBRARY AND BLAS_LIBRARY) + endif(WIN32 AND NOT UNIX) +ENDIF(NOT LAPACK_LIBRARY_INIT) + +#IF(NOT LAPACK_LIBRARY_INIT) +# FIND_LIBRARY(LAPACK_LIBRARY NAMES lapack lapack_gnu +# PATHS /usr/apps/math/lapack +# /usr/lib +# /opt/lib +# /usr/local/lib +# /sw/lib +# ) +# IF(LAPACK_LIBRARY) +# MESSAGE(STATUS "Found netlib lapack library") +# SET(LAPACK_LIBRARY_INIT 1) +# ENDIF(LAPACK_LIBRARY) +#ENDIF(NOT LAPACK_LIBRARY_INIT) + +#IF(NOT BLAS_LIBRARY_INIT) +# FIND_LIBRARY(BLAS_LIBRARY NAMES goto blas blas_gnu +# PATHS +# $ENV{GOTOBLAS_HOME} +# /usr/apps/math/lapack +# /usr/lib +# /opt/lib +# /usr/local/lib +# /sw/lib +# ) +# IF(BLAS_LIBRARY) +# MESSAGE(STATUS "Found netlib blas") +# SET(BLAS_LIBRARY_INIT 1) +# ENDIF(BLAS_LIBRARY) +#ENDIF(NOT BLAS_LIBRARY_INIT) + +# Use CMake provided LAPACK/BLAS detection code +# Fortran compiler is needed +IF(NOT BLAS_LIBRARY_INIT AND NOT LAPACK_LIBRARY_INIT) + enable_language(Fortran) + message(STATUS "Falling back to CMake provied LAPACK/BLAS detection.") + find_package(BLAS) + if(BLAS_FOUND) + SET(BLAS_LIBRARY_INIT 1) + SET(BLAS_LIBRARY ${BLAS_LIBRARIES}) + find_package(LAPACK) + if(LAPACK_FOUND) + SET(LAPACK_LIBRARY_INIT 1) + SET(LAPACK_LIBRARY ${LAPACK_LIBRARIES}) + endif(LAPACK_FOUND) + endif(BLAS_FOUND) +ENDIF(NOT BLAS_LIBRARY_INIT AND NOT LAPACK_LIBRARY_INIT) + +### BRANDT +### MOVED BECAUSE OF SCOPE PROBLEM +### PROBABLY SHOULD BE FIXED +MARK_AS_ADVANCED( + LAPACK_LIBRARY + BLAS_LIBRARY +) + +IF(USE_SCALAPACK) + SET(PNPATHS + ${MKL_PATHS} + ${BLACS_HOME}/lib + ${SCALAPACK_HOME}/lib + /usr/lib + /opt/lib + /usr/local/lib + /sw/lib + ) + + IF(INTEL_MKL) + FIND_LIBRARY(BLACSLIB mkl_blacs_${PLAT}_lp${QMC_BITS} PATHS ${PNPATHS}) + FIND_LIBRARY(SCALAPACKLIB mkl_scalapack PATHS ${PNPATHS}) + ENDIF(INTEL_MKL) + + IF(NOT SCALAPACKLIB) + FIND_LIBRARY(BLACSLIB blacs_MPI-${PLAT}-{BLACSDBGLVL} PATHS ${PNPATHS}) + FIND_LIBRARY(BLACSCINIT blacsCinit_MPI-${PLAT}-{BLACSDBGLVL} PATHS ${PNPATHS}) + FIND_LIBRARY(SCALAPACKLIB scalapack PATHS ${PNPATHS}) + ENDIF(NOT SCALAPACKLIB) + + IF(BLACSLIB AND SCALAPACKLIB) + SET(FOUND_SCALAPACK 1 CACHE BOOL "Found scalapack library") + ELSE(BLACSLIB AND SCALAPACKLIB) + SET(FOUND_SCALAPACK 0 CACHE BOOL "Mising scalapack library") + ENDIF(BLACSLIB AND SCALAPACKLIB) + + MARK_AS_ADVANCED( + BLACSCINIT + BLACSLIB + SCALAPACKLIB + FOUND_SCALAPACK + ) +ENDIF(USE_SCALAPACK) + +IF(LAPACK_LIBRARY_INIT) + SET(LAPACK_FOUND TRUE) +ENDIF(LAPACK_LIBRARY_INIT) + +IF(ALPS_BUILD_ON_CRAY) + MARK_AS_ADVANCED( + BLAS_FOUND + LAPACK_FOUND + ) + SET(BLAS_FOUND TRUE) + SET(LAPACK_FOUND TRUE) +ENDIF(ALPS_BUILD_ON_CRAY) + + diff --git a/cmake/FindMathJax.cmake b/cmake/FindMathJax.cmake new file mode 100644 index 00000000..1eade0b5 --- /dev/null +++ b/cmake/FindMathJax.cmake @@ -0,0 +1,23 @@ +# Copyright Olivier Parcollet 2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# +# This module looks for mathjax. +# It sets up : MATHJAX_PATH +# + +SET(TRIAL_PATHS + $ENV{MATHJAX_ROOT} + ${MATHJAX_ROOT} + $ENV{HOME}/MathJax + /usr/share/javascript/mathjax + /opt/local/share/javascript/mathjax + ) +FIND_PATH(MATHJAX_PATH MathJax.js ${TRIAL_PATHS} DOC "Root Path of MathJax") + +mark_as_advanced(MATHJAX_PATH) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(MATHJAX DEFAULT_MSG MATHJAX_PATH) + diff --git a/cmake/FindPython.cmake b/cmake/FindPython.cmake new file mode 100644 index 00000000..da21076e --- /dev/null +++ b/cmake/FindPython.cmake @@ -0,0 +1,178 @@ +# Copyright Olivier Parcollet 2012 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# +# Python settings : +# +# This module checks that : +# - the python interpreter is working and version >= 2.6.5 +# - it has modules : distutils, numpy +# +# This module defines the variables +# - PYTHON_INTERPRETER : name of the python interpreter +# - PYTHON_INCLUDE_DIRS : include for compilation +# - PYTHON_NUMPY_INCLUDE_DIR : include for compilation with numpy +# - PYTHON_LIBRARY : link flags +# - PYTHON_SITE_PKG : path to the standard packages of the python interpreter +# - PYTHON_EXTRA_LIBS : libraries which must be linked in when embedding +# - PYTHON_LINK_FOR_SHARED : linking flags needed when building a shared lib for external modules + +set(PYTHON_MINIMAL_VERSION 2.6.5) + +MESSAGE( STATUS "-------- Python detection -------------") + +# IF PYTHON_INTERPRETER is not defined, try to find a python +if (NOT PYTHON_INTERPRETER ) + find_program(PYTHON_INTERPRETER python PATHS $ENV{PATH}) +endif (NOT PYTHON_INTERPRETER) +if (NOT PYTHON_INTERPRETER) + MESSAGE(FATAL_ERROR "No python interpreter found") +endif(NOT PYTHON_INTERPRETER) + +MESSAGE (STATUS "Python interpreter ${PYTHON_INTERPRETER}") +# +# The function EXEC_PYTHON_SCRIPT executes the_script in python interpreter +# and set the variable of output_var_name in the calling scope +# +FUNCTION ( EXEC_PYTHON_SCRIPT the_script output_var_name) + EXECUTE_PROCESS(COMMAND ${PYTHON_INTERPRETER} -c "${the_script}" + OUTPUT_VARIABLE res RESULT_VARIABLE returncode OUTPUT_STRIP_TRAILING_WHITESPACE) + IF (NOT returncode EQUAL 0) + MESSAGE(FATAL_ERROR "The script : ${the_script} \n did not run properly in the Python interpreter. Check your python installation.") + ENDIF (NOT returncode EQUAL 0) + SET( ${output_var_name} ${res} PARENT_SCOPE) +ENDFUNCTION (EXEC_PYTHON_SCRIPT) + +# +# Check the interpreter and its version +# +EXEC_PYTHON_SCRIPT ("import sys, string; print sys.version.split()[0]" PYTHON_VERSION) +STRING(COMPARE GREATER ${PYTHON_MINIMAL_VERSION} ${PYTHON_VERSION} PYTHON_VERSION_NOT_OK) +IF (PYTHON_VERSION_NOT_OK) + MESSAGE(FATAL_ERROR "Python intepreter version is ${PYTHON_VERSION} . It should be >= ${PYTHON_MINIMAL_VERSION}") +ENDIF (PYTHON_VERSION_NOT_OK) + +EXEC_PYTHON_SCRIPT ("import distutils " nulle) # check that distutils is there... +EXEC_PYTHON_SCRIPT ("import numpy" nulle) # check that numpy is there... +EXEC_PYTHON_SCRIPT ("import h5py" nulle) # check that h5py is there... +EXEC_PYTHON_SCRIPT ("import scipy" nulle) # check that scipy is there... +MESSAGE(STATUS "Python interpreter and modules are ok : version ${PYTHON_VERSION}" ) + +# +# Check for Python include path +# +EXEC_PYTHON_SCRIPT ("import distutils ; from distutils.sysconfig import * ; print distutils.sysconfig.get_python_inc()" PYTHON_INCLUDE_DIRS ) +message(STATUS "PYTHON_INCLUDE_DIRS = ${PYTHON_INCLUDE_DIRS}" ) +mark_as_advanced(PYTHON_INCLUDE_DIRS) +FIND_PATH(TEST_PYTHON_INCLUDE patchlevel.h PATHS ${PYTHON_INCLUDE_DIRS} NO_DEFAULT_PATH) +if (NOT TEST_PYTHON_INCLUDE) + message (ERROR "The Python herader files have not been found. Please check that you installed the Python headers and not only the interpreter.") +endif (NOT TEST_PYTHON_INCLUDE) +mark_as_advanced(TEST_PYTHON_INCLUDE) + +# +# include files for numpy +# +EXEC_PYTHON_SCRIPT ("import numpy;print numpy.get_include()" PYTHON_NUMPY_INCLUDE_DIR) +MESSAGE(STATUS "PYTHON_NUMPY_INCLUDE_DIR = ${PYTHON_NUMPY_INCLUDE_DIR}" ) +mark_as_advanced(PYTHON_NUMPY_INCLUDE_DIR) + +# +# include files for numpy +# +EXEC_PYTHON_SCRIPT ("import numpy;print numpy.version.version" PYTHON_NUMPY_VERSION) +MESSAGE(STATUS "PYTHON_NUMPY_VERSION = ${PYTHON_NUMPY_VERSION}" ) +mark_as_advanced(PYTHON_NUMPY_VERSION) + +# +# Check for site packages +# +EXEC_PYTHON_SCRIPT ("from distutils.sysconfig import * ;print get_python_lib(0,0)" + PYTHON_SITE_PKG) +MESSAGE(STATUS "PYTHON_SITE_PKG = ${PYTHON_SITE_PKG}" ) +mark_as_advanced(PYTHON_SITE_PKG) + +# +# Check for Python library path + # + #EXEC_PYTHON_SCRIPT ("import string; from distutils.sysconfig import * ;print string.join(get_config_vars('VERSION'))" PYTHON_VERSION_MAJOR_MINOR) + EXEC_PYTHON_SCRIPT ("import string; from distutils.sysconfig import *; print '%s/config' % get_python_lib(0,1)" PYTHON_LIBRARY_BASE_PATH) + EXEC_PYTHON_SCRIPT ("import string; from distutils.sysconfig import *; print 'libpython%s' % string.join(get_config_vars('VERSION'))" PYTHON_LIBRARY_BASE_FILE) + IF(BUILD_SHARED_LIBS) + FIND_FILE(PYTHON_LIBRARY NAMES "${PYTHON_LIBRARY_BASE_FILE}.so" PATHS ${PYTHON_LIBRARY_BASE_PATH}) + IF(NOT PYTHON_LIBRARY) + FIND_FILE(PYTHON_LIBRARY NAMES "${PYTHON_LIBRARY_BASE_FILE}.a" PATHS ${PYTHON_LIBRARY_BASE_PATH}) + ENDIF(NOT PYTHON_LIBRARY) + ELSE(BUILD_SHARED_LIBS) + FIND_FILE(PYTHON_LIBRARY NAMES "${PYTHON_LIBRARY_BASE_FILE}.a" PATHS ${PYTHON_LIBRARY_BASE_PATH}) + ENDIF(BUILD_SHARED_LIBS) + MESSAGE(STATUS "PYTHON_LIBRARY = ${PYTHON_LIBRARY}" ) + mark_as_advanced(PYTHON_LIBRARY) + + # + # Cython + # + EXEC_PYTHON_SCRIPT("from Cython.Compiler import Version as V;print V.version.split('.')[1]" PYTHON_CYTHON_VERSION ) + MESSAGE(STATUS "Found cython 0.${PYTHON_CYTHON_VERSION}.xxx") + # check version here + + # + # libraries which must be linked in when embedding + # + EXEC_PYTHON_SCRIPT ("from distutils.sysconfig import * ;print (str(get_config_var('LOCALMODLIBS')) + ' ' + str(get_config_var('LIBS'))).strip()" + PYTHON_EXTRA_LIBS) + MESSAGE(STATUS "PYTHON_EXTRA_LIBS =${PYTHON_EXTRA_LIBS}" ) + mark_as_advanced(PYTHON_EXTRA_LIBS) + + # + # Looking for ipython ... (optional) + # not very useful... in static case, we should not allow ipython anyway I guess... + EXECUTE_PROCESS(COMMAND ${PYTHON_INTERPRETER} -c "try :\n import IPython\n print 1\nexcept:\n print 0" OUTPUT_VARIABLE TRIQS_IPYTHON_DETECTED RESULT_VARIABLE returncode OUTPUT_STRIP_TRAILING_WHITESPACE) + if (TRIQS_IPYTHON_DETECTED) + MESSAGE(STATUS "IPython found") + else (TRIQS_IPYTHON_DETECTED) + MESSAGE(STATUS "IPython NOT FOUND ") + endif (TRIQS_IPYTHON_DETECTED) + + # + # linking flags needed when embedding (building a shared lib) + # To BE RETESTED + # + #EXEC_PYTHON_SCRIPT ("from distutils.sysconfig import *;print get_config_var('LINKFORSHARED')" + # PYTHON_LINK_FOR_SHARED) + #MESSAGE(STATUS "PYTHON_LINK_FOR_SHARED = ${PYTHON_LINK_FOR_SHARED}" ) + #mark_as_advanced(PYTHON_LINK_FOR_SHARED) + + # Correction on Mac + #IF(APPLE) + # SET (PYTHON_LINK_FOR_SHARED -u _PyMac_Error -framework Python) + # SET (PYTHON_LINK_MODULE -bundle -undefined dynamic_lookup) + #ELSE(APPLE) + # SET (PYTHON_LINK_MODULE -shared) + #ENDIF(APPLE) + + set (PYTHONLIBS_FOUND TRUE) #${PYTHON_FOUND}) + + # used in BOOST ONLY !! + FUNCTION(PYTHON_ADD_MODULE _NAME ) + OPTION(PYTHON_ENABLE_MODULE_${_NAME} "Add module ${_NAME}" TRUE) + OPTION(PYTHON_MODULE_${_NAME}_BUILD_SHARED "Add module ${_NAME} shared" ${BUILD_SHARED_LIBS}) + + IF(PYTHON_ENABLE_MODULE_${_NAME}) + IF(PYTHON_MODULE_${_NAME}_BUILD_SHARED) + SET(PY_MODULE_TYPE MODULE) + ELSE(PYTHON_MODULE_${_NAME}_BUILD_SHARED) + SET(PY_MODULE_TYPE STATIC) + SET_PROPERTY(GLOBAL APPEND PROPERTY PY_STATIC_MODULES_LIST ${_NAME}) + ENDIF(PYTHON_MODULE_${_NAME}_BUILD_SHARED) + + SET_PROPERTY(GLOBAL APPEND PROPERTY PY_MODULES_LIST ${_NAME}) + ADD_LIBRARY(${_NAME} ${PY_MODULE_TYPE} ${ARGN}) + # TARGET_LINK_LIBRARIES(${_NAME} ${PYTHON_LIBRARIES}) + + ENDIF(PYTHON_ENABLE_MODULE_${_NAME}) + ENDFUNCTION(PYTHON_ADD_MODULE) +MESSAGE( STATUS "--------------------------------------------") + diff --git a/cmake/FindTRIQS.cmake b/cmake/FindTRIQS.cmake new file mode 100644 index 00000000..94602090 --- /dev/null +++ b/cmake/FindTRIQS.cmake @@ -0,0 +1,58 @@ +# Copyright Olivier Parcollet 2013 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# +# This module looks for triqs +# It sets up : +# HERE MAKE THE LIST ! +# +find_package(PackageHandleStandardArgs) + +SET(TRIAL_PATHS + $ENV{TRIQS_PATH}/include/triqs + ${TRIQS_PATH}/include/triqs + /usr/include/triqs + /usr/local/include/triqs + /opt/local/include/triqs + /sw/include/triqs + ) +FIND_PATH(TRIQS_INCLUDE_DIR triqs_config.h ${TRIAL_PATHS} DOC "Include triqs") + +SET(TRIAL_LIBRARY_PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + $ENV{TRIQS_PATH}/lib + ${TRIQS_PATH}/lib + ) + +SET(TRIQS_LIBRARIES "TRIQS_LIBRARIES-NOTFOUND" CACHE STRING "TRIQS library") +# Try to detect the lib +FIND_LIBRARY(TRIQS_LIBRARIES triqs ${TRIAL_LIBRARY_PATHS} DOC "TRIQS library") + +SET(TRIAL_PATHS + $ENV{TRIQS_PATH}/share/triqs/cmake + ${TRIQS_PATH}/share/triqs/cmake + /usr/share/triqs/cmake + /usr/local/share/triqs/cmake + /opt/local/share/triqs/cmake + /sw/share/triqs/cmake + ) +FIND_PATH(TRIQS_CONFIG_FILE TRIQSConfig.cmake ${TRIAL_PATHS} DOC "TRIQS configuration file") + +mark_as_advanced(TRIQS_INCLUDE_DIR) +mark_as_advanced(TRIQS_LIBRARIES) + +if (NOT TRIQS_CONFIG_FILE) + MESSAGE(FATAL_ERROR " ${TRIQS_PATH} $ENV{TRIQS_PATH}") + MESSAGE(FATAL_ERROR " Can not find the TRIQS config file") +endif() +# include prepare variables + +include(${TRIQS_CONFIG_FILE}/TRIQSConfig.cmake ) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(TRIQS DEFAULT_MSG TRIQS_LIBRARIES TRIQS_INCLUDE_DIR) + diff --git a/cmake/FindTestCSimple.cmake b/cmake/FindTestCSimple.cmake new file mode 100644 index 00000000..10a4c874 --- /dev/null +++ b/cmake/FindTestCSimple.cmake @@ -0,0 +1,44 @@ +# runs python_with_DMFT script > output +# and compares output with script.output +# Example: +# add_triqs_test_script(ExampleTest) +# where ExampleTest.py is the script and ExampleTest.output is the expected output +# +macro(add_test_C_simple testname ) + enable_testing() + + if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output) + + file( COPY ${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + + add_test(${testname} + ${CMAKE_COMMAND} + -Dname=${testname}${ARGN} + -Dcmd=${CMAKE_CURRENT_BINARY_DIR}/${testname}${ARGN} + -Dreference=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output + -P ${TRIQS_SOURCE_DIR}/cmake/run_test.cmake + ) + + else (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output) + add_test(${testname}${ARGN} ${testname}${ARGN} ) + endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output) + +endmacro(add_test_C_simple) + + +macro(add_test_C_hdf testname h5diff_options) + set(h5diff_objects ${ARGN}) # grab additionnal arguments ! + enable_testing() + add_test(${testname} + ${CMAKE_COMMAND} + -Dname=${testname}${ARGN} + -Dcmd=${CMAKE_CURRENT_BINARY_DIR}/${testname}${ARGN} + -DoutputName=${testname}.output.h5 + -Dreference=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output.h5 + -DH5_DIFF_EXECUTABLE=${HDF5_DIFF_EXECUTABLE} + -DH5_DIFF_OPTIONS=${h5diff_options} + -DH5_DIFF_OBJECTS=${h5diff_objects} + -P ${TRIQS_SOURCE_DIR}/cmake/run_test.cmake + ) +endmacro(add_test_C_hdf) + diff --git a/cmake/FindTestScriptHdf.cmake b/cmake/FindTestScriptHdf.cmake new file mode 100644 index 00000000..deb2c80c --- /dev/null +++ b/cmake/FindTestScriptHdf.cmake @@ -0,0 +1,55 @@ + +SET(RUN_TEST ${CMAKE_BINARY_DIR}/run_pytriqs_for_test.sh ) +#if (TRIQS_BUILD_STATIC) +# FILE(WRITE ${RUN_TEST} "PYTHONPATH=${CMAKE_BINARY_DIR}:$PYTHONPATH ${PYTHON_INTERPRETER} $1") +# #FILE(WRITE ${RUN_TEST} "PYTHONPATH=${CMAKE_BINARY_DIR}:$PYTHONPATH ${CMAKE_BINARY_DIR}/bin/pytriqs $1") +# execute_process( COMMAND chmod u+x ${RUN_TEST} ) +#endif (TRIQS_BUILD_STATIC) + +SET(ExecutableNameForTest ${RUN_TEST}) + +# runs pytriqs script > output +# and compares output with script.output +# Example: +# add_triqs_test_script(ExampleTest) +# where ExampleTest.py is the script and ExampleTest.output is the expected output +# +macro(add_triqs_test_txt testname ) + enable_testing() + add_test(${testname} + ${CMAKE_COMMAND} + -Dname=${testname} + -Dcmd=${ExecutableNameForTest} + -Dinput=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.py + -Dreference=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output + -P ${TRIQS_SOURCE_DIR}/cmake/run_test.cmake + ) +endmacro(add_triqs_test_txt) + +# - runs python_with_DMFT script +# - compares the file named testname_output.h5 +# with the file testname.output.h5 of the source directory +# The comparison with made with h5diff_options +# all remainings arguments are the objects to which to restrict the comparison (default = no restriction) +# Example : +# add_triqs_test_hdf(ExampleTestH5 "-r" ) +# where ExampleTestH5.py produces to be compared with ExampleTestH5_output.h5 with option "-r" and for all objects +# +macro(add_triqs_test_hdf testname h5diff_options) + set(h5diff_objects ${ARGN}) # grab additionnal arguments ! + enable_testing() + add_test(${testname} + ${CMAKE_COMMAND} + -Dname=${testname} + -Dcmd=${ExecutableNameForTest} + -Dinput=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.py + -DoutputName=${testname}.output.h5 + -Dreference=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output.h5 + -DH5_DIFF_EXECUTABLE=${HDF5_DIFF_EXECUTABLE} + -DH5_DIFF_OPTIONS=${h5diff_options} + -DH5_DIFF_OBJECTS=${h5diff_objects} + -P ${TRIQS_SOURCE_DIR}/cmake/run_test.cmake + ) +endmacro(add_triqs_test_hdf) + + diff --git a/cmake/FindTriqsMacros.cmake b/cmake/FindTriqsMacros.cmake new file mode 100644 index 00000000..6e49e9d6 --- /dev/null +++ b/cmake/FindTriqsMacros.cmake @@ -0,0 +1,15 @@ + +# add_all_subdirectories_with_cmakelist : include all subdirectory to current path +# which contains a CMakeLists.txt file... +# rational : automatize inclusion when projects are splitted & merged .... + +macro (add_all_subdirectories_with_cmakelist) + SET( print_decal_sub_dir "${print_decal_sub_dir} ") + FILE(GLOB ALLSUBS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} */CMakeLists.txt) + foreach ( f ${ALLSUBS}) + get_filename_component(d ${f} PATH) + #MESSAGE(STATUS "${print_decal_sub_dir}## Including subdirectory : ${d}") + add_subdirectory(${d}) + endforeach ( f ${ALLSUBS}) +endmacro (add_all_subdirectories_with_cmakelist) + diff --git a/cmake/FindTriqsTest.cmake.in b/cmake/FindTriqsTest.cmake.in new file mode 100644 index 00000000..2a4a418b --- /dev/null +++ b/cmake/FindTriqsTest.cmake.in @@ -0,0 +1,101 @@ + +# runs python_with_DMFT script > output +# and compares output with script.output +# Example: +# triqs_add_triqs_test_script(ExampleTest) +# where ExampleTest.py is the script and ExampleTest.output is the expected output +# +macro(triqs_add_test_C_simple testname ) + enable_testing() + + if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output) + + file( COPY ${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + + add_test(${testname} + ${CMAKE_COMMAND} + -Dname=${testname}${ARGN} + -Dcmd=${CMAKE_CURRENT_BINARY_DIR}/${testname}${ARGN} + -Dreference=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output + -P @CMAKE_INSTALL_PREFIX@/share/triqs/cmake/run_test.cmake + ) + + else (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output) + add_test(${testname}${ARGN} ${testname}${ARGN} ) + endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output) + +endmacro(triqs_add_test_C_simple) + + +macro(triqs_add_test_C_hdf testname h5diff_options) + set(h5diff_objects ${ARGN}) # grab additionnal arguments ! + enable_testing() + add_test(${testname} + ${CMAKE_COMMAND} + -Dname=${testname}${ARGN} + -Dcmd=${CMAKE_CURRENT_BINARY_DIR}/${testname}${ARGN} + -DoutputName=${testname}.output.h5 + -Dreference=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output.h5 + -DH5_DIFF_EXECUTABLE=${TRIQS_HDF5_DIFF_EXECUTABLE} + -DH5_DIFF_OPTIONS=${h5diff_options} + -DH5_DIFF_OBJECTS=${h5diff_objects} + -P @CMAKE_INSTALL_PREFIX@/share/triqs/cmake/run_test.cmake + ) +endmacro(triqs_add_test_C_hdf) + + +SET(RUN_TEST ${CMAKE_BINARY_DIR}/run_pytriqs_for_test.sh ) +#if (TRIQS_BUILD_STATIC) +# FILE(WRITE ${RUN_TEST} "PYTHONPATH=${CMAKE_BINARY_DIR}:$PYTHONPATH ${PYTHON_INTERPRETER} $1") +# #FILE(WRITE ${RUN_TEST} "PYTHONPATH=${CMAKE_BINARY_DIR}:$PYTHONPATH ${CMAKE_BINARY_DIR}/bin/pytriqs $1") +# execute_process( COMMAND chmod u+x ${RUN_TEST} ) +#endif (TRIQS_BUILD_STATIC) + +SET(ExecutableNameForTest ${RUN_TEST}) + +# runs pytriqs script > output +# and compares output with script.output +# Example: +# triqs_add_triqs_test_script(ExampleTest) +# where ExampleTest.py is the script and ExampleTest.output is the expected output +# +macro(triqs_add_triqs_test_txt testname ) + enable_testing() + add_test(${testname} + ${CMAKE_COMMAND} + -Dname=${testname} + -Dcmd=${ExecutableNameForTest} + -Dinput=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.py + -Dreference=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output + -P @CMAKE_INSTALL_PREFIX@/share/triqs/cmake/run_test.cmake + ) +endmacro(triqs_add_triqs_test_txt) + +# - runs python_with_DMFT script +# - compares the file named testname_output.h5 +# with the file testname.output.h5 of the source directory +# The comparison with made with h5diff_options +# all remainings arguments are the objects to which to restrict the comparison (default = no restriction) +# Example : +# triqs_add_triqs_test_hdf(ExampleTestH5 "-r" ) +# where ExampleTestH5.py produces to be compared with ExampleTestH5_output.h5 with option "-r" and for all objects +# +macro(triqs_add_triqs_test_hdf testname h5diff_options) + set(h5diff_objects ${ARGN}) # grab additionnal arguments ! + enable_testing() + add_test(${testname} + ${CMAKE_COMMAND} + -Dname=${testname} + -Dcmd=${ExecutableNameForTest} + -Dinput=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.py + -DoutputName=${testname}.output.h5 + -Dreference=${CMAKE_CURRENT_SOURCE_DIR}/${testname}.output.h5 + -DH5_DIFF_EXECUTABLE=${TRIQS_HDF5_DIFF_EXECUTABLE} + -DH5_DIFF_OPTIONS=${h5diff_options} + -DH5_DIFF_OBJECTS=${h5diff_objects} + -P @CMAKE_INSTALL_PREFIX@/share/triqs/cmake/run_test.cmake + ) +endmacro(triqs_add_triqs_test_hdf) + + + diff --git a/cmake/TRIQSConfig.cmake.in b/cmake/TRIQSConfig.cmake.in new file mode 100644 index 00000000..696b7a12 --- /dev/null +++ b/cmake/TRIQSConfig.cmake.in @@ -0,0 +1,101 @@ +# version +set(TRIQS_VERSION @TRIQS_VERSION@) +set(TRIQS_GIT_HASH @TRIQS_GIT_HASH@) + +#definitions +set(TRIQS_CXX_DEFINITIONS @TRIQS_CXX_DEFINITIONS@) + +# Includes +set(TRIQS_INCLUDE @CMAKE_INSTALL_PREFIX@/include) + +set(TRIQS_INCLUDE_BOOST @BOOST_INCLUDE_DIR@) +set(TRIQS_INCLUDE_MPI @TRIQS_INCLUDE_MPI@) +set(TRIQS_INCLUDE_PYTHON @TRIQS_INCLUDE_PYTHON@) +set(TRIQS_INCLUDE_HDF5 @TRIQS_INCLUDE_HDF5@) +set(TRIQS_INCLUDE_FFTW @TRIQS_INCLUDE_FFTW@) +set(TRIQS_INCLUDE_GMP @TRIQS_INCLUDE_GMP@) +set(TRIQS_INCLUDE_GSL @GSL_INCLUDE_DIR@) + +# Libraries +set(TRIQS_LIBRARY -L@CMAKE_INSTALL_PREFIX@/lib -ltriqs) + +set(TRIQS_LIBRARY_BOOST @BOOST_LIBRARY@) +set(TRIQS_LIBRARY_MPI @TRIQS_LIBRARY_MPI@) +set(TRIQS_LIBRARY_PYTHON @TRIQS_LIBRARY_PYTHON@) +set(TRIQS_LIBRARY_HDF5 @TRIQS_LIBRARY_HDF5@) +set(TRIQS_LIBRARY_LAPACK @TRIQS_LIBRARY_LAPACK@) +set(TRIQS_LIBRARY_FFTW @TRIQS_LIBRARY_FFTW@) +set(TRIQS_LIBRARY_GMP @TRIQS_LIBRARY_GMP@) +set(TRIQS_LIBRARY_GSL @GSL_LIBRARIES@) + +# Misc +set(TRIQS_HDF5_DIFF_EXECUTABLE @TRIQS_HDF5_DIFF_EXECUTABLE@) + +# for people who want to quickly add everything TRIQS has detected... +set(TRIQS_LIBRARY_ALL ${TRIQS_LIBRARY} ${TRIQS_LIBRARY_BOOST} ${TRIQS_LIBRARY_PYTHON} ${TRIQS_LIBRARY_MPI} ${TRIQS_LIBRARY_HDF5} ${TRIQS_LIBRARY_LAPACK} ${TRIQS_LIBRARY_FFTW} ${TRIQS_LIBRARY_GMP} ${TRIQS_LIBRARY_GSL} ) +set(TRIQS_INCLUDE_ALL ${TRIQS_INCLUDE} ${TRIQS_INCLUDE_BOOST} ${TRIQS_INCLUDE_PYTHON} ${TRIQS_INCLUDE_MPI} ${TRIQS_INCLUDE_HDF5} ${TRIQS_INCLUDE_LAPACK} ${TRIQS_INCLUDE_FFTW} ${TRIQS_INCLUDE_GMP} ${TRIQS_INCLUDE_GSL} ) +list (REMOVE_DUPLICATES TRIQS_INCLUDE_ALL) + +# Python specific stuff +set (TRIQS_PYTHON_INTERPRETER @PYTHON_INTERPRETER@) + +# Fix the rpath +set(CMAKE_INSTALL_RPATH "@CMAKE_INSTALL_PREFIX@/lib") +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) + +message(STATUS "TRIQS : Adding C++11 compilation flags -std=c++11 ") +add_definitions( -std=c++0x) + +# Check compiler +if (NOT CMAKE_CXX_COMPILER STREQUAL "@CMAKE_CXX_COMPILER@" ) + message(FATAL_ERROR "For your own safety, you should use the same compiler as the one used to compile TRIQS !") +endif() + +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ ") + message(STATUS "TRIQS : Adding C++11 compilation flags for Os X: -stdlib=libc++ ") + else () + message( WARNING "${line_of_star}You are on Os X but your are not using clang. This is NOT recommended...${line_of_star}") + endif () +endif( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + +# This function add the target to build a python module +# +# NickName = +# ModuleName = the python name of the module +# ModuleDest = path in the pytriqs tree [ FOR INSTALLATION ONLY] IMPROVE MAKE THIS OPTIONAL (for test) +macro (triqs_cython_module NickName ModuleName) + message(STATUS "TRIQS : Preparing cython module ${NickName} with the interpreter ${TRIQS_PYTHON_INTERPRETER} ") + get_filename_component(CYTHON_EXECUTABLE_PATH ${TRIQS_PYTHON_INTERPRETER} PATH) + set(CYTHON_EXECUTABLE ${CYTHON_EXECUTABLE_PATH}/cython CACHE STRING "Path to the cython executable") + set(cython_src ${CMAKE_CURRENT_SOURCE_DIR}/${ModuleName}.pyx ) + FILE(GLOB all_pyx_src RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.pyx *.pxd ) + set(cython_wrap ${CMAKE_CURRENT_BINARY_DIR}/wrap_${NickName}_by_cython.cpp) + add_custom_command (OUTPUT ${cython_wrap} DEPENDS ${all_pyx_src} COMMAND ${CYTHON_EXECUTABLE} ${cython_src} -I ${CMAKE_CURRENT_SOURCE_DIR}/ -I@CMAKE_INSTALL_PREFIX@/include/pytriqs/ -I@CMAKE_INSTALL_PREFIX@/include/ -X embedsignature=True --cplus -o ${cython_wrap} ) + add_custom_target(cython_${NickName} ALL DEPENDS ${cython_wrap}) + + add_library(${ModuleName} MODULE ${cython_wrap} ) + 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 "") + install (TARGETS ${ModuleName} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/${ARGN} ) + endif (${ARGN} MATCHES "") + set_property (GLOBAL APPEND PROPERTY DEPENDANCE_TO_ADD triqs_${NickName} ) + +endmacro (triqs_cython_module) + + +# Also duplicate from the FindTriqsMacro.... ? Include ? +macro (triqs_add_all_subdirectories_with_cmakelist) + SET( print_decal_sub_dir "${print_decal_sub_dir} ") + FILE(GLOB ALLSUBS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} */CMakeLists.txt) + foreach ( f ${ALLSUBS}) + get_filename_component(d ${f} PATH) + #MESSAGE(STATUS "${print_decal_sub_dir}## Including subdirectory : ${d}") + add_subdirectory(${d}) + endforeach ( f ${ALLSUBS}) +endmacro (triqs_add_all_subdirectories_with_cmakelist) + + diff --git a/cmake/postinst.in b/cmake/postinst.in new file mode 100644 index 00000000..58614aea --- /dev/null +++ b/cmake/postinst.in @@ -0,0 +1,4 @@ +#!/bin/sh +echo "Compiling the .py files into .pyc" +@ALPS_PYTHON_INTERPRETER@ -mcompileall /usr/@TRIQS_PYTHON_LIB_DEST@ 2>1 > /dev/null + diff --git a/cmake/prerm.in b/cmake/prerm.in new file mode 100644 index 00000000..4b96a1a0 --- /dev/null +++ b/cmake/prerm.in @@ -0,0 +1,4 @@ +#!/bin/sh +find /usr/@TRIQS_PYTHON_LIB_DEST@ -name "*.pyc" -exec rm {} \; +#find /usr/@TRIQS_PYTHON_LIB_DEST@ -name "*.pyc" -exec ls -l {} \; + diff --git a/cmake/run_test.cmake b/cmake/run_test.cmake new file mode 100644 index 00000000..69fa64d0 --- /dev/null +++ b/cmake/run_test.cmake @@ -0,0 +1,63 @@ +set (output_new ${CMAKE_CURRENT_BINARY_DIR}/${name}_output) + +# hum, only a recent version of hdf5 1.8.7 ? +#SET(H5_DIFF_EXCLUDE --exclude-path=revisions --exclude-path=log_type --exclude-path=state_type) + +if (H5_DIFF_EXECUTABLE) + separate_arguments(H5_DIFF_OPTIONS) + separate_arguments(H5_DIFF_OBJECTS) + set (COM ${H5_DIFF_EXECUTABLE} ${H5_DIFF_EXCLUDE} ${H5_DIFF_OPTIONS} ${outputName} ${reference} ${H5_DIFF_OBJECTS}) +else(H5_DIFF_EXECUTABLE) + set (COM ${CMAKE_COMMAND} -E compare_files ${output_new} ${reference}) +endif (H5_DIFF_EXECUTABLE) + +message(" command for the test ${cmd} ${input}") +if (input) +execute_process( + COMMAND ${cmd} + RESULT_VARIABLE not_successful + INPUT_FILE ${input} + OUTPUT_FILE ${output_new} + ERROR_FILE ${output_new}.err + ERROR_VARIABLE err + TIMEOUT 600 + ) +else() +execute_process( + COMMAND ${cmd} + RESULT_VARIABLE not_successful + OUTPUT_FILE ${output_new} + ERROR_FILE ${output_new}.err + ERROR_VARIABLE err + TIMEOUT 600 + ) +endif() + +if(not_successful) + message(SEND_ERROR "error runing test '${name}': ${err}; command ${cmd} : shell output: ${not_successful}!") +endif(not_successful) + +MESSAGE( "About to compare with ${COM}") + +if (NOT H5_DIFF_EXECUTABLE) + # Little fix to turn -0 into 0 (--0 is not replaced) + FILE(READ ${output_new} temp) + STRING(REGEX REPLACE "([^-])-0([^.])" "\\10\\2" temp_after "${temp}") + FILE(WRITE ${output_new} ${temp_after}) +endif() + +execute_process( + COMMAND ${COM} + RESULT_VARIABLE not_successful + OUTPUT_VARIABLE out + ERROR_VARIABLE err + TIMEOUT 600 + ) + +if(not_successful) + message(SEND_ERROR "output does not match for '${name}': ${err}; ${out}; shell output: ${not_successful}!") +endif(not_successful) +#endif(output) + +#file(REMOVE ${output_new}) + diff --git a/cmake/run_test_simple.cmake b/cmake/run_test_simple.cmake new file mode 100644 index 00000000..9b6f6666 --- /dev/null +++ b/cmake/run_test_simple.cmake @@ -0,0 +1,64 @@ + +## Useless, use run_test and suppress this + +set (output_new ${CMAKE_CURRENT_BINARY_DIR}/${name}_output) + +if (H5_DIFF_EXECUTABLE) + separate_arguments(H5_DIFF_OPTIONS) + separate_arguments(H5_DIFF_OBJECTS) + set (COM ${H5_DIFF_EXECUTABLE} ${H5_DIFF_EXCLUDE} ${H5_DIFF_OPTIONS} ${outputName} ${reference} ${H5_DIFF_OBJECTS}) +else(H5_DIFF_EXECUTABLE) + set (COM ${CMAKE_COMMAND} -E compare_files ${output_new} ${reference}) +endif (H5_DIFF_EXECUTABLE) + +message(" command for the test ${cmd} ${input}") + +if (input) +execute_process( + COMMAND ${cmd} + RESULT_VARIABLE not_successful + INPUT_FILE ${input} + OUTPUT_FILE ${output_new} + ERROR_FILE ${output_new}.err + ERROR_VARIABLE err + TIMEOUT 600 + ) +else() +execute_process( + COMMAND ${cmd} + RESULT_VARIABLE not_successful + OUTPUT_FILE ${output_new} + ERROR_FILE ${output_new}.err + ERROR_VARIABLE err + TIMEOUT 600 + ) +endif() + +if(not_successful) + message(SEND_ERROR "error runing test '${name}': ${err}; command ${cmd} : shell output: ${not_successful}!") +endif(not_successful) + +MESSAGE( "About to compare with ${COM}") + +if (NOT H5_DIFF_EXECUTABLE) + # Little fix to turn -0 into 0 (--0 is not replaced) + FILE(READ ${output_new} temp) + STRING(REGEX REPLACE "([^-])-0([^.])" "\\10\\2" temp_after "${temp}") + FILE(WRITE ${output_new} ${temp_after}) +endif() + +execute_process( + COMMAND ${COM} + RESULT_VARIABLE not_successful + OUTPUT_VARIABLE out + ERROR_VARIABLE err + TIMEOUT 600 + ) + +if(not_successful) + message(SEND_ERROR "output does not match for '${name}': ${err}; ${out}; shell output: ${not_successful}!") +endif(not_successful) +endif(output) + +#file(REMOVE ${output_new}) + diff --git a/cmake/triqs_config.h.in b/cmake/triqs_config.h.in new file mode 100644 index 00000000..48604c75 --- /dev/null +++ b/cmake/triqs_config.h.in @@ -0,0 +1,18 @@ + +// DO NOT EDIT : generated by cmake + +#cmakedefine TRIQS_WITH_PYTHON_SUPPORT +#cmakedefine TRIQS_NUMPY_VERSION_LT_17 + +#cmakedefine BOOST_PP_VARIADICS + +#cmakedefine TRIQS_BIND_FORTRAN_LOWERCASE + +#cmakedefine TRIQS_WORKAROUND_INTEL_COMPILER_BUGS +#cmakedefine BOOST_MATH_DISABLE_STD_FPCLASSIFY + +#define TRIQS_GIT_HASH @GIT_HASH@ + +#define TRIQS_HOSTNAME @TRIQS_HOSTNAME@ +#define TRIQS_COMPILEDBY @TRIQS_COMPILEDBY@ + diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 00000000..c220511c --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,114 @@ + +# Should we use MathJax.... +find_package(MathJax) +if (MATHJAX_PATH) + message(STATUS "Detected MathJax at ${MATHJAX_PATH}") +else() + message(STATUS "MathJax not found automatically") + option(Sphinx_Math_Generator_MathJax " " OFF) + if (Sphinx_Math_Generator_MathJax) + set(SPHINX_MATH_GENERATOR "mathjax") + set(MATHJAX_PATH "MathJax" CACHE STRING "Path to the MathJax directory") + else (Sphinx_Math_Generator_MathJax) + set(SPHINX_MATH_GENERATOR "pngmath") + endif (Sphinx_Math_Generator_MathJax) +endif() + +# the local extensions.... +file(COPY ../foreignlibs/breathe ../foreignlibs/doxylink ../foreignlibs/mpl ../foreignlibs/autocompile DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +# The compiler flags for autocompile +set(TRIQS_LIBRARY_ALL ${TRIQS_LIBRARY_BOOST} ${TRIQS_LIBRARY_PYTHON} ${TRIQS_LIBRARY_MPI} ${TRIQS_LIBRARY_HDF5} ${TRIQS_LIBRARY_LAPACK} ${TRIQS_LIBRARY_FFTW} ${TRIQS_LIBRARY_GMP} ${TRIQS_LIBRARY_GSL} ) +set(TRIQS_INCLUDE_ALL ${TRIQS_INCLUDE_BOOST} ${TRIQS_INCLUDE_PYTHON} ${TRIQS_INCLUDE_MPI} ${TRIQS_INCLUDE_HDF5} ${TRIQS_INCLUDE_LAPACK} ${TRIQS_INCLUDE_FFTW} ${TRIQS_INCLUDE_GMP} ${TRIQS_INCLUDE_GSL} ) + +set( link_libs " ${TRIQS_LIBRARY_ALL}") +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + list (REMOVE_DUPLICATES link_libs) +endif( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +string(REPLACE "boost_for_triqs" " " TMP "${link_libs}") +string(REPLACE "debug" " " TMP "${TMP}") +string(REPLACE "optimized" " " TMP "${TMP}") + +if(BOOST_SOURCE_DIR) + set( link_boost_for_triqs "-lboost_for_triqs") + EXECUTE_PROCESS(COMMAND sh -c "ln -sf ${CMAKE_BINARY_DIR}/foreignlibs/boost/libboost_for_triqs.so ${CMAKE_CURRENT_BINARY_DIR}") +else(BOOST_SOURCE_DIR) + set( link_boost_for_triqs " ") +endif(BOOST_SOURCE_DIR) + + +set(DOC_AUTOCOMPILE_INCLUDE ${BOOST_SOURCE_DIR} ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/foreignlibs ${TRIQS_INCLUDE_ALL} ) +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(DOC_AUTOCOMPILE_LINK "-L ${CMAKE_BINARY_DIR}/foreignlibs/boost ${link_boost_for_triqs} -L ${CMAKE_BINARY_DIR}/triqs -ltriqs ${TMP} ") + set(DOC_AUTOCOMPILE_DEFINITIONS -std=c++0x -DBOOST_PP_VARIADICS=1 -stdlib=libc++ -I/System/Library/Frameworks/vecLib.framework/Versions/A/Headers) +else() + set(DOC_AUTOCOMPILE_LINK "-L ${CMAKE_BINARY_DIR}/foreignlibs/boost ${link_boost_for_triqs} -L ${CMAKE_BINARY_DIR}/triqs -ltriqs ${TMP} -Wl,-rpath=${CMAKE_CURRENT_BINARY_DIR} ") + set(DOC_AUTOCOMPILE_DEFINITIONS -std=c++0x -DBOOST_PP_VARIADICS=1 ) +endif() +set(DOC_AUTOCOMPILE_LD_LIBRARY_PATH " ${CMAKE_BINARY_DIR}/foreignlibs/boost/:${CMAKE_BINARY_DIR}/triqs ") +# to find the triqs_config.h +set(DOC_AUTOCOMPILE_DEFINITIONS ${DOC_AUTOCOMPILE_DEFINITIONS} -DTRIQS_BUILDING_LIBRARY -I ${CMAKE_BINARY_DIR}/Config ) + +# debug +#message( " Link libs ${DOC_AUTOCOMPILE_LINK}") + +EXECUTE_PROCESS(COMMAND sh -c "ln -sf ${CMAKE_BINARY_DIR}/triqs/libtriqs.so ${CMAKE_CURRENT_BINARY_DIR}") + +# Dive and find the doxygen sources +add_subdirectory(reference/c++) + +# Build the doxygen +set(DOXYGEN_HTML_OUTPUT ./html/doxy_triqs) +find_package(Doxygen REQUIRED) + +# debug +get_property(DOXYGEN_SOURCES GLOBAL PROPERTY DOXYGEN_SOURCES) +string(REPLACE ";" " " DOXYGEN_SOURCES_LIST "${DOXYGEN_SOURCES}") +#message(STATUS "Doxygen sources are ${DOXYGEN_SOURCES}") + +# Prepare the Doxyfile +configure_file(${TRIQS_SOURCE_DIR}/cmake/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + +# Generate the conf.py +FILE(GLOB_RECURSE SOURCES *.rst) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in ${CMAKE_CURRENT_BINARY_DIR}/conf.py) +EXECUTE_PROCESS(COMMAND sh -c "mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/html") +set(DOC_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}) +include(${TRIQS_SOURCE_DIR}/cmake/BuildSphinx.cmake) + +# Set dependencies +GET_PROPERTY(PYTHON_DYNAMIC_MODULES_LIST GLOBAL PROPERTY PYTHON_DYNAMIC_MODULES_LIST) +foreach (mod ${PYTHON_DYNAMIC_MODULES_LIST}) + add_dependencies(docs_sphinx ${mod}) +endforeach (mod ${PYTHON_DYNAMIC_MODULES_LIST}) +set(doxy_top ${CMAKE_CURRENT_BINARY_DIR}/doxy.log) +add_custom_command (OUTPUT ${doxy_top} DEPENDS ${DOXYGEN_SOURCES} COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile > ${doxy_top} ) +add_custom_target(docs_doxy ALL DEPENDS ${doxy_top}) +add_dependencies(docs_sphinx docs_doxy) # we must first have doxygen process the sources to link to them +add_dependencies(docs_sphinx triqs boost_for_triqs ) # add also mpi ? + +# Install +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ COMPONENT documentation DESTINATION share/doc/triqs/user_manual + FILES_MATCHING + PATTERN "*.html" + PATTERN "*.png" + PATTERN "*.js" + PATTERN "_*" + PATTERN "*.png" + PATTERN "*.gif" + PATTERN "*.xsl" + PATTERN "*.css" + PATTERN "*.pdf" + PATTERN "*.py" + PATTERN "*.txt" + PATTERN "*.bib" + PATTERN ".svn" EXCLUDE + PATTERN "CVS" EXCLUDE + ) + +# PDF documentation +if (Build_PDF_Documentation) + add_dependencies(docs_sphinx_pdf_cpp triqs boost_for_triqs ) # add also mpi ? + install(FILES ${sphinx_top_pdf} DESTINATION share/doc/triqs/) +endif() + diff --git a/doc/_templates/index.html b/doc/_templates/index.html new file mode 100644 index 00000000..689d3c15 --- /dev/null +++ b/doc/_templates/index.html @@ -0,0 +1,193 @@ +{% extends "layout.html" %} + +{% block footer %} +{{ super() }} + +{% endblock %} + + +{% set title = 'Home' %} +{% block body %} + +

User manual

+ +

TRIQS basic components:

+ + +
+ + + + + + + + + + + + + + +
+ +

Extension modules:

+ + + + + + +
+ + + +
+ +

C++ Libraries:

+ + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ +
+ +

More about the {{project}} project:

+ + + + + + +
+ + + + + + + +
+ + +{% endblock %} diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html new file mode 100644 index 00000000..70cedcb7 --- /dev/null +++ b/doc/_templates/layout.html @@ -0,0 +1,19 @@ +{% extends "!layout.html" %} + +{% block extrahead %} +{{ super() }} + +{% endblock %} + diff --git a/doc/conf.py.in b/doc/conf.py.in new file mode 100644 index 00000000..56b766c8 --- /dev/null +++ b/doc/conf.py.in @@ -0,0 +1,245 @@ +# -*- coding: utf-8 -*- +# +# TRIQS documentation build configuration file, created by +# sphinx-quickstart on Tue Sep 21 10:50:39 2010. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed automatically). +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If your extensions are in another directory, add it here. If the directory +# is relative to the documentation root, use os.path.abspath to make it +# absolute, like shown here. +#sys.path.append(os.path.abspath('.')) + +# General configuration +# --------------------- + +sys.path +=["@CMAKE_BINARY_DIR@/doc/breathe", +"@CMAKE_BINARY_DIR@/doc/mpl","@CMAKE_BINARY_DIR@/doc/autocompile", +"@CMAKE_BINARY_DIR@/doc/sandbox","@CMAKE_BINARY_DIR@/doc"] + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +#extensions = ['sphinx.ext.autodoc','sphinx.ext.pngmath'] +extensions = ['sphinx.ext.autodoc','sphinx.ext.@SPHINX_MATH_GENERATOR@','breathe','doxylink'] + +# adding support for matplotlib plots +extensions += [ + 'matplotlib.sphinxext.only_directives', + 'plot_directive', + # 'matplotlib.sphinxext.ipython_directive', + # 'ipython_console_highlighting', + # 'inheritance_diagram', + 'numpydoc'] + +extensions += ['autocompile','autorun'] + +##options for autocompile module: c++ execution +autocompile_opts = dict(compiler = "@CMAKE_CXX_COMPILER@", + link = "@DOC_AUTOCOMPILE_LINK@".replace(';',' '), + ld_library_path = "@DOC_AUTOCOMPILE_LD_LIBRARY_PATH@".replace(';',' '), + include =''.join([ " -I%s"%arg for arg in "@DOC_AUTOCOMPILE_INCLUDE@".split(';')] ), + definitions =''.join([ " %s"%arg for arg in "@DOC_AUTOCOMPILE_DEFINITIONS@".split(';')] ) + ) + +##options for autorun module: python execution +autorun_languages = {} +autorun_languages['python'] = 'python -' +autorun_languages['python_prefix_chars'] = 0 +autorun_languages['python_show_source'] = True + +autoclass_content = "both" + +#pngmath_dvipng_args = ['-gamma 1.2', '-D 150', '-bg Transparent'] +mathjax_path = "@MATHJAX_PATH@/MathJax.js?config=default" + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['@TRIQS_SOURCE_DIR@/doc/_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'contents' + +# General information about the project. +project = u'TRIQS' +copyright = u'2011, The TRIQS collaboration' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = ['build','html'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# Options for breathe extension +# ----------------------------- + +breathe_projects = { + "mc_tools":"@CMAKE_CURRENT_BINARY_DIR@/xml/", + "arrays":"@CMAKE_CURRENT_BINARY_DIR@/xml/", + } + +breathe_default_project = "mc_tools" + +# Options for doxylink extension +# ----------------------------- + +doxylink = { 'doxy' : ('@CMAKE_CURRENT_BINARY_DIR@/doxy.tag', 'doxy_triqs') } + + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +#html_style = 'default.css' +html_theme_path = ["@TRIQS_SOURCE_DIR@/doc/themes/"] +html_theme = "agogo" +#html_theme = "default" + +#html_theme_options = { "pagewidth": "80em", "documentwidth" : "60em" } + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = '@TRIQS_SOURCE_DIR@/Doc/misc/python-powered-w-200x80.png' + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +#html_static_path = ['@TRIQS_SOURCE_DIR@/doc/_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +html_additional_pages = { 'index':'index.html' } + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, the reST sources are included in the HTML build as _sources/. +#html_copy_source = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'TRIQSdoc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +latex_documents = [ + ('contents', 'TRIQS.tex', ur'TRIQS Documentation', + ur'2011, The TRIQS collaboration', 'manual'), + ] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True + + + diff --git a/doc/contents.rst b/doc/contents.rst new file mode 100644 index 00000000..23d562e5 --- /dev/null +++ b/doc/contents.rst @@ -0,0 +1,14 @@ +Table of contents +================= + +.. toctree:: + :maxdepth: 3 + + overview + installation/install + tutorials/contents + reference/python/contents + reference/c++/contents + +.. + reference/applications/contents diff --git a/doc/faq/faq.rst b/doc/faq/faq.rst new file mode 100644 index 00000000..92d11de2 --- /dev/null +++ b/doc/faq/faq.rst @@ -0,0 +1,21 @@ +.. index:: FAQ + +Frequently asked questions +=========================== + +Documentation +------------- + +.. toctree:: + :maxdepth: 1 + + typeerrorunicode + + +Installation +------------ + +.. toctree:: + :maxdepth: 1 + + relativedirforboost diff --git a/doc/faq/relativedirforboost.rst b/doc/faq/relativedirforboost.rst new file mode 100644 index 00000000..8b1f3959 --- /dev/null +++ b/doc/faq/relativedirforboost.rst @@ -0,0 +1,7 @@ +Cannot find source file "archive_exception.cpp" +=============================================== + +If you get this message when you call cmake, it is probably because you gave a +*relative* path for the boost sources ``BOOST_SOURCE_DIR`` (like +``../../../boost_1_47``). You must use an absolute path for +``BOOST_SOURCE_DIR``, like ``/path/to/boost_1_47``. diff --git a/doc/faq/typeerrorunicode.rst b/doc/faq/typeerrorunicode.rst new file mode 100644 index 00000000..9427f0a2 --- /dev/null +++ b/doc/faq/typeerrorunicode.rst @@ -0,0 +1,7 @@ +TypeError: coercing to Unicode: need string or buffer, dict found +----------------------------------------------------------------- + +If this appears when the documentation is produced, just delete the +.matplotlib directory in your home and start again. The reason for +the bug is that different versions of matplotlib produce different +formats for font caches that are not compatible diff --git a/doc/installation/Ubuntu.rst b/doc/installation/Ubuntu.rst new file mode 100644 index 00000000..0f8c2c6a --- /dev/null +++ b/doc/installation/Ubuntu.rst @@ -0,0 +1,73 @@ +.. index:: Ubuntu + +.. _Ubuntu : + +.. highlight:: bash + +Installation on Ubuntu (12.04 LTS) +#################################################### + +TRIQS can be installed on Ubuntu 12.04 LTS. + +NB : Ubuntu 12.10: there is a bug in Ubuntu 12.10 (hdf5 compiled without hdf5 support). +On Ubuntu 12.10, you have to recompile hdf5. The problem has been reported and will be fixed in 13.04. + +#. Install the following packages which are necessary to build TRIQS and use it:: + + sudo apt-get install cmake git g++ libgfortran3 gfortran openmpi-bin openmpi-common \ + openmpi-checkpoint libopenmpi-dev libblas-dev liblapack-dev libfftw3-dev libgmp-dev \ + hdf5-tools libhdf5-serial-dev python-h5py libboost1.48-all-dev python-dev \ + python-numpy python-scipy python-virtualenv python-matplotlib doxygen\ + python-tornado python-zmq + +#. Download the code:: + + git clone git://github.com/TRIQS/TRIQS.git path_to_triqs_sources + +#. Create a build directory (different from the TRIQS source directory nor a subdirectory thereof) :: + + mkdir triqs_build && cd triqs_build + +#. Configure :: + + cmake path_to_triqs_sources -DCMAKE_INSTALL_PREFIX=path_to_install_directory + + NB: the install directory is optional and defaults to `triqs_build/INSTALL_DIR`. It is + however usually a good idea to have an install directory outside `triqs_build` (after + a successful installation `triqs_build` can be deleted). The cmake call should end with:: + + -- Build files have been written to: *path_to_triqs_build* + + OPTIONAL: To install the documentation, install Sphinx and doxygen: :: + + sudo easy_install -U Sphinx + sudo apt-get install doxygen + + and add:: + + -DBuild_Documentation=ON + + to the above cmake command. + +#. Build TRIQS, test it and install it with (N being the number of cores of your machine) :: + + make -jN && make test && make -jN install + + NB: the tests SingleSite and CDMFT-v2 take longer than the other ones (30s to 1 min). + +#. If you use Wien2TRIQS, please complete the installation as described :ref:`here `. + + + + +#. You can now :ref:`start ... ` + +#. Optionally, you may be interested in: + + * How to *simply* upgrade the ipython notebook with :ref:`virtualenv ` to the latest version? + + * How to use the nice :ref:`clang ` C++ compiler? + + * How to use :ref:`Intel ` C++ compiler? + +.. warning:: For the branch 1.0, you need the latest version of Cython (>=.17, downloadable on Cython.org). If Cython is not found, specify the location of the executable with the option -DCYTHON_EXECUTABLE. diff --git a/doc/installation/changelog.rst b/doc/installation/changelog.rst new file mode 100644 index 00000000..f63678a5 --- /dev/null +++ b/doc/installation/changelog.rst @@ -0,0 +1,16 @@ +Changelog between releases +======================================= + +v0.9 -> current +------------------ + +* Now use to C++11. + + +v0.8 -> v0.9 +------------- + +* To be written + + + diff --git a/doc/installation/clang.rst b/doc/installation/clang.rst new file mode 100644 index 00000000..090f9222 --- /dev/null +++ b/doc/installation/clang.rst @@ -0,0 +1,47 @@ +.. index:: clang + +.. _clang: + +.. highlight:: bash + +Using clang compiler +========================== + +clang++ compiler is **highly recommended** for anyone developing in C++ since : + +* It has very nice and useful error messages, much nicer than intel or gcc. +* It implements most of the new C++11 standard. + +clang/llvm is now the standard compiler on OS X, but it is open source +and works very well on linux too. + +Version +--------- + +* TRIQS compiles on clang, version 3.0 and later. + +* Recommended version is 3.1 (latest stable). + +Get and install clang +------------------------ + +If you have precompiled version in the `LLVM dowload page `_, +use it. E.g. on Ubuntu 12.04 LTS :: + + wget http://llvm.org/releases/3.1/clang+llvm-3.1-x86_64-linux-ubuntu_12.04.tar.gz + tar xzf clang+llvm-3.1-x86_64-linux-ubuntu_12.04 + sudo mv clang+llvm-3.1-x86_64-linux-ubuntu_12.04 /opt/clang + # add /opt/clang/bin to your path + # use clang++... + +Otherwise, it is in fact quite easy to compile clang from source, just follow the +`instructions `_. + +Usage +-------------- + +In the current version, when compiling with clang, say (provided clang++ is your path of course) :: + + CXX=clang++ cmake path_to_TRIQS_source_directory .... others options ... + + diff --git a/doc/installation/dependencies.rst b/doc/installation/dependencies.rst new file mode 100644 index 00000000..c79086ff --- /dev/null +++ b/doc/installation/dependencies.rst @@ -0,0 +1,68 @@ +.. index:: dependencies + +.. _dependencies: + +A complete list of dependencies +================================== + +TRIQS is built upon several python and C++ libraries, which, if not present already in your system, can be freely downloaded and installed. +All the libraries and tools used by TRIQS are listed in the table : + +================== ================ ================================================================================ +Libraries/tools Version Comment +================== ================ ================================================================================ +mpi e.g., openmpi Parallelism + + Since standard linux distributions (and macports on OS X) + now provides openmpi, even on laptops, we avoid the unnecessary complication + of maintaining a non parallel version of TRIQS +fftw >= 3.2 Fourier transform +boost >= 1.49 C++ librairies +hdf5 >= 1.8.0 File storage system. Important: the *serial* version must be installed +python* >= 2.6.5 +scipy* python mathematical library +numpy* python scientific library +h5py* python interface to hdf5 library +sphinx* >= 1.0.1 python documentation tools (to compile documentation) +pyparsing* Tool for sphinx (to compile documentation) +matplotlib* >= 0.99 python 2D plotting library +cython >=0.17 [DEVELOPERS ONLY] +================== ================ ================================================================================ + + \* designates the libraries included in the Enthought python distribution. + +C++11 +-------- + +The current version of TRIQS use the new C++11 standard, and therefore require a recent C++ compiler. + +Tested compilers include : + +* g++ 4.6.3, 4.7 +* clang++ 3.1 +* icc 13.0 + +Note that older compilers will *never* be supported for current and future version of TRIQS. + +Older releases may accept older compilers. + +F90 +------- +For the Wien2TRIQS interface only. + +Tested compilers include : + +* ifort +* gfortran + +Boost +-------------------------- + +The boost library is often upgraded, and it is rare to have the correct version in your distribution. TRIQS installation process offers two choices : + + * Recommended choice: As explained in the :ref:`page above `, you can download simply the latest *sources* and TRIQS will do all the job for you by compiling the pieces of boost that are needed in a little boost_for_triqs library. + + * OR you can include and link with an installed boost if the version if high enough as discussed in :ref:`install_options`. + + + diff --git a/doc/installation/get_started.rst b/doc/installation/get_started.rst new file mode 100644 index 00000000..0a448193 --- /dev/null +++ b/doc/installation/get_started.rst @@ -0,0 +1,34 @@ + + +.. _install_scheme: +.. _get_started: + +.. highlight:: bash + +Getting started +==================== + +* After the installation, provided that the tests have passed successfully, + TRIQS has been installed using the standard UNIX scheme: + + * executables in :file:`path_to_install_directory/bin`. + + * python modules in :file:`path_to_install_directory/lib/pytriqs`. + + * documentation in :file:`path_to_install_directory/share`. + + * C++ libraries in :file:`path_to_install_directory/include` and :file:`path_to_install_directory/lib/triqs`. + +* Add ``path_to_install_directory/bin`` to your path... + +* Just launch :: + + ipytriqs my_script.py + + Or to get the notebook :: + + ipytriqs_notebook + + +* You can now proceed to the tutorial .... + diff --git a/doc/installation/install.rst b/doc/installation/install.rst new file mode 100644 index 00000000..ad078e41 --- /dev/null +++ b/doc/installation/install.rst @@ -0,0 +1,49 @@ +.. index:: installation steps + +.. highlight:: bash + +.. _installation: + +Installation +============ + +* TRIQS is hosted on **GitHub**, where you can : + + * Download `the current version `_ (recommended) :: + + git clone git://github.com/TRIQS/TRIQS.git path_to_triqs_sources + + NB : this version is normally never broken (developments are done elsewhere). + + * Download `an older release `_, which may require less recent versions of compilers, libs... + + * Use the GitHub *Issues* tracker for any problem, questions. + + *Please do NOT contact the developers directly by email* + +Complete installation instructions for standard systems +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. toctree:: + :maxdepth: 1 + + Ubuntu + linux + install_on_osx_lion + +Details +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. toctree:: + :maxdepth: 1 + + wien2k_inst + dependencies + python + clang + intel + install_options + get_started + changelog + + diff --git a/doc/installation/install_on_osx_lion.rst b/doc/installation/install_on_osx_lion.rst new file mode 100644 index 00000000..86772be8 --- /dev/null +++ b/doc/installation/install_on_osx_lion.rst @@ -0,0 +1,113 @@ +.. index:: install_on_osx_lion + +.. _install_on_osx_lion: +.. highlight:: bash + +Installation on Mac OS X [Mountain Lion] +============================================== + +This installation guide may work for older versions of Mac OS X. However, previous versions of Mac OS X are not supported. + +NB: The installation of TRIQS under previous versions of OS X requires installing clang (via Xcode) or gcc 4.7 (via MacPorts). +On Mountain Lion, clang (llvm) replaces gcc 4.2 as the default C++ compiler. + +We strongly recommend the following installation procedure, which provides a clean way to set up all dependencies, so that all +of them are compatible with each other. Only the installation via homebrew is supported for the Mac. + +Installation of the dependencies +________________________________ + +1. Install `homebrew `_. + + Run ``brew doctor`` and resolve potential conflicts before continuing. + +2. Install XCode (directly from the Mac store). In Preferences/Downloads, install "Command Line tools". + +3. Install several packages which are needed: :: + + brew install cmake + brew install gfortran + brew install --enable-cxx hdf5 + brew install gsl + brew install fftw + brew install open-mpi + brew install zmq + brew install python + brew install doxygen + +4. Now install virtualenv: :: + + pip install virtualenv + virtualenv mypython + +Using virtualenv provides a clean way to set up a different python environment for each user. +The first line in the instructions above installs the package and the second creates the virtual +environment, which is created in ``$HOME/mypython``. +Make sure to permanently add (prepend) ``$HOME/mypython/bin`` to your path by adding :: + + export PATH = $HOME/mypython/bin:$PATH + +to your ``.bashrc file`` (assuming bash). Within a new shell, check that + + which python + which pip + which easy_install + +yield the ones located in ``$HOME/mypython``. + +5. Install the required python packages: :: + + pip install numpy + pip install h5py + pip install scipy + pip install git+https://github.com/matplotlib/matplotlib.git#egg=matplotlib-dev + pip install tornado + pip install pyzmq + pip install ipython + pip install cython + +6. If you wish to compile the documentation locally, install sphinx, its dependencies and mathjax: :: + + pip install sphinx + easy_install pyparsing==1.5.7 + git clone git://github.com/mathjax/MathJax.git MathJax + +NB : you need pyparsing <=1.5.7 since apparently v.2.0 works only for python 3. + +7. Download the latest `sources of boost `_ and untar them into a directory ``BOOST_SRC``. + + +TRIQS installation +__________________ + +#. Download the TRIQS sources: :: + + git clone git@github.com:TRIQS/TRIQS.git TRIQS_src + +#. Generate a Makefile using cmake: :: + + cmake TRIQS_src -DBOOST_SOURCE_DIR=BOOST_SRC + +#. Compile TRIQS, its tests and install it into INSTALL_DIR (default) (N is the number of cores of your mac): :: + + make -jN && make test && make install + +#. If you use Wien2TRIQS, please complete the installation as described :ref:`here `. + +Possible issues: +________________ + +If you encounter the following error: :: + + /usr/local/include/ft2build.h:56:38: error: freetype/config/ftheader.h: No such file or directory + +in the installation of matplotlib, you need to pass the proper include path. Locate the freetype directory +with the header file and pass the include path through ``CPPFLAGS``: :: + + CPPFLAGS=-I/usr/X11/include/freetype2/ pip install git+https://github.com/matplotlib/matplotlib.git#egg=matplotlib-dev + + + + + + diff --git a/doc/installation/install_options.rst b/doc/installation/install_options.rst new file mode 100644 index 00000000..bc5ad6d5 --- /dev/null +++ b/doc/installation/install_options.rst @@ -0,0 +1,106 @@ +.. index:: install_options + +.. highlight:: bash + +.. _install_options: + +Customizing installation : cmake options +---------------------------------------------------- + +Specifying the compiler or compile/link flags +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To specify the compiler with cmake one may use the CXX, CXXFLAGS variables, e.g. :: + + CXX=clang++ CXXFLAGS cmake path_to_TRIQS_source_directory ..... + +Customize the installation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can then customize the installation options using the :program:`ccmake` program:: + + ccmake . + +This opens an interface with your main installation options shown :: + + BUILD_SHARED_LIBS ON + Build_CTHyb ON + Build_Documentation OFF + Build_HubbardI ON + Build_Triqs_General_Tools_Test ON + Build_Wien2k ON + CMAKE_INSTALL_PREFIX /home/parcolle/BUILD2/Triqs_dynamic/INSTALL_DIR + Install_dev OFF + LAPACK_LIBS /usr/lib/liblapack.so;/usr/lib/libblas.so;/usr/lib/libpthread.so;/usr/lib/libblas.so + PYTHON_INTERPRETER /usr/bin/python + +You can for instance change the following options: + + * ``CMAKE_INSTALL_PREFIX``: This is the directory :file:`path_to_TRIQS_install_directory` where you want to install TRIQS. + * ``Build_CTHyb``: Build the continuous-time hybridization impurity solver. + * ``Build_HubbardI``: Build a simple HubbardI solver. + * ``Build_Wien2k``: Build the interface to **WIEN2K**. + * ``Build_Documentation``: Get the documentation locally in :file:`path_to_TRIQS_install_directory/share/doc`. + +You may change all other installation options (like locations of libraries, the choice of compilers, etc.) in the advanced mode, by typing 't' after having opened the *ccmake* interface. + +After having corrected your options you may build, test and install TRIQS as described in :ref:`installation`. + +.. _install_without_boost: + +Installation with your own version of boost [-DBOOST_INSTALL_DIR=...] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you have a sufficiently recent version of boost already installed in your system you may +link TRIQS with it instead of compiling a new version of boost from sources. + +In this case, the cmake instruction is :: + + cmake path_to_TRIQS_source_directory -DBOOST_INSTALL_DIR=root_path_to_Boost_installation .... + + +The cmake option `DBOOST_INSTALL_DIR` is the path to the **boost** libraries. +The default value is : + + * BOOST_INSTALL_DIR : /usr + +So if boost is at the right place, you can just say:: + + cmake path_to_TRIQS_source_directory + +**Obviously, you should not specify `DBOOST_SOURCE_DIR` in this case!** +.. _static_dyn : + +Static versus dynamic linking [-DBUILD_SHARED_LIBS=OFF] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +TRIQS can be compiled in two different ways: + +* **dynamic linking** [default] : + + This is the standard python procedure and the default choice. + All the C++ codes are compiled in shared libraries and loaded dynamically at runtime by the python interpreter. + + With this technique however, you have to properly set the PYTHONPATH environment variable to the TRIQS installation directory in order + for python to be able to find the module. To avoid errors, TRIQS provides a + tiny script :file:`path_to_TRIQS_install_directory/bin/pytriqs` that sets up this variable for you and launch the python interpreter. + +* **static linking** : + + An alternative is to compile a new interpreter statically. + + Here the C++ modules are linked with libpython2.x.a to create a *new python interpreter* :file:`path_to_TRIQS_install_directory/bin/pytriqs` + that contains these modules as *built-in* modules. + + Though it is not as standard and extensible as the dynamic linking, this technique has several advantages : + + * It avoids opening dynamic libs, which simplifies code profiling for example. + * It may be more stable on some cluster machines (the boost.mpi modules in this case is also linked statically). + +In any case, both the scripts and the way to call them remain the same in both cases:: + + pytriqs myscript.py + +The choice is made with the cmake option :: + + -DBUILD_SHARED_LIBS=OFF/ON diff --git a/doc/installation/intel.rst b/doc/installation/intel.rst new file mode 100644 index 00000000..e5dcc166 --- /dev/null +++ b/doc/installation/intel.rst @@ -0,0 +1,54 @@ +.. index:: icc + +.. _icc: + +.. highlight:: bash + +Using Intel icc compiler +========================== + +While less user friendly than clang, Intel compilers are usually recommended on some machines +because of optimisation. + +Version +--------- + +The current version of TRIQS compiles only on Intel C++ version 13.0 +(because of the lack of C++11 support in previous versions). + +NB: previous releases (<= v0.9 compiles on icc >= 11). + +Usage +------------- + +To compile TRIQS, you will need : + +* a new and patched version of boost 1.51 (because of a stupid C++11 issue in one file...). + + PROVIDE IT WITH THE LINK ... + +* to pass the option to the compiler :: + + -DBOOST_MATH_DISABLE_STD_FPCLASSIFY + + e.g. in configuring:: + + CXX=icc CXXFLAGS="-DBOOST_MATH_DISABLE_STD_FPCLASSIFY" cmake path_to_triqs_sources ...... + + .. warning:: Do it or tests will fail and computations will be WRONG + + To be written : link to the ticket. + +Caveats +-------------- + +* icc does not provide its own implementation of the standard library + (given the price, it is quite disappointing). + So it uses gcc's standard lib. + It must use gcc 4.6 or 4.7. + +* Linking with mkl is always a mess.... + + TO BE WRITTEN ... + + diff --git a/doc/installation/ipython.rst b/doc/installation/ipython.rst new file mode 100644 index 00000000..c3a0af40 --- /dev/null +++ b/doc/installation/ipython.rst @@ -0,0 +1,24 @@ +.. index:: ipython + +ipython and the ipython notebook +-------------------------------- + +`ipython `_ is a more user-friendly version of python with an enhanced interactive shell, which is specially useful +in conjunction with matplotlib. + +If :program:`ipython` is installed on your machine, it will be automatically detected by the TRIQS installation process. +A second script named `ipytriqs` will be generated along `pytriqs`, where the standard python shell is replaced by the ipython one. + + +IPython notebook +^^^^^^^^^^^^^^^^ + +TRIQS is compatible with the great new IPython notebook (ipython 0.12), which is a notebook-style web interface to IPython and can be started withe command ipython notebook. + +If you wish to install the notebook: + +* The simplest is to use an Enthought distribution or Ubuntu 12.10. + +* Use the shell ipytriqs_notebook in the directory you want to work. + +* NB : example of notebooks are provided in the notebook sudirectory. diff --git a/doc/installation/linux.rst b/doc/installation/linux.rst new file mode 100644 index 00000000..d8dea646 --- /dev/null +++ b/doc/installation/linux.rst @@ -0,0 +1,51 @@ +.. index:: Linux + +.. _Linux: + +.. highlight:: bash + +Installation on a generic Linux distribution +####################################################### + +TRIQS has been installed successfully on several distributions. + +#. Download the code (this is for the current development version) :: + + git clone git://github.com/TRIQS/TRIQS.git path_to_triqs_sources + +#. Download the `sources of boost `_ and untar them into ``path_to_boost_sources``. + **Don't compile boost**. + +#. Create a build directory (different from the TRIQS source directory nor a subdirectory thereof) :: + + mkdir triqs_build && cd triqs_build + +#. Configure :: + + cmake path_to_triqs_sources -DBOOST_SOURCE_DIR=path_to_boost_sources \ + -DCMAKE_INSTALL_PREFIX=path_to_install_directory + + [NB : the install directory is optional, the default value is `triqs_build/INSTALL_DIR`] + + Successful run of cmake will finish with :: + + -- Build files have been written to: *path_to_triqs_build* + +#. Build TRIQS, test it and install it with (N being the number of cores of your machine) :: + + make -jN && make test && make -jN install + + [NB : the tests SingleSite and CDMFT-v2 take longer than the other ones (30s to 1 min) ]. + +#. If you use Wien2TRIQS, please complete the installation as described :ref:`here `. + +#. You can now :ref:`start ... ` + +#. Optionally, you can be interested in : + + * How to *simply* upgrade the ipython notebook with :ref:`virtualenv ` to the latest version ? + + * How to use the nice :ref:`clang ` C++ compiler ? + + * How to use :ref:`Intel ` C++ compiler ? + diff --git a/doc/installation/python.rst b/doc/installation/python.rst new file mode 100644 index 00000000..8db52f03 --- /dev/null +++ b/doc/installation/python.rst @@ -0,0 +1,66 @@ +.. _python_install: + +Python and the scientific python tools +==================================================== + +On some machines, not all the necessary scientific python tools are present +(e.g. old distribution, computation centers, etc....), or not in the right version. + +There is a way to efficiently solve this issue (other than recompiling your own python, and +all the libs, which is painful) and specially **avoiding any upgrade on your system** (which +is crucial on cluster machines e.g.). + +.. _virtualenv: +.. highlight:: bash + +Using virtualenv to install/upgrade some python packages locally +---------------------------------------------------------------------------- + +In the frequent cases where only one or two packages are missing, there is a simple solution +called virtualenv. + +Principle +^^^^^^^^^^^^ + +virtualenv is a python package that allow you to install in your home a simple copy (or mirror) +or python, and install and upgrade some packages for you, without touching the systems. + +.. warning:: This works as long as the other dependencies of the packages on e.g. C++ libraries are satisfied. + +Usage +^^^^^^^^ + +* First install virtualenv, or ask the system manager to do it. + On ubuntu :: + + sudo apt-get install python-virtualenv + +* To create a new python in your home, do e.g. :: + + virtualenv ~/.my_python --system-site-packages + + This create in ~/.my_python a clone of the python of the system, with its packages. + + You can then use it with :: + + ~/.my_python/bin/python + +* To make this your default python, just add in your ~/.bash_aliases (or bashrc) :: + + source $HOME/.my_python/bin/activate + + Then (reopen your terminal ...) :: + + which python + + should return typically:: + + /home/ME/.my_python/bin/python + +* You can install any python package for this local python installation, e.g. :: + + easy_install --upgrade ipython + + and you have the latest ipython notebook.... + + diff --git a/doc/installation/wien2k_inst.rst b/doc/installation/wien2k_inst.rst new file mode 100644 index 00000000..aa337cb7 --- /dev/null +++ b/doc/installation/wien2k_inst.rst @@ -0,0 +1,27 @@ +.. index:: wien2k_inst + +.. _wien2k_inst: + +Complete the installation of Wien2TRIQS (all platforms) +------------------------------------------------------------- + +If you choose to install the Wien2TRIQS interface to the Wien2K package for doing DMFT calculations of +realistic systems, you need take the last steps manually since Wien2k installation is not standard on all machines. +During TRIQS installation several files will be will be put into :: + + path_to_TRIQS_install_directory/share/triqs/Wien2k_SRC_files/SRC_templates + +Those files are:: + * :file:`case.cf_f_mm2` and :file:`case.cf_p_cubic` containing matrices for the complex->cubic transformation of the local angular basis + + * :file:`case.indmftpr` is a template for the input file needed by the :program:`dmftproj` program. This program constructs a set of localized orbitals representing correlated states. + +These files then have to be copied manually to :file:`path_to_Wien2k/SRC_templates`, where :file:`path_to_Wien2k` is the path to Wien2K main directory. + +When building the Wien2k extension module, TRIQS will compile :program:`dmftproj` and install it into :file:`path_to_TRIQS_install_directory/bin`. + +In addition, :file:`path_to_Wien2k/SRC_templates` also contains :program:`run_triqs` and :program:`runsp_triqs` scripts for running Wien2k+DMFT fully self-consistent calculations. These files should be copied to :file:`path_to_Wien2k`. + +You will also need to insert manually a correct call of :file:`pytriqs` into these scripts using an appropriate for your system MPI wrapper (mpirun, mpprun...), if needed. Search for *pytriqs* within the scripts to locate the appropriate place for inserting the :file:`pytriqs` call. + +Finally, you will have to change the calls to :program:`python_with_DMFT` to :program:`pytriqs` in the Wien2k :file:`path_to_Wien2k/run*` files. diff --git a/doc/license/collaboration.rst b/doc/license/collaboration.rst new file mode 100644 index 00000000..4d6c6a26 --- /dev/null +++ b/doc/license/collaboration.rst @@ -0,0 +1,71 @@ +.. index:: TRIQS collaboration + +.. _collaboration: + +The TRIQS collaboration +======================== + +TRIQS core +---------- + +Basic components and python libraries +..................................... + +**Main developers**: M. Ferrero, O. Parcollet + +**Contributors**: L. Boehnke (Legendre Green's functions) + + +C++ ``triqs::arrays`` library +............................. + +**Developer**: O. Parcollet + + +Quantum impurity solvers +------------------------- + +Continuous-time quantum Monte Carlo +................................... + +The CTQMC algorithm implemented in TRIQS is based on a hybridization expansion +of the partition function as described in references [#ctqmc1]_ and [#ctqmc2]_. +The computation of the imaginary-time Green's function has been improved with +the use of Legendre polynomials following reference [#ctqmc3]_. + +**Main developers**: M. Ferrero, O. Parcollet + +**Contributors**: L. Boehnke (measures in Legendre basis) + +**Related papers**: + +.. [#ctqmc1] `P. Werner, A. Comanac, L. de’ Medici, M. Troyer, and A. J. Millis, Phys. Rev. Lett. 97, 076405 (2006) `_ (:download:`bibtex file `) +.. [#ctqmc2] `P. Werner and A. J. Millis, Phys. Rev. B 74, 155107 (2006) `_ (:download:`bibtex file `) +.. [#ctqmc3] `L. Boehnke, H. Hafermann, M. Ferrero, F. Lechermann, and O. Parcollet, Phys. Rev. B 84, 075145 (2011) `_ (:download:`bibtex file `) + +Hubbard I +.......... + +**Main developer**: L. Pourovskii + + +Wien2TRIQS +----------------- + +The developement of an interface between the Wien2k electronic structure +package and TRIQS has been motivated by a scientific collaboration between the +research groups of Antoine Georges, Silke Biermann (Ecole Polytechnique), +Olivier Parcollet (CEA Saclay). A first step has been the definition of the +framework and the construction of the projective Wannier functions as input for +the DMFT calculations [#wien2k1]_. This has been followed by the introduction +of full charge self-consistency [#wien2k2]_, necessary for total energy +calculations. + +**Developers**: M. Aichhorn, L. Pourovskii, V. Vildosola, C. Martins + +**Related papers**: + +.. [#wien2k1] `M. Aichhorn, L. Pourovskii, V. Vildosola, M. Ferrero, O. Parcollet, T. Miyake, A. Georges, and S. Biermann, Phys. Rev. B 80, 085101 (2009) `_ (:download:`bibtex file `) +.. [#wien2k2] `M. Aichhorn, L. Pourovskii, and A. Georges, Phys. Rev. B 84, 054529 (2011) `_ (:download:`bibtex file `) + + diff --git a/doc/license/ctqmc1.bib b/doc/license/ctqmc1.bib new file mode 100644 index 00000000..d59087a4 --- /dev/null +++ b/doc/license/ctqmc1.bib @@ -0,0 +1,14 @@ +@Article{triqs_ctqmc_solver_boehnke, + volume = {84}, + month = {Aug}, + numpages = {13}, + author = {Boehnke, Lewin and Hafermann, Hartmut and Ferrero, Michel and Lechermann, Frank and Parcollet, Olivier}, + year = {2011}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.84.075145}, + doi = {10.1103/PhysRevB.84.075145}, + issue = {7}, + title = {Orthogonal polynomial representation of imaginary-time Green's functions}, + publisher = {American Physical Society}, + pages = {075145}, + journal = {Phys. Rev. B} +} diff --git a/doc/license/ctqmc2.bib b/doc/license/ctqmc2.bib new file mode 100644 index 00000000..327a696f --- /dev/null +++ b/doc/license/ctqmc2.bib @@ -0,0 +1,14 @@ +@Article{triqs_ctqmc_solver_werner1, + volume = {97}, + month = {Aug}, + numpages = {4}, + author = {Werner, Philipp and Comanac, Armin and de' Medici, Luca and Troyer, Matthias and Millis, Andrew J.}, + year = {2006}, + url = {http://link.aps.org/doi/10.1103/PhysRevLett.97.076405}, + doi = {10.1103/PhysRevLett.97.076405}, + issue = {7}, + title = {Continuous-Time Solver for Quantum Impurity Models}, + publisher = {American Physical Society}, + pages = {076405}, + journal = {Phys. Rev. Lett.} +} diff --git a/doc/license/ctqmc3.bib b/doc/license/ctqmc3.bib new file mode 100644 index 00000000..bce7cea6 --- /dev/null +++ b/doc/license/ctqmc3.bib @@ -0,0 +1,14 @@ +@Article{triqs_ctqmc_solver_werner2, + volume = {74}, + month = {Oct}, + numpages = {13}, + author = {Werner, Philipp and Millis, Andrew J.}, + year = {2006}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.74.155107}, + doi = {10.1103/PhysRevB.74.155107}, + issue = {15}, + title = {Hybridization expansion impurity solver: General formulation and application to Kondo lattice and two-orbital models}, + publisher = {American Physical Society}, + pages = {155107}, + journal = {Phys. Rev. B} +} diff --git a/doc/license/legal/CITATIONS.bib b/doc/license/legal/CITATIONS.bib new file mode 100644 index 00000000..6f83b618 --- /dev/null +++ b/doc/license/legal/CITATIONS.bib @@ -0,0 +1,93 @@ +-------------------------------------------------------------------------------- +THE TRIQS PROJECT BASIC COMPONENTS (Green's functions, HDF archives, ...) +-------------------------------------------------------------------------------- + +@Article{triqs_project, + author = {} + year = {} +} + +-------------------------------------------------------------------------------- +EXTENSION MODULES: Hybridization Quantum Monte Carlo +-------------------------------------------------------------------------------- + +@Article{triqs_ctqmc_solver_boehnke, + volume = {84}, + month = {Aug}, + numpages = {13}, + author = {Boehnke, Lewin and Hafermann, Hartmut and Ferrero, Michel and Lechermann, Frank and Parcollet, Olivier}, + year = {2011}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.84.075145}, + doi = {10.1103/PhysRevB.84.075145}, + issue = {7}, + title = {Orthogonal polynomial representation of imaginary-time Green's functions}, + publisher = {American Physical Society}, + pages = {075145}, + journal = {Phys. Rev. B} +} + +@Article{triqs_ctqmc_solver_werner1, + volume = {97}, + month = {Aug}, + numpages = {4}, + author = {Werner, Philipp and Comanac, Armin and de' Medici, Luca and Troyer, Matthias and Millis, Andrew J.}, + year = {2006}, + url = {http://link.aps.org/doi/10.1103/PhysRevLett.97.076405}, + doi = {10.1103/PhysRevLett.97.076405}, + issue = {7}, + title = {Continuous-Time Solver for Quantum Impurity Models}, + publisher = {American Physical Society}, + pages = {076405}, + journal = {Phys. Rev. Lett.} +} + +@Article{triqs_ctqmc_solver_werner2, + volume = {74}, + month = {Oct}, + numpages = {13}, + author = {Werner, Philipp and Millis, Andrew J.}, + year = {2006}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.74.155107}, + doi = {10.1103/PhysRevB.74.155107}, + issue = {15}, + title = {Hybridization expansion impurity solver: General formulation and application to Kondo lattice and two-orbital models}, + publisher = {American Physical Society}, + pages = {155107}, + journal = {Phys. Rev. B} +} + +-------------------------------------------------------------------------------- +EXTENSION MODULES: Wien2K interface +-------------------------------------------------------------------------------- + +@Article{triqs_wien2k_interface, + volume = {80}, + month = {Aug}, + numpages = {15}, + author = {Aichhorn, Markus and Pourovskii, Leonid and Vildosola, Veronica and Ferrero, Michel and Parcollet, Olivier + and Miyake, Takashi and Georges, Antoine and Biermann, Silke}, + year = {2009}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.80.085101}, + doi = {10.1103/PhysRevB.80.085101}, + issue = {8}, + title = {Dynamical mean-field theory within an augmented plane-wave framework: + Assessing electronic correlations in the iron pnictide LaFeAsO}, + publisher = {American Physical Society}, + pages = {085101}, + journal = {Phys. Rev. B} +} + +@Article{triqs_wien2k_full_charge_SC, + doi = {10.1103/PhysRevB.84.054529}, + month = {Aug}, + issue = {5}, + author = {Aichhorn, Markus and Pourovskii, Leonid and Georges, Antoine}, + year = {2011}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.84.054529}, + publisher = {American Physical Society}, + title = {Importance of electronic correlations for structural and magnetic properties of the iron pnictide superconductor LaFeAsO}, + pages = {054529}, + journal = {Phys. Rev. B}, + volume = {84}, + numpages = {7} +} diff --git a/doc/license/legal/CITATIONS.rst b/doc/license/legal/CITATIONS.rst new file mode 100644 index 00000000..e8c7e7e4 --- /dev/null +++ b/doc/license/legal/CITATIONS.rst @@ -0,0 +1,3 @@ +.. _CITATIONS: + +.. literalinclude:: CITATIONS.bib diff --git a/doc/license/legal/COPYING.txt b/doc/license/legal/COPYING.txt new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/doc/license/legal/COPYING.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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. + + This program 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 this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/doc/license/legal/GPL.rst b/doc/license/legal/GPL.rst new file mode 100644 index 00000000..2cb5c709 --- /dev/null +++ b/doc/license/legal/GPL.rst @@ -0,0 +1,6 @@ +.. _GPL: + +GNU Public License +------------------ + +.. literalinclude:: COPYING.txt diff --git a/doc/license/legal/License.rst b/doc/license/legal/License.rst new file mode 100644 index 00000000..7da0a782 --- /dev/null +++ b/doc/license/legal/License.rst @@ -0,0 +1,6 @@ +.. _License: + +License +------- + +.. literalinclude:: License.txt diff --git a/doc/license/legal/License.txt b/doc/license/legal/License.txt new file mode 100644 index 00000000..ed9df280 --- /dev/null +++ b/doc/license/legal/License.txt @@ -0,0 +1,23 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + + + diff --git a/doc/license/legal/legal.rst b/doc/license/legal/legal.rst new file mode 100644 index 00000000..992dcb6b --- /dev/null +++ b/doc/license/legal/legal.rst @@ -0,0 +1,44 @@ +.. index:: disclaimer + +.. role:: red + +.. _legal: + +License, Citations and Disclaimer +========================================== + +License +--------- + +TRIQS is published under the GNU Public License, :ref:`GNU Public License `, version 3 (also provided as the +LICENSE.txt and COPYING.txt files in the source directory). + +Citations +----------- + +TRIQS is a part of our scientific work. As such, like any other kind of publication, +we expect you to cite it if you use it, according to the standard rules of the academic world. +To help you, we provide in :ref:`CITATION.bib ` a digest of the papers relevant for the various TRIQS modules. + +If you find TRIQS useful, giving proper reference and citation is indeed a simple way to help convincing funding +sources that such projects are useful for our community and should be supported. + +Disclaimer +------------------- + +The program is provided `as is`, i.e. WITHOUT ANY WARRANTY of any kind, as stated in the license. +In particular, its authors and contributors will take no responsability for any possible bugs +or any improper use of these programs, +including those resulting in incorrect scientific publications. + +Moreover, we emphasize that TRIQS is a **toolbox**, which means that you need to learn how to use the tools properly. +In particular, + +* using TRIQS correctly requires **a solid knowledge of the quantum many-body problem**, + its technical concepts, and their physical interpretation. + +* TRIQS has **no safety net**. + We do not provide exhaustive checks of parameters passed to various objects and functions + to ensure that they are reasonable and physically meaningful. + + diff --git a/doc/license/wien2k1.bib b/doc/license/wien2k1.bib new file mode 100644 index 00000000..1c241a01 --- /dev/null +++ b/doc/license/wien2k1.bib @@ -0,0 +1,15 @@ +@Article{triqs_wien2k_interface, + volume = {80}, + month = {Aug}, + numpages = {15}, + author = {Aichhorn, Markus and Pourovskii, Leonid and Vildosola, Veronica and Ferrero, Michel and Parcollet, Olivier and Miyake, Takashi and Georges, Ant +oine and Biermann, Silke}, + year = {2009}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.80.085101}, + doi = {10.1103/PhysRevB.80.085101}, + issue = {8}, + title = {Dynamical mean-field theory within an augmented plane-wave framework: Assessing electronic correlations in the iron pnictide LaFeAsO}, + publisher = {American Physical Society}, + pages = {085101}, + journal = {Phys. Rev. B} +} diff --git a/doc/license/wien2k2.bib b/doc/license/wien2k2.bib new file mode 100644 index 00000000..cfe49e24 --- /dev/null +++ b/doc/license/wien2k2.bib @@ -0,0 +1,14 @@ +@Article{triqs_wien2k_full_charge_SC, + doi = {10.1103/PhysRevB.84.054529}, + month = {Aug}, + issue = {5}, + author = {Aichhorn, Markus and Pourovskii, Leonid and Georges, Antoine}, + year = {2011}, + url = {http://link.aps.org/doi/10.1103/PhysRevB.84.054529}, + publisher = {American Physical Society}, + title = {Importance of electronic correlations for structural and magnetic properties of the iron pnictide superconductor LaFeAsO}, + pages = {054529}, + journal = {Phys. Rev. B}, + volume = {84}, + numpages = {7} +} diff --git a/doc/overview.rst b/doc/overview.rst new file mode 100644 index 00000000..517acd81 --- /dev/null +++ b/doc/overview.rst @@ -0,0 +1,209 @@ +TRIQS in a nutshell +=================== + +TRIQS is a toolbox containing **ready-to-use applications**, **python modules** as well as **C++ libraries** aimed at physicists in the field of quantum interacting systems. + +Applications +------------ + +Interface to Wien2k for LDA+DMFT calculation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +TRIQS allows you to turn band-structure calculations obtained from the Wien2k package to inputs to full-fledged LDA+DMFT calculations in a few lines! + + + +[example here] + +To learn more, see + +Solvers for impurity models +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +TRIQS comes with powerful numerical solvers for quantum impurity models. + + +[example here] + +To learn more, see + +Python modules +-------------- + +Green's functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With TRIQS, the manipulation of Green's functions is made easy: construction of Green's functions in frequency and time domains (imaginary and real), Fourier transforms, visualization, tail computation... + + + +.. runblock:: python + + # Import the Green's functions + from pytriqs.gf.local import GfImFreq, iOmega_n, inverse + + # Create the Matsubara-frequency Green's function and initialize it + gw = GfImFreq(indices = [1], beta = 50, n_points = 1000, name = "imp") + gw <<= inverse( iOmega_n + 0.5 ) + + + # Create an imaginary-time Green's function and plot it + gt = GFBloc_ImTime(Indices = [1], Beta = 50) + gt <<= InverseFourier(gw) + + #from pytriqs.plot.mpl_interface import oplot + #oplot(g, '-o', x_window = (0,10)) + + print gt(0.5) + + +To learn more, see + +Lattice tools +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +With TRIQS, build a tight-binding model on any lattice in a few lines, and extract its density of states, dispersion... + + +[example here] + +.. runblock:: python + + print 2+2 # this will give output + + +To learn more, see + +C++ libraries +------------- + + +Monte-Carlo library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Set up a Monte-Carlo simulation in a few lines: you write the configuration, moves and measures, while TRIQS takes care of the Metropolis algorithm and parallelization of the code. + + +.. compileblock:: + + #include + #include + #include + + // the configuration: a spin, the inverse temperature, the external field + struct configuration { + int spin; double beta, h; + configuration(double beta_, double h_) : spin(-1), beta(beta_), h(h_) {} + }; + + // a move: flip the spin + struct flip { + configuration & config; + + flip(configuration & config_) : config(config_) {} + + double attempt() { return std::exp(-2*config.spin*config.h*config.beta); } + double accept() { config.spin*= -1; return 1.0; } + void reject() {} + }; + + // a measurement: the magnetization + struct compute_m { + configuration & config; + double Z, M; + + compute_m(configuration & config_) : config(config_), Z(0), M(0) {} + + void accumulate(double sign) { Z += sign; M += sign * config.spin; } + + void collect_results(boost::mpi::communicator const &c) { + double sum_Z, sum_M; + boost::mpi::reduce(c, Z, sum_Z, std::plus(), 0); + boost::mpi::reduce(c, M, sum_M, std::plus(), 0); + + if (c.rank() == 0) { + std::cout << "Magnetization: " << sum_M / sum_Z << std::endl << std::endl; + } + } + }; + + int main(int argc, char* argv[]) { + + // initialize mpi + boost::mpi::environment env(argc, argv); + boost::mpi::communicator world; + + // greeting + if (world.rank() == 0) std::cout << "Isolated spin" << std::endl; + + // prepare the MC parameters + int N_Cycles = 500000; + int Length_Cycle = 10; + int N_Warmup_Cycles = 1000; + std::string Random_Name = ""; + int Random_Seed = 374982 + world.rank() * 273894; + int Verbosity = (world.rank() == 0 ? 2 : 0); + + // construct a Monte Carlo loop + triqs::mc_tools::mc_generic SpinMC(N_Cycles, Length_Cycle, N_Warmup_Cycles, + Random_Name, Random_Seed, Verbosity); + + // parameters of the model + double beta = 0.3; + double field = 0.5; + + // construct configuration + configuration config(beta, field); + + // add moves and measures + SpinMC.add_move(flip(config), "flip move"); + SpinMC.add_measure(compute_m(config), "magnetization measure"); + + // Run and collect results + SpinMC.start(1.0, triqs::utility::clock_callback(600)); + SpinMC.collect_results(world); + + return 0; + } + +To learn more, see + +Array library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Create, manipulate and store powerful multi-dimensional arrays: + + +.. highlight:: c + + +.. compileblock:: + + #include + using triqs::arrays::array; + int main(){ + array A(20); + } + +To learn more, see + +Expression library: CLEF +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Write mathematical expressions in a seamless and computationally efficient way: + + + .. compileblock:: + + #include + int main () { + triqs::clef::placeholder <1> x_; + + auto e1 = cos(2*x_+1); + auto e2 = abs(2*x_-1); + auto e3 = floor(2*x_-1); + auto e4 = pow(2*x_+1,2); + } + + +To learn more, see diff --git a/doc/reference/c++/CMakeLists.txt b/doc/reference/c++/CMakeLists.txt new file mode 100644 index 00000000..e2bc51d3 --- /dev/null +++ b/doc/reference/c++/CMakeLists.txt @@ -0,0 +1,3 @@ +add_all_subdirectories_with_cmakelist() + + diff --git a/doc/reference/c++/CMakeLists.txt.v1 b/doc/reference/c++/CMakeLists.txt.v1 new file mode 100644 index 00000000..4127e91f --- /dev/null +++ b/doc/reference/c++/CMakeLists.txt.v1 @@ -0,0 +1,86 @@ +# Copyright Olivier Parcollet 2010 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +FILE(GLOB_RECURSE SOURCES *.rst) + +# The compiler flags for autocompile +SET( link_libs "${LAPACK_LIBS} ${BOOST_LIBRARY} ${ALPS_EXTRA_LIBRARIES}") +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + list (REMOVE_DUPLICATES link_libs) +ENDIF( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +string(REPLACE "boost_for_triqs" " " TMP "${link_libs}") +string(REPLACE "debug" " " TMP "${TMP}") +string(REPLACE "optimized" " " TMP "${TMP}") + +if(BOOST_SOURCE_DIR) + SET( link_boost_for_triqs "-lboost_for_triqs") +EXECUTE_PROCESS(COMMAND sh -c "ln -sf ${CMAKE_BINARY_DIR}/foreignlibs/boost/libboost_for_triqs.so ${CMAKE_CURRENT_BINARY_DIR}") +else(BOOST_SOURCE_DIR) + SET( link_boost_for_triqs " ") +endif(BOOST_SOURCE_DIR) +SET(DOC_AUTOCOMPILE_INCLUDE ${BOOST_SOURCE_DIR} ${CMAKE_SOURCE_DIR} ${ALPS_INCLUDE_DIRS} ${ALPS_EXTRA_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/foreignlibs ) +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +SET(DOC_AUTOCOMPILE_LINK "-L ${CMAKE_BINARY_DIR}/foreignlibs/boost ${link_boost_for_triqs} -L ${CMAKE_BINARY_DIR}/triqs -ltriqs -L ${CMAKE_BINARY_DIR}/triqs -ltriqs_utility ${TMP} ") +SET(DOC_AUTOCOMPILE_DEFINITIONS -std=c++0x -DBOOST_PP_VARIADICS=1 -stdlib=libc++ -I/System/Library/Frameworks/vecLib.framework/Versions/A/Headers) +else() +SET(DOC_AUTOCOMPILE_LINK "-L ${CMAKE_BINARY_DIR}/foreignlibs/boost ${link_boost_for_triqs} -L ${CMAKE_BINARY_DIR}/triqs -ltriqs -L ${CMAKE_BINARY_DIR}/triqs -ltriqs_utility ${TMP} -Wl,-rpath=${CMAKE_CURRENT_BINARY_DIR} ") +SET(DOC_AUTOCOMPILE_DEFINITIONS -std=c++0x -DBOOST_PP_VARIADICS=1 ) +endif() +SET(DOC_AUTOCOMPILE_LD_LIBRARY_PATH " ${CMAKE_BINARY_DIR}/foreignlibs/boost/:${CMAKE_BINARY_DIR}/triqs ") + +EXECUTE_PROCESS(COMMAND sh -c "ln -sf ${CMAKE_BINARY_DIR}/triqs/libtriqs.so ${CMAKE_CURRENT_BINARY_DIR}") +EXECUTE_PROCESS(COMMAND sh -c "ln -sf ${CMAKE_BINARY_DIR}/triqs/libtriqs_utility.so ${CMAKE_CURRENT_BINARY_DIR}") + +# generating the conf.py +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in ${CMAKE_CURRENT_BINARY_DIR}/conf.py) +EXECUTE_PROCESS(COMMAND sh -c "mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/html") +SET(DOC_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}) +SET(DOC_EXT "_cpp") +include(${TRIQS_SOURCE_DIR}/cmake/BuildSphinx.cmake) + +add_all_subdirectories_with_cmakelist() + +# Build the doxygen +SET(DOXYGEN_HTML_OUTPUT ./html/doxy_triqs) +find_package(Doxygen REQUIRED) + +get_property(DOXYGEN_SOURCES GLOBAL PROPERTY DOXYGEN_SOURCES) +string(REPLACE ";" " " DOXYGEN_SOURCES_LIST "${DOXYGEN_SOURCES}") +message(STATUS "Doxygen sources are ${DOXYGEN_SOURCES}") + +# Prepare the Doxyfile +configure_file(${TRIQS_SOURCE_DIR}/cmake/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + +SET(doxy_top ${CMAKE_CURRENT_BINARY_DIR}/doxy.log) +add_custom_command (OUTPUT ${doxy_top} DEPENDS ${DOXYGEN_SOURCES} COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile > ${doxy_top} ) +add_custom_target(docs_doxy ALL DEPENDS ${doxy_top}) +add_dependencies(docs_sphinx_cpp docs_doxy) # we must first have doxygen process the sources to link to them +add_dependencies(docs_sphinx_cpp triqs boost_for_triqs ) # add also mpi ? + +if (Build_PDF_Documentation) + # not needed, no link to doxygen in the pdf ... + #add_dependencies(docs_sphinx_pdf_cpp docs_doxy) # we must first have doxygen process the sources to link to them + add_dependencies(docs_sphinx_pdf_cpp triqs boost_for_triqs ) # add also mpi ? + install(FILES ${sphinx_top_pdf} DESTINATION share/doc/triqs/developer_manual/) +endif() + +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ COMPONENT documentation DESTINATION share/doc/triqs/developer_manual + FILES_MATCHING + PATTERN "*.html" + PATTERN "*.png" + PATTERN "*.js" + PATTERN "_*" + PATTERN "*.png" + PATTERN "*.gif" + PATTERN "*.xsl" + PATTERN "*.css" + PATTERN "*.pdf" + PATTERN "*.py" + PATTERN "*.txt" + PATTERN "*.bib" + PATTERN ".svn" EXCLUDE + PATTERN "CVS" EXCLUDE + ) + diff --git a/doc/reference/c++/arrays/CMakeLists.txt b/doc/reference/c++/arrays/CMakeLists.txt new file mode 100644 index 00000000..65e6b28a --- /dev/null +++ b/doc/reference/c++/arrays/CMakeLists.txt @@ -0,0 +1,10 @@ +# Doxygen sources +set_property(GLOBAL APPEND PROPERTY DOXYGEN_SOURCES + ${TRIQS_SOURCE_DIR}/triqs/arrays/h5/simple_read_write.hpp + ${TRIQS_SOURCE_DIR}/triqs/arrays/h5/array_proxy.hpp + ${TRIQS_SOURCE_DIR}/triqs/arrays/h5/array_stack.hpp + ${TRIQS_SOURCE_DIR}/triqs/arrays/array.hpp + ${TRIQS_SOURCE_DIR}/triqs/arrays/matrix.hpp + ${TRIQS_SOURCE_DIR}/triqs/arrays/vector.hpp + ) + diff --git a/doc/reference/c++/arrays/Design/centralconcept.rst b/doc/reference/c++/arrays/Design/centralconcept.rst new file mode 100644 index 00000000..aacc28a6 --- /dev/null +++ b/doc/reference/c++/arrays/Design/centralconcept.rst @@ -0,0 +1,39 @@ +The central concept : HasImmutableArrayInterface +======================================================= + +The central concept used by the library (both in the colloquial and in the technical acceptance of the word) +is the notion of **Immutable Array Interface**. + +This is just a formal definition of what has an object has to implement ("which concept it has to model") +to look like an array. + +Basically, the answer is simple, an array is a (discrete) map between a domain of indices into an algebra +(typically R, ou C). Therefore it has to defined : + +* a domain of indices, which can be enumerated, e.g. cartesian products of integer ranges. +* an evaluation method [] so that a[ I ] has a `value_type` type for any index I in the domain. + +The precise concept if defined at :ref:`HasImmutableArrayInterface` concept. + +Examples : + +* a matrix has a domain of range(0,n1) x range(0,n2). +* a general array has a domain of dimension rank and values in R, C, other arrays... +* a triangular matrix has a more complex domain... +* any algebraic expression of arrays, matrices are like this (and those one are certainly NOT mutable objects !). + +* What is then a (partial) view/slice of an array ? + + Simply another map on the same data. + +* Do you want to see a 4 indices arrays as a matrix of double indices ? + + Simply change the map... + +* Why is this concept useful ? + + Because if you program another object of your own, which models it, + it is guaranteed to interact properly with arrays.... + + + diff --git a/doc/reference/c++/arrays/Design/concepts.rst b/doc/reference/c++/arrays/Design/concepts.rst new file mode 100644 index 00000000..9b946c95 --- /dev/null +++ b/doc/reference/c++/arrays/Design/concepts.rst @@ -0,0 +1,252 @@ + +Concepts +============================================================= + +BoostSerializable +------------------------------------------------- + +* define serialize for boost serialize library + +Printable +------------------------------------------------- + + ====================================================== =========================================================== + Elements Comment + ====================================================== =========================================================== + std::ostream & operator << (std::ostream & out, ...) Printing + ====================================================== =========================================================== + +Domain +------------------------------------------------- + +* **Purpose** : The domain of definition of the array, i.e. the possible value of the indices. +* **Refines** : BoostSerializable, Printable +* **Definition** : + ++------------------------------------------------------------------+-------------------------------------------------------+ +| Elements | Comment | ++==================================================================+=======================================================+ +| static const unsigned int rank | rank | ++------------------------------------------------------------------+-------------------------------------------------------+ +| index_value_type | type of the multi-index | ++------------------------------------------------------------------+-------------------------------------------------------+ +| default constructor, copy construction | | ++------------------------------------------------------------------+-------------------------------------------------------+ +| operator = | | ++------------------------------------------------------------------+-------------------------------------------------------+ +| operator ==, != | | ++------------------------------------------------------------------+-------------------------------------------------------+ +| size_t number_of_elements() const | number of elements | ++------------------------------------------------------------------+-------------------------------------------------------+ +| generator | type of the IndexGenerator that generates the indices | ++------------------------------------------------------------------+-------------------------------------------------------+ +| begin() const/ end() const | a generator at start/end | ++------------------------------------------------------------------+-------------------------------------------------------+ + +* **Examples** : + + Typically, this is is a multi-index for an array, matrix, ...., e.g. + + * Cuboid : standard hyperrectangular arrays. This is little more than the tuple of the lengths. + * triangle, .... ? + +.. _HasImmutableArrayInterface: + +HasImmutableArrayInterface +------------------------------------------------- + +* **Purpose** : The most abstract definition of something that behaves like an immutable array. + * it has a domain (hence a rank). + * it can be evaluated on any value of the indices in the domain + * By combining the generator of the domain with the evaluation, it is therefore easy to + iterate on the values of such an object. + * NB : It does not need to be stored in memory. A formal expression, e.g. model this concept. + +* **Definition** ([A|B] denotes that the return type maybe A or B). + + ================================================================================================== ============================================================= + Elements Comment + ================================================================================================== ============================================================= + value_type Type of the element of the array + domain_type Type of the domain. + [domain_type const & | domain_type] domain() const Access to the domain. + [ value_type | value_type const &] operator[] (domain_type::index_value_type const &) const Evaluation. + ================================================================================================== ============================================================= + +* **Examples** : + * array, array_view, matrix, matrix_view, vector, vector_view (all implemented as Indexmap_Storage_Pair) + * array expressions (in which case the returns are not const & since they are computed, not stored). + +IndexGenerator +------------------------------------------------- +* **Purpose** : Generate the indices of a domain. + +* **Definition** : + + ============================================================== ================================================================================================== + Elements Comment + ============================================================== ================================================================================================== + domain_type Type of the domain whose indices are generated. + default contruction, copy construction + construction from (domain_type const &, bool atend=false) + IndexGenerator & operator=(const IndexGenerator & ) + operator ++ + operator = + operator ==, != + domain_type::index_value_type const & operator * () const Access to the value of the multi-index + bool at_end() const True iif the generator has reached the last value + ============================================================== ================================================================================================== + + +* **Examples** : + + * cuboid_index_generator + +IndexMap +------------------------------------------------- + +* **Purpose** : + + * Store the mapping of the index domain to a linear array. + * It is basically a function : indices --> 1d position, the bijection between the indices + of an element and its position in the memory block. +* **Refines** : BoostSerializable, Printable +* **Definition** : + + ======================================================================== ================================================================================================== + Elements Comment + ======================================================================== ================================================================================================== + * domain_type The type of the domain. + * domain_type const & domain() const The domain. + * default constructor, copy construction Cpy is a true copy. + * can be constructed from domain_type const & + * size_t operator[] (domain_type::index_value_type const & key ) const The mapping itself. + * iterator A type modeling IndexMapIterator, which is the optimal memory traversal. + NB : the order of indices is chosen for optimal traversal of memory, it + does not need to be "natural". + cuboid_map also provides a natural_iterator for that purpose. + ======================================================================== ================================================================================================== + +* The type also has to define two free functions and to specialize a template : + + ========================================================== ================================================================================================== + Elements Comment + ========================================================== ================================================================================================== + * bool compatible_for_assignment (M1, M2) Returns whether an array/matrix/vector with map M1 can be equated to a array/matrix/vector with + map M2 + * bool raw_copy_possible (M1, M2) Is the assignment of an array/matrix/vector with map M2 into an array/matrix/vector with map M1 + doable with raw copy + * struct indexmap_iterator_adapter< It, I > Metafunction : + + - I is the IndexMap class + - It any similar IndexMapIterator which returns (in ::type) the IndexMapIterator on I + with the same order traversal as It. + + Example : It is a IndexMapIterator on I1 stored in C order, I is in Fortran order, + the result will be an IndexMapIterator on I that presents the data of I in C order + This is used in copying array with different indexmaps. + ========================================================== ================================================================================================== + + +* **Examples** : + * cuboid_map : a map of the cuboid indices in a fixed order in memory. + +IndexMapIterator +------------------------------------------------- + +* **Purpose** : + * A basic iterator on an IndexMap which can be dereferenced into the shift of successive elements compared to the start of the memory block. + * These iterators are kept as simple as possible, so that it is easy to implement new indices maps and their iterators. + * NB : In particular, they are *not* necessary STL-compliant. The array_iterator class will + take such an iterator and a Storage and produce a true, STL compliant iterator on the array (iterator_adapter). + +* **Definition** : + + ========================================================== ================================================================================================== + Elements Comment + ========================================================== ================================================================================================== + indexmap_type The index_map on which the iterator is iterating + domain_type Type of the domain whose indices are generated. + default contruction, copy construction + construction from (domain_type const &, bool atend=false) + IndexMapIterator & operator=(const IndexMapIterator & ) + IndexMapIterator & operator ++ + operator ==, != + std::ptrdiff_t operator*() const Dereference as a shift from the beginning of the array + domain_type::index_value_type const & indices () const Access to the value of the multi-index at the iterator position + bool at_end() const True iif the generator has reached the last value (in practice quicker that it = XX.end()). + ========================================================== ================================================================================================== + +* **Example(s)** : + + * cuboid_map_iterator + +Storage +------------------------------------------------- + +* **Purpose** : + * The storage of the array in memory, e.g. plain C++ array, a numpy, etc... + * A Storage keeps the reference to the memory block where the array is stored. + * NB : This memory block can be typically shared between various arrays and views, + so the Storage is just a reference. The memory is deallocated only + when all storages referencing it has been destroyed. +* **Refines** : BoostSerializable +* **Definition** : + + ====================================================== ================================================================================================== + Elements Comment + ====================================================== ================================================================================================== + value_type Type of the element stored, e.g. int, const int, double, const double, ... + default construction Makes a storage of size 0 + copy construction a shallow copy (another reference to the same data). + the copy construction is possible from another storage of the same value_type + up to the const qualifier. + The construction of a storage with value_type=T from a storage with value_type const T + is forbidden at compile time. + void operator = (const STO &) A shallow copy of the reference to the data. + + clone() const Create a clone of the data. + const_clone() const Create a clone of the data with const value_type (e.g. int--> const int). + + void raw_copy_from(const STO & X) Copy all the data from X to * this. Behaviour undefined if sizes do not match. + + size_t size() const Number of elements in the storage + + value_type & operator[](size_t p) const Access to the data. Behaviour is undefined if empty()==true. + ====================================================== ================================================================================================== + + + +StorageOrder concept +------------------------------------------------- + +* **Purpose** : + + * Store the order of indices in memory. + * Can be fixed at compile time, or dynamically (not implemented). + +* **Refines** : BoostSerializable +* **Definition** : + + ====================================================== ================================================================================================== + Elements Comment + ====================================================== ================================================================================================== + size_t index_number(size_t i) + static unsigned int rank + default construction + copy construction + bool is_Fortran() const Is it Fortran-style ordering ? + bool is_C() const Is it C-style ordering ? + + ====================================================== ================================================================================================== + + +* The type also has to define the == operator : + + ========================================================== ================================================================================================== + Elements Comment + ========================================================== ================================================================================================== + Operator == Defined between any of the ordering. + ========================================================== ================================================================================================== + + diff --git a/doc/reference/c++/arrays/Design/contents.rst b/doc/reference/c++/arrays/Design/contents.rst new file mode 100644 index 00000000..de4e0d73 --- /dev/null +++ b/doc/reference/c++/arrays/Design/contents.rst @@ -0,0 +1,11 @@ +Concepts, implementation, design ... +*************************************** + +.. highlight:: c + +.. toctree:: + :maxdepth: 1 + :numbered: + + concepts + diff --git a/doc/reference/c++/arrays/Design/cuboid_formula.rst b/doc/reference/c++/arrays/Design/cuboid_formula.rst new file mode 100644 index 00000000..e2185c11 --- /dev/null +++ b/doc/reference/c++/arrays/Design/cuboid_formula.rst @@ -0,0 +1,60 @@ + +.. _cuboid_formula: + +Cuboid formula +====================== + +* **Notations** : + + * R = rank + * index : (i0,...,i_{R-1}) + * Lengths : (L0, ... , L_{R-1}) + * Strides : (S0, ... , S_{R-1}) + * position = start_shift + \sum_{j=0}^{R-1} i_j S_j + +* **Strides for compact cuboid** : + + If :math:`\sigma(i)` is the i-th index in memory (0 the first, R-1 the last one), we have + + .. math:: + :nowrap: + + \begin{align*} + S_{\sigma(0)} &= 1\\ + S_{\sigma(1)} &= L_{\sigma(0)} S_{\sigma(0)} = L_{\sigma(0)}\\ + S_{\sigma(i)} &= L_{\sigma(i-1)} S_{\sigma(i-1)} = \prod_{j=i-1}^{0} L_{\sigma(j)} + \end{align*} + + +* **Slicing the cuboid** : + + + * Argument of the slice : (R0, R1, ..., R_{R-1}), with R_i = range : (start,end,step) + for the moment, if R_i = E_i, a number, consider it as a special range of length 1. + * new index (k0,...., k_{R-1}). + i_u = R_u.start + k_u * R_u.step + * Compute the new strides : Sn_j + + .. math:: + :nowrap: + + \def\offset{\text{offset}} + \begin{align*} + position &= \offset + \sum_{j=0}^{R-1} i_j S_j \\ + &= \offset + \sum_{j=0}^{R-1} (k_j* R_j.step + R_j.start) S_j \\ + &= (\offset + \sum_{j=0}^{R-1} (k_j* R_j.step + R_j.start) S_j ) + \sum_{j=0}^{R-1} k_j (S_j * R_j.start) + \\ + \offset_\text{new} &= \offset + \sum_{j=0}^{R-1} (k_j* R_j.step + R_j.start) S_j \\ + &= position( R_j.start) \\ + Sn_j &= S_j * R_j.start + \end{align*} + + * Now : for the cases R_i = E_i, just drop the index. + + + + + + + + diff --git a/doc/reference/c++/arrays/Design/slicing.rst b/doc/reference/c++/arrays/Design/slicing.rst new file mode 100644 index 00000000..d41a4b93 --- /dev/null +++ b/doc/reference/c++/arrays/Design/slicing.rst @@ -0,0 +1,52 @@ +.. _DesignSlicing: + +Slicing +============================================================= + +In this section, IM denotes some IndexMaps. + +* We refer here to any partial view of the arrays as "slicing", i.e. subarrays, true slices, etc... + A slicing is any (meta)-function that take an indexmap and return another one. + + * It is a meta-function that computes the type of the resulting indexmap + * It is a function that computes the resulting indexmap. + +* The array/matrix/vector classes and their views, when called with the () operator, will : + + * forward all the arguments and their types to IndexMaps::slice, to compute the new indexmap IM2. + * If IM2 is of dimension 0, return a value_type & or const & (it is a simple number, not an array). + * Otherwise : return a new view, made of IM2 and the same data as for the original object. + +* Possible slices are defined by the IndexMap type. + Slicing an class C with IndexMap I1 produces a class C2_view, with IndexMap I2, + i.e. a new sliced IndexMap on the same data. + +* **Examples** : + * array and array_view can be sliced : +`` + array A(10,10); : defines an array + A(1,2) : element access. + A ( 1, range(0,2) ) : 1d slice + A( range(0,10,2), range(0,10,2)) : a 2d slice viewing every each elements with even coordinates. +`` + * matrix, matrix_view when sliced, return vector_view or matrix_view. + +* One can be much more general : e.g. slicing the diagonal of a matrix, etc... + + + +* Implementation is entirely done in the IndexMaps classes, by specializing 2 templates + (basically by writing the function IM1-> IM2). + The rest is done by indexmap_storage_pair class, which will compute the correct view class + depending on the view class and IM2 (view_from_tag_I_S template). + +:: + //In namespace IndexMaps::result_of + template + struct slice< IM, ArgsTuple> { typedef IM2 type; }; + + //In namespace IndexMaps : + template + typename result_of::slice::type slice(IM const &, ArgsTuple args); + + diff --git a/doc/reference/c++/arrays/Design/strategy.rst b/doc/reference/c++/arrays/Design/strategy.rst new file mode 100644 index 00000000..d985e716 --- /dev/null +++ b/doc/reference/c++/arrays/Design/strategy.rst @@ -0,0 +1,62 @@ +.. _Design: + +Strategy +============================================================= + +All the classes are a combination of a system of indices (called IndexMap I in the following) +and a physical storage S in the computer (a block of memory), denoted as an IndexMap_Storage_Pair (I,S). + +* I models the IndexMap concept [REF below]. + + * It is the bijection between the a set of indices and the position in the memory block. It can be though as a coordinate system on the (linear) memory block. + * Various types of indices are possible (only the first is implemented now). + + * cuboid (the standard hypercubic array, the only one currently implemented) + * triangular arrays + * band matrix + * multi-indices, with indices made of pair e.g. + +* S models the Storage concept [REF]. + + * It is a handle to the memory block containing the actual data. + * It can be e.g.: + + * a C++ shared pointer to a memory block. + * a reference to a numpy array. + +This design has several consequences : + +* **Interoperability** : classes are widely interoperable, e.g. one can add a array and a matrix (if dimensions are ok of course). + one can also add a python numpy and a C++ array without any further coding. + +* It is straighforward to construct a matrix_view from an array, since it is the same couple , + just interpreted differently. + +* It is easy to view a array as a matrix by gathering indices (properly ordered in memory) : + one just has to provide a new IndexMap I2 to see the same data. + [ --> very useful for vertex computation in many body...] + +* Slicing, or partial view is very natural : it is just a function on indexmaps : I--> I2, + independantly of any storage. + + +Quick guide through the implementation +============================================================= + +The implementation is divided into basically 4 parts : + +* Storages : implements two storages shared_block and numpy + +* IndexMaps : implements cuboid index map, its domain and iterators + +* impl/indexmap_storage_pair.hpp : the basic implementation class for all user class. + It is basically just a couple of an indexmap and a storage, with shallow copy. + It also forward the slices to the indexmap and construct the correct views. + +* upper level : + * user class : array, array_view, matrix, matrix_view, vector, vector_view + * expression.hpp : boost proto expression + * numpy_interface.hpp : helper to get numpy into array + * lapack/blas interface + * hdf5 support. + diff --git a/doc/reference/c++/arrays/FAQ.rst b/doc/reference/c++/arrays/FAQ.rst new file mode 100644 index 00000000..eeb139e0 --- /dev/null +++ b/doc/reference/c++/arrays/FAQ.rst @@ -0,0 +1,24 @@ +.. highlight:: c + +FAQ +====== + +How do I iterate on my array ? +----------------------------------- + + +There are different way to iterate on the element of an array, recommended in this order from the most simple/efficient to the most complex/slow : + +* To assign data into an array, the simplest and efficient way is to use + automatic assignment with lazy expressions, Cf :ref:`Lazy`. + +* For a more general case, where one does not simply assign a value to the array element, + use a *foreach* construct, Cf :ref:`Foreach`. + +* You can use STL algorithms, since arrays have STL compliant iterators. + The performance may be lower than *foreach* loops (never better anyhow). + +* Of course, one can still use a simple for loop, but this is not recommended in general + since it is more error prone and less optimal. + + diff --git a/doc/reference/c++/arrays/H5.rst b/doc/reference/c++/arrays/H5.rst new file mode 100644 index 00000000..22ba3b40 --- /dev/null +++ b/doc/reference/c++/arrays/H5.rst @@ -0,0 +1,27 @@ +.. highlight:: c + +The HDF5 interface +###################### + + +The array classes (`array`, `matrix`, `vector`) have a simple interface to the HDF5 files. + +A simple example +------------------ + + +Reference +------------ + +.. toctree:: + :maxdepth: 1 + + h5_rw + h5_stack + h5_proxy + h5_complex + +You can also get the :doxy:`full C++ documentation` for these classes and functions. + + + diff --git a/doc/reference/c++/arrays/IO.rst b/doc/reference/c++/arrays/IO.rst new file mode 100644 index 00000000..2332206d --- /dev/null +++ b/doc/reference/c++/arrays/IO.rst @@ -0,0 +1,39 @@ +.. highlight:: c + +MPI and serialization +########################################## + +Serialization +============================ + +The `value classes` and the views are compatible with Boost Serialization library. + +MPI +============================ + +The `value classes` (array, matrix, vector) can be bcasted, reduced, +with the boost.mpi library, e.g. : + +.. compileblock:: + + #include + #include + using triqs::arrays::array;using triqs::clef::placeholder; + + int main() { + boost::mpi::environment env;//argc, argv); + boost::mpi::communicator world; + + array A (2,2), B(2,2),C(2,2); + placeholder<0> i_; placeholder<1> j_; + A(i_,j_) << (1+world.rank())*(10*i_+ j_); + + if (world.rank() ==0) std::cout<<" A = "< >(),0); + + int s= world.size(); + if (world.rank() ==0) std::cout<<" C = "<( (s*(s+1)/2) * A) < also the theory above. + +Put here the array_cython example + +- a routine that take a view +- a routine that take an array (beware to the copy). +- a wrapped class. +- a function that returns a new array from C++. Check references.... + + +.. code-block:: python + + import numpy,_testarray + a=numpy.array([[1.0,2],[3,4]]) + _testarray.f(a) + + diff --git a/doc/reference/c++/arrays/Iterators.rst b/doc/reference/c++/arrays/Iterators.rst new file mode 100644 index 00000000..8ad8b176 --- /dev/null +++ b/doc/reference/c++/arrays/Iterators.rst @@ -0,0 +1,2 @@ +.. highlight:: c + diff --git a/doc/reference/c++/arrays/STL.rst b/doc/reference/c++/arrays/STL.rst new file mode 100644 index 00000000..bd2af59a --- /dev/null +++ b/doc/reference/c++/arrays/STL.rst @@ -0,0 +1,67 @@ +.. highlight:: c + +.. _STL: + +Iterators and STL +################################################################## + +Standard iterators are provided that model the boost Mutable_ForwardIterator and ForwardIterator concepts +(and hence are STL compliant). + +The iterator implements also two additional methods : + +* it can be casted to a bool : it is true iif the iteration is not at end. +* it.indices() : returns const & to the indices at the point of the iteration. + +Examples:: + + array A (2,3); + for (auto it = A.begin(); it; ++it) *it =it.indices()[0] + 10 *it.indices()[1]; + + +Some examples of usage : + + +.. compileblock:: + + #include + #include + #include + #include + using triqs::arrays::array; using triqs::arrays::matrix; using triqs::clef::placeholder; + int main(){ + + // For example, one can make a vector of arrays ... :: + + array A (2,3); + std::vector > VV; + VV.push_back(A); + + // ... or a map :: + std::map > MAP; + MAP[1] = A; + + // We can put a std::vector in an array ... :: + // --> should make a direct constructor for this.. + factory in the reverse direction... + std::vector V (10,2); + array B(V.size()), C(V.size()); + std::copy(V.begin(),V.end(),B.begin()); + + // ... or in reverse :: + B*=2; + std::copy(B.begin(),B.end(),V.begin()); + + // ... or use other algorithms of std:: + std::cout<<" max(B) "<< * std::max_element(B.begin(),B.end())< i_; + B(i_) << 3*i_ ; + std::cout<<" B "<< B << std::endl; + std::replace_if (B.begin(), B.end(), [](int i) { return i>21;}, 0); + std::cout<<" B "<< B << std::endl; + + } + + + diff --git a/doc/reference/c++/arrays/algebras.rst b/doc/reference/c++/arrays/algebras.rst new file mode 100644 index 00000000..3f653cfd --- /dev/null +++ b/doc/reference/c++/arrays/algebras.rst @@ -0,0 +1,114 @@ +.. highlight:: c + +Operations : array and matrix/vector algebras +======================================================= + +Operations +------------ + +Arrays and matrices can be combined in formal algebraic expressions, which models the :ref:`HasImmutableArrayInterface` concept. +This algebraic expressions can therefore be used as RHS of assignment (SEE) or in array/matrix contructors. +For example ; + +.. compileblock:: + + #include + using triqs::arrays::array; + int main() { + array A (2,2), B(2,2), C; + C= A + 2*B; + array D = A+ 2*B; + array F = 0.5 * A; // Type promotion is automatic + } + +Arrays vs matrices +---------------------- + +Because their multiplication is not the same, arrays and matrices algebras can not be mixed. +Mixing them in expression would therefore be meaningless and it is therefore not allowed :: + + array A; + matrix M; + M + A; // --> ERROR. Rejected by the compiler. + +However, you can always make a matrix_view from a array of rank 2 :: + + A + make_matrix_view(M); //--> OK. + +.. note:: + + Making view is cheap, it only copies the index systems. Nevertheless + this can still cause severe overhead in very intense loops. + + +Compound operators (+=, -=, *=, /=) +------------------------------------------- + +The `value classes` and the `view classes` behaves similarly. +We will illustrate it on the `array` class, it is the same for `matrix` and `vector`. + + * **Syntax** + + The syntax is natural :: + + template array & operator += (const RHS & X); + template array & operator -= (const RHS & X); + template array & operator *= (const Scalar & S); + template array & operator /= (const Scalar & S); + + * **Behaviour** + + - Similar to assignment, but it makes the operation + - For matrices, scalar is correctly interpreted as a scalar matrix. + + +Performance +--------------------------------------------- + +The performance of such compact writing is as good as "hand-written" code or even better. + +Indeed, the operations are implemented with the `expression templates` technique. +The principle is that the result of A+B is **NOT** an array, but a more complex type which stores +the expression using the naturally recursive structure of templates. + +Expressions models :ref:`HasImmutableArrayInterface` concept. +They behave like an immutable array : they have a domain, they can be evaluated. +Hence they can used *anywhere* an object modeling this concept is accepted, e.g. : + +* array, matrix contruction +* operator =, +=, -=, ... + +When an array in assigned (or constructed from) such expression, it fills itself +by evaluating the expression. + +This technique allows the elimination of temporaries, so that the clear and readable code:: + + Z= A + 2*B + C/2; + +is in fact rewritten by the compiler into :: + + for (i,j,...) indices of A, B : + C(i,j) = A(i,j) + 2* B(i,j) + C(i,j)/2 + +instead of making a chain of temporaries (C/2, 2*B, 2*B + C/2...) that "ordinary" object-oriented programming would produce. +As a result, the produced code is as fast as if you were writing the loop yourself, +but with several advantages : + +* It is more **compact** and **readable** : you don't have to write the loop, and the indices range are computed automatically. +* It is much better for **optimization** : + + * What you want is to tell the compiler/library to compute this expression, not *how* to do it optimally on a given machine. + * For example, since the traversal order of indices is decided at compile time, the library can traverse the data + in an optimal way, allowing machine-dependent optimization. + * The library can perform easy optimisations behind the scene when possible, e.g. for vector it can use blas. + +Note that expressions are lazy objects. It does nothing when constructed, it just "record" the mathematical expression :: + + auto e = A + 2*B; // expression, purely formal, no computation is done + cout<< e < D(e); // now really makes the computation and store the result in D. + D = 2*A +B; // reassign D to the evaluation of the expression. + + diff --git a/doc/reference/c++/arrays/all.rst b/doc/reference/c++/arrays/all.rst new file mode 100644 index 00000000..b10dd6f4 --- /dev/null +++ b/doc/reference/c++/arrays/all.rst @@ -0,0 +1,360 @@ +.. highlight:: c + +array and array_view +============================ + +array and array_view are the class for standard d-dimensional cuboid array +and the corresponding view. + +Template parameters +---------------------------- + +* The class has four template parameters (same for array_view). + + .. code-block:: c + + array + + + ============================ ========================== ======================================= + Template parameter Access in the class Meaning + ============================ ========================== ======================================= + ValueType value_type The type of the element of the array + Rank rank The rank of the array *[int]* + IndexOrderTag indexmap_type The ordering in memory : can be Tag::C, Tag::Fortran or a permutation + StorageTag storage_type The storage : Tag::shared_block or Tag::numpy + ============================ ========================== ======================================= + + +* Various IndexOrderTag are possible : + + ================= ==================================================================================================== + IndexOrderTag Meaning + ================= ==================================================================================================== + Tag::C C-style order *[default]* + Tag::Fortran Fortran-style order + P - P is a permutation + - Determined by a permutation P at compile time. Explain here the permutation, the convention. + ================= ==================================================================================================== + + +* Two possible storages : + + ================== ============================================================================ + StorageTag Meaning + ================== ============================================================================ + Tag::shared_block a (shared_ptr on a) C++ block *[default]* + Tag::numpy stored in a numpy array, in which case the array is also a numpy array + and read numpy, be returned as numpy, sliced into a numpy, etc... + ================== ============================================================================ + + +.. _array_constructors: + +Constructors +----------------- + +Intentionally, array and array_view have only a few constructors : + +========================================== =========================================================================================== +Constructors of array Comments +========================================== =========================================================================================== +array() - empty array of size 0 +array(size_t, ...., size_t) - from the dimensions +array(cuboid_domain const &) - a new array with the corresponding cuboid +array(const array &) - copy construction +array(const T & X) - Type T models the :ref:`HasImmutableArrayInterface` concept. + - X must have the appropriate domain (checked at compile time). + - Enabled iif has_immutable_array_interface::value == true. + - Constructs a new array of domain X.domain() and fills it with evaluation of X. +========================================== =========================================================================================== + +====================================================================== ======================================================================================= +Constructors of array_view Comments +====================================================================== ======================================================================================= +array_view(indexmap_type const & I, S_type const &) from a couple of indexmap I and storage of type S_type +array_view(const T & X) T is any type such that X.indexmap() and X.storage(). Models ISP ... +====================================================================== ======================================================================================= + +array_view are typically constructed by slicing (Cf below). + +* Examples :: + + array A(10,2); + array Af (2,2); + + //Higher dim, custom order : + array > A0 (2,3,4); + array > A1 (2,3,4); + array > A2 (2,3,4); + array A3 (2,3,4); + array A4 (2,3,4); + + +Access to data, domain, simple evaluation, ... +-------------------------------------------------------- + +array, array_view, matrix, matrix_view, vector, vector_view model HasImmutableArrayInterface. + + +Assignment & Copy +-------------------- + +Every classes comes in two flavors: C and C_view (with C = array, matrix, vector, etc...). +These two flavors differ in the way they handle their data in construction, copy construction, assignement. +Basically, C owns its data, while C_view if only a view. + +array, matrix, vector +^^^^^^^^^^^^^^^^^^^^^^^^ + +They own their data. In many aspects, they are similar to like std::vector. + +* The data are contiguous in memory. +* Constructors and copy constructors all create a new memory block. If needed, they + make a *true* copy of the data. +* The assignment operator may create a new Storage if size do not match. +* As a result, /pointers to the data/ and reference to the storage are invalid after assignment. +* They can be resized, again invalidating all references. + +array_view, matrix_view, vector_view +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These classes do not own their data, but only present a view of them. + +* The data may not be contiguous in memory (e.g. if the view is the result of a slice). +* Constructors only make another view of the data. +* They *never* copy data, so they are quite quick. + In particular, copy constructor makes shallow copy (i.e. return another view). +* The assignement operator just copy data into the view. Behaviour is undefined if the + size of the view is too small (define the macro ARRAY_CHECK for dynamical debugging checks). +* Pointers to data taken from the views are still valid after assignement. +* Views can be not be resized. + +.. warning:: **Memory management** + + Views carry a reference to the memory block they view, + which guarantees that memory will not be + dellocated before the destruction of the view. + Indeed, the Storage types implement incorporated a reference counting mechanism, + either using boost::shared_ptr for the C++ arrays, or using the python references + for the numpy storage. + The memory block will be dellocated when its array and all array_view + pointing to it or to a portion of it will be destroyed, and only at that moment. + +Examples:: + + array *A = new array (Matrix(2,3)); // create an array A + array_view B(*A); // making a view + delete A; // A is gone... + cout< array & operator=(const RHS & X); + + * RHS models HasImmutableArrayInterface. + * array is first resized to have a domain X.domain(), and then filled + with the evaluation of X (e.g. a copy if X is an array, computing the value if X is an expression). + + +array_view, matrix_view, vector_view +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +//.. cpp:function:: + template array_view & operator=(const RHS & X); + + * RHS models HasImmutableArrayInterface [ or less ? : RHS can be evaluated in the domain_type::value_type, no domain needed.]. + * Dimension of the view must match or behaviour is undefined. + +Iterators and interaction with STL containers and algorithms +---------------------------------------------------------------- + +STL compliant iterators, hence STL algorithms work... + +Examples:: + + array A (2,3); + + // first print the index generator + for (array::indexmap_type::domain_type::generator it = A.indexmap().domain().begin(); !it.at_end(); ++it) + cout<<" "<<*it<::iterator it = A.begin(); !it.at_end(); ++it) + { *it =it.indices().get<0>() + 10 *it.indices().get<1>() ; } + + int u=0; + for (array::iterator it = A.begin(); !it.at_end(); ++it,++u) { *it =u; } + + array A (2,3); + std::vector > VV; VV.push_back(A); + map > MAP; MAP["1"] = A; + + // Trying to put a vector in an array + std::vector V (10); + array B(V.size()), C(V.size()); + for (unsigned int i =0; i<10; ++i) V[i] = 10+i; + + std::copy(V.begin(),V.end(),B.begin()); + std::copy(B.begin(),B.end(),V.begin()); + cout<<" Number of elements <25 : "<< std::count_if(B.begin(), B.end(),te)< A (2,3); + array_view SL( A(range(0,2),0)); + array_view SL2( A(1,range(0,2))); + + +It is the standard way to produce a view. + +NB : + +* we use here the python convention: range(0,3) is 0:3, i.e. 0,1,2 NOT 0,1,2,3. +* Todo : in fact we should wrap the range to python::slice for interoperability with python. + +Serialization +------------------------------------------------- + +* Boost.serialization +* Boost.mpi + +Examples:: + + array A (2,2), B(2,2),C(2,2); + boost::mpi::reduce (world, A,C, std::plus >(),0); + + +* HDF5 (ALPS), eg. + +Examples:: + + array A (2,3),B,vc; + array Af,Bf,vf; + + alps::hdf5::oarchive ar1("data.h5"); + ar1 << alps::make_pvp("Tableau", A); + ar1 << alps::make_pvp("Tableau2", Af); + ar1 << alps::make_pvp("Tableau_view", A(range(),range(1,3))); + + alps::hdf5::iarchive ar2("data.h5"); + ar2 >> alps::make_pvp("Tableau", B); + ar2 >> alps::make_pvp("Tableau", Bf); + ar2 >> alps::make_pvp("Tableau_view", vc); + ar2 >> alps::make_pvp("TableauC",C); + + +blas/lapack interface +------------------------------------------------- + +* matrix, vector and their views are interfaced with blas/lapack, via boost::numerics::bindings. +* If needed (for a view), a temporary (and silent) copy is made to reorganize the +data before calling blas/lapack (impl: cache class). +Of course, performance is altered, but code is simple... + +Examples:: + + namespace blas = boost::numeric::bindings::blas; + namespace lapack = boost::numeric::bindings::lapack; + + triqs_arrays::vector > V(5),V2(5); + triqs_arrays::vector V3(2); + triqs_arrays::matrix M1(2,2), M2(2,2), M3(2,2); + + blas::axpy(2.0,V,V2); + blas::gemm(1.0,M1, M2, 1.0, M3); + blas::ger(1.0,V3,V3,M2); + + // invert + triqs_arrays::vector ipiv(2); + lapack::getrf(M1, ipiv); + lapack::getri(M1, ipiv); + +Transparent use of python arrays +------------------------------------------------- + +* If the storage is Tag::numpy, the memory block is allocated/viewed through the numpy interface. +* One can mix arrays with any storage in expression (they have the same concepts). +* boost python converters are enable for those arrays into numpy and their views [impl :broken for views]. + + +Expression +------------------------------------------------- + +Simple expressions are made using boost.proto. +Examples :: + + array A (2,2), B(2,2),C; + C= A + 2*B; + array D( A+ 2*B); + + // or even in C++0x : + auto e = A + 2*B; // expression, purely formal + array D(e); // really makes the computation + cout<< e < A (2,2), B(2,2),C(2,2); + C= A + 2*B; + C= std::plus >()(A,B); + C = A + Transpose(B); // Transpose(X) returns a lazy object that models HasImmutableArrayInterface. + C = A + Transpose(B + B); // X can also be an expression... + C = Transpose(B); // + array F( 0.5 * A); // Type promotion is automatic + + // non square + array R(2,3),Rt(3,2); + cout<<" R = "<< array(Transpose(R)) < B; // read the file into B + h5_read (file, "A",B); + std::cout << "B = "< + using triqs::arrays::array; using triqs::arrays::array_view; using triqs::arrays::range; + int main(){ + array A(3,3); A() = 2.5; + std::cout << A < B = A(1,range()); //select the first line of the matrix + std::cout <<"B = "<< B << std::endl; + B(0) = 1; + + std::cout <<"A = "<< A << std::endl; + } + + +Matrices and vectors +------------------------- +Arrays must be distinguished from vectors and matrices, which have an algebra of their own. + +.. compileblock:: + + #include + + using triqs::arrays::array; using triqs::arrays::matrix; using triqs::arrays::vector; + int main(){ + array A(2,2), B(2,2),C; + + A() = 3; B() = 1; C = A*B; + std::cout << "A*B = "<< C << std::endl; + + matrix D(2,2),E(2,2),F; + E() = 3; E() = 1; F = D*E; + std::cout << "C*D = "<< F << std::endl; + + vector u(2),v(2),w; + u()=1;v()=2; w = u+v; + + std::cout <<"u+v = "<< w << std::endl; + } + + + +Defining through a lazy expression +----------------------------------- + +.. compileblock:: + + #include + using triqs::arrays::array; namespace tql=triqs::clef; + + int main(){ + tql::placeholder<0> i_; tql::placeholder<1> j_; + array A(2,2); + A(i_,j_) << i_ + j_ ; + std::cout << "A = "< + #include + #include + + using triqs::arrays::array; using triqs::arrays::matrix; using triqs::clef::placeholder; + int main(){ + placeholder<0> i_; + placeholder<1> j_; + matrix A(2,2); + A(i_,j_) << i_+j_; + + matrix B = inverse(A); + double C = determinant(A); + + std::cout << "A^(-1) = "<< B << std::endl; + std::cout << "det(A) = " < + #include + using triqs::arrays::array; + + double f(int i) { return i*10;} + + int main() { + auto F = triqs::arrays::map(std::function(f)); + array A(2,2); A() =2; + + array B,C; + + A() =2; + B = F(A); + C = F(2*A); // works also with expressions of course + + std::cout << "A = "< +#include +namespace tqa=triqs::arrays; namespace h5=tqa::h5; + +int main() { + + tqa::array A(2,2),B; A() = 3; // declare some array and init it + + h5::H5File file("ess.h5",H5F_ACC_TRUNC); // open the file ess.h5 + h5::write(file,"A",A); // write A in the file as 'A' + + file.createGroup("G"); // create a subgroup G (Cf hdf5 doc, C++ API) + h5::write(file,"G/A",A); // write A as G/A + + h5::Group G = file.openGroup("G"); // another way to do it : open the group and write G/A2 + h5::write(G, "A2",A); + + h5::read (file, "A",B); // Read from the file. NB : B is automatically resized +} + diff --git a/doc/reference/c++/arrays/examples_h5/h5_rw.output b/doc/reference/c++/arrays/examples_h5/h5_rw.output new file mode 100644 index 00000000..e69de29b diff --git a/doc/reference/c++/arrays/examples_h5/h5_stack_ex.cpp b/doc/reference/c++/arrays/examples_h5/h5_stack_ex.cpp new file mode 100644 index 00000000..7d2fa33a --- /dev/null +++ b/doc/reference/c++/arrays/examples_h5/h5_stack_ex.cpp @@ -0,0 +1,23 @@ + +#include +#include +namespace tqa=triqs::arrays; namespace h5=tqa::h5; + +int main() { + const size_t N = 100, bufsize = 5; + h5::H5File file("ess.h5", H5F_ACC_TRUNC); // open a file + + tqa::array A(3,2); // an array of the shape of the base of the stack + + h5::array_stack< tqa::array > S(file, "my_stack", A.shape(), bufsize); + + for (int u = 0; u< N ; ++u) { // fill the stack for a while... + A() = (u+1)* 20; + S << A; + // S() = A; ++S; // equivalent + } + S.flush(); // useless at the end... + +} + + diff --git a/doc/reference/c++/arrays/examples_h5/h5_stack_ex.output b/doc/reference/c++/arrays/examples_h5/h5_stack_ex.output new file mode 100644 index 00000000..e69de29b diff --git a/doc/reference/c++/arrays/examples_h5/h5_stack_ex_sca.cpp b/doc/reference/c++/arrays/examples_h5/h5_stack_ex_sca.cpp new file mode 100644 index 00000000..5d8fe501 --- /dev/null +++ b/doc/reference/c++/arrays/examples_h5/h5_stack_ex_sca.cpp @@ -0,0 +1,18 @@ +#include +#include +namespace tqa=triqs::arrays; namespace h5=tqa::h5; + +int main() { + const size_t N = 100, bufsize = 5; + h5::H5File file("ess.h5", H5F_ACC_TRUNC); // open a file + + h5::array_stack< double > S (file, "my_stack", bufsize); + + for (int u = 0; u< N ; ++u) { // fill the stack for a while... + S << (u+1)* 20; + } + S.flush(); // useless at the end... + +} + + diff --git a/doc/reference/c++/arrays/examples_h5/h5_stack_ex_sca.output b/doc/reference/c++/arrays/examples_h5/h5_stack_ex_sca.output new file mode 100644 index 00000000..e69de29b diff --git a/doc/reference/c++/arrays/expr_arith.rst b/doc/reference/c++/arrays/expr_arith.rst new file mode 100644 index 00000000..87e824e5 --- /dev/null +++ b/doc/reference/c++/arrays/expr_arith.rst @@ -0,0 +1,104 @@ +.. highlight:: c + +.. _arith_expression: + +Arithmetic Expressions +------------------------------------------------- + +* **Definition** : + + By `expression`, we mean here an object, typically representing a mathematical expression, + which models the :ref:`HasImmutableArrayInterface` concept. + +* **Use** : + + Expression can be used : + - as RHS (Right Hand Side) of various operators (=, +=, -=, ...) + - at any place where an `expression` is expected. + +* **How to make expression ?** + + Expressions can be build easily in various ways : + + - Using arithmetic operators, e.g. A + 2*B + Examples :: + + array A (2,2), B(2,2),C; + C= A + 2*B; + array D( A+ 2*B); + array F( 0.5 * A); // Type promotion is automatic + + // or even in C++0x : + auto e = A + 2*B; // expression, purely formal + array D(e); // really makes the computation + cout<< e < M1(2,2), M2(2,2), M3; + M3 = matmul(M1,M2); + + will do the following : + - matmul returns a lazy object modelling the :ref:`Expression` concept. + - a result this is compiled as some `matmul_with_lapack(M1,M2,M3)` : **there is NO intermediate copy**. + + - mat_vec_mul + + - Building custom expressions. The transpose example... + + Describe the concept, what to implement, etc.... + + - Transpose:: + + array A (2,2), B(2,2),C(2,2); + C= A + 2*B; + C = A + Transpose(B); // Transpose(X) returns a lazy object that models HasImmutableArrayInterface. + C = A + Transpose(B + B); // X can also be an expression... + C = Transpose(B); // + + // non square + array R(2,3),Rt(3,2); + cout<<" R = "<< array(Transpose(R)) < + void assign_foreach (ArrayType const & A, Function F); + + * A is an array/matrix/vector or the corresponding view. + * The template is enabled iif ImmutableArray::value == true + * F is a function with the following synopsis :: + + F(size_t ... indices) + +* The assign_foreach algorithm is equivalent to :: + + for (i,j,k...) A(i,j,k...) = F(i,j,k...) + +* The for loop are automatically organised to optimize the traversal order of A + using the TraversalOrder flag of the array. + +.. compileblock:: + + #include + using triqs::arrays::array; + int main(){ + array A (2,3); + assign_foreach (A, [](size_t i, size_t j) { return i+j;}); + std::cout<<" A "<< A << std::endl; + } + +.. note:: + Cf the note of the *foreach* function. diff --git a/doc/reference/c++/arrays/group_indices.rst b/doc/reference/c++/arrays/group_indices.rst new file mode 100644 index 00000000..64d9d699 --- /dev/null +++ b/doc/reference/c++/arrays/group_indices.rst @@ -0,0 +1,13 @@ +.. highlight:: c + +Grouping indices +======================================================== + +.. warning:: This functionality is still beta. API may change in the future... + +* **Purpose** : + +* **Syntax** : + + +* **Example** : diff --git a/doc/reference/c++/arrays/h5_complex.rst b/doc/reference/c++/arrays/h5_complex.rst new file mode 100644 index 00000000..f611617f --- /dev/null +++ b/doc/reference/c++/arrays/h5_complex.rst @@ -0,0 +1,15 @@ +.. highlight:: c + +Issue with the complex numbers +============================================================================ + +There is no standard representation of the complex numbers `std::complex` in hdf5. + +The classes therefore represent them as arrays of `T` with one more dimension, and +adding a tag *_complex_* to the array for identification when rereading. + +* This is compatible with the ALPS 2.0 storage. +* This is **not** compatible with the regular h5py storage for complex. + The conversion is made by HDFArchive class automatically. + + diff --git a/doc/reference/c++/arrays/h5_proxy.rst b/doc/reference/c++/arrays/h5_proxy.rst new file mode 100644 index 00000000..4aca7df5 --- /dev/null +++ b/doc/reference/c++/arrays/h5_proxy.rst @@ -0,0 +1,47 @@ +.. highlight:: c + +h5::array_proxy : a simple proxy to the array in file +=========================================================== + +The principle is that `array_proxy` is a proxy to an array, possibly big, in the h5 file. +It has a domain, and can be assigned from/to an array and sliced. +This allows to read/write only parts of a large array using the same slicing syntax +as for the array class itself (which is then translated into the hyperslab technique of the HDF5 library). + + +Tutorial +----------- + +* Write a "big" array in the h5 file and write it slice by slice:: + + #include + using namespace triqs::arrays; + + h5::H5File file( "ess.h5", H5F_ACC_TRUNC ); + + // first create a 'big' array in the file (no temporary is made in memory, it uses directly the HDF5 API). + const size_t N = 100; + h5::array_proxy Pn( file, "Z", make_shape(N,2,2) ); + + // a slice... + array the_slice (2,2); the_slice() = 1; + + // write the large array slice by slice + for (int u = 0; u + using namespace triqs::arrays; + + h5::H5File file ("ess.h5", H5F_ACC_RDONLY ); + h5::array_proxy P(file, "A"); + + array a_slice ; + for (int u = 0; u` for this class. + diff --git a/doc/reference/c++/arrays/h5_rw.rst b/doc/reference/c++/arrays/h5_rw.rst new file mode 100644 index 00000000..78edb45b --- /dev/null +++ b/doc/reference/c++/arrays/h5_rw.rst @@ -0,0 +1,38 @@ +.. highlight:: c + +Simple read/write operations of an array (or a view) +============================================================================ + +Given an array (or an array_view), the functions `h5::write` and `h5::read` write and read it to/from the file +or any subgroup thereof. For example : + +.. compileblock:: + + #include + using triqs::arrays::array; using triqs::arrays::matrix; + int main(){ + + array A(2,2); A() = 3; // declare and init + + H5::H5File file("store_A.h5",H5F_ACC_TRUNC); // open the file + h5_write(file,"A",A); // write the array as 'A' into the file + + //array B; // read the file into B + matrix B; // read the file into B + h5_read (file, "A",B); + std::cout << "B = "< REF TO COMPLEX + +Reference +------------ + +Here is the :doxy:`full C++ documentation` for this class. + + +Tutorial +----------- + +A simple example with a stack of double: + +.. literalinclude:: examples_code/h5_stack_ex_sca.cpp + +A simple example with a stack of array of rank 2 : + +.. literalinclude:: examples_code/h5_stack_ex.cpp + + + diff --git a/doc/reference/c++/arrays/introduction.rst b/doc/reference/c++/arrays/introduction.rst new file mode 100644 index 00000000..d074a4af --- /dev/null +++ b/doc/reference/c++/arrays/introduction.rst @@ -0,0 +1,38 @@ +Rational +=========================== + +.. highlight:: c + + +This library provides a multi-dimensionnal array library +for numerical computations with the following characteristics/goals : + +* **Simplicity of use**. + + Arrays must be as simple to use as in python (numpy) or fortran. + This library is designed to be used by physicists, not only by professionnal programmers, + We do *a lot* of array manipulations, and we want to maintain *readable* codes. + +* **Genericity, abstraction and performance** : + + We want to have simple, readeable code, with the same (or better) speed than manually written low level code. + Most optimisations should be delegated to the library and the compiler. + +* **Complete interoperability with python numpy arrays**. + + This library is used a lot with mixed C++/python codes. + It handles quick conversion between the C++ and python world, e.g. : + + * work on a view of a numpy, + * create a array in C++, and return it as a numpy. + * mix the various kind of arrays transparently in C++ expressions and in cython code. + +* **HDF5** : simple interface to hdf5 library for an easy storing/retrieving into/from HDF5 files. + +* **Simple interface to (some) blas/lapack** for matrices, vectors. + +* **MPI** : compatibility with boost::mpi interface. + + + + diff --git a/doc/reference/c++/arrays/lazy.rst b/doc/reference/c++/arrays/lazy.rst new file mode 100644 index 00000000..4ecc5b50 --- /dev/null +++ b/doc/reference/c++/arrays/lazy.rst @@ -0,0 +1,49 @@ +.. highlight:: c + +.. _Lazy: + +Interaction with clef expressions +============================================ + +* The Value and View classes (array, matrix and vector and algebraic expression of them) + are ready to use with the triqs::clef library : + + * They can be called on lazy expressions made of placeholders. + + * Automatic assignment has been set up. Cf clef lib doc ... + +* Using the clef library offers a quick and efficient way to fill an array with multiple advantages : + + * It is simpler and more readeable than a series of for loops. + * It is usually more optimal since the for loops are automatically written in the TraversalOrder of the + array. + +* NB : the expression can be (and are) inlined by the compilers... + +* **Example** : + +.. compileblock:: + + #include + using triqs::arrays::array; using triqs::clef::placeholder; + + int main(){ + placeholder<0> i_; placeholder<1> j_; + array A(2,2), B(2,2); + + A(i_,j_) << i_ + 2*j_ ; + + B(i_,j_) << A(j_,i_)/2; + + std::cout << "A = "< + #include + using triqs::arrays::vector; using triqs::arrays::range; + int main () { + triqs::arrays::vector V(3), W(3); + V() = 3; W()=5; // initialize + auto VV = V(range (0,2)); + auto VW = W(range (0,2)); + + std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + deep_swap(V,W); + std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + deep_swap(VV,VW); + std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + } + + + diff --git a/doc/reference/c++/arrays/options.rst b/doc/reference/c++/arrays/options.rst new file mode 100644 index 00000000..7a677e89 --- /dev/null +++ b/doc/reference/c++/arrays/options.rst @@ -0,0 +1,79 @@ +.. highlight:: c + +.. _option_template: + +Options template parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The `Option::options` template can take several parameters that determine various aspects of `array` (resp. `matrix`, `vector`) at **compile time**. +These parameters can be given in any order in the `options` template, but only at most only (they all have a default, that can also be changed +using macros for maximum flexibility). +These options parameters determine : + +* the storage order of indices in memory at **compile time**. + + =============================== =========================================================================================== + Template parameter Meaning + =============================== =========================================================================================== + `Tag::C` `[default]` C-style order + `Tag::Fortran` Fortran-style order ( NB the base index is still 0, not 1 !) + memory_order The tuple of size rank determines the storage order of indices in memory + memory_order_p

P is a triqs::arrays::Permutations::permutation that determines the storage order in memory + P[0] is the fastest index, P[rank - 1] the slowest index + =============================== =========================================================================================== + + Example of custom order :: + + custom > // same as index_order_Fortran, the first index is the fastest + custom > // same as index_order_C, the last index is the fastest + custom > // if indices are (i,j,k) : index j is fastest, then k, then i + +* whether bound check are done while accessing array elements or slicing the arrays. + + =============================== ==================================================================================================== + Template parameter Meaning + =============================== ==================================================================================================== + `Tag::NoBoundCheck` `[default]` Do no bound check at all. This is the default, for speed ! + `Tag::BoundCheck` Do bound checks. Boundary errors throw triqs::arrays::key_error exception (See ??) + =============================== ==================================================================================================== + + The macro `TRIQS_ARRAYS_ENFORCE_BOUNDCHECK` change the default to `Tag::BoundCheck` (for debugging purposes). + + Rational : one may want for some array to activate bound check and catch the exception, while keeping faster unchecked arrays elsewhere. + +* whether arrays are initialized at construction. + + =============================== ==================================================================================================== + Template parameter Meaning + =============================== ==================================================================================================== + `Tag::no_init` `[default]` No initialization of the array at construction (fastest). + `Tag::default_init` Initialize with the default constructor of ValueType + `Tag::nan_inf_init` Initialize to nan for floating type and std::limits::infinity() for integer type + as in D e.g. mainly for detecting easily lack of initialization errors. + =============================== ==================================================================================================== + + Note that : + + * The macro `TRIQS_ARRAYS_ENFORCE_INIT_NAN_INF` change the default to `Tag::nan_inf_init`. + * The macro `TRIQS_ARRAYS_ENFORCE_INIT_DEFAULT` change the default to `Tag::default_init`. + +* Several simple aliases are defined in the namespace Option for the most current cases : + + =============================== =============================== + Option aliases + =============================== =============================== + Option::C Option::options<`Tag::C`> + Option::Default Option::options<`Tag::C`> + Option::Fortran Option::options<`Tag::Fortran>` + =============================== =============================== + + +* Examples :: + + array > > A0 (2,3,4); + array > > A1 (2,3,4); + array > > A2 (2,3,4); + array A4 (2,3,4); + + + diff --git a/doc/reference/c++/arrays/python_tools.rst b/doc/reference/c++/arrays/python_tools.rst new file mode 100644 index 00000000..a3055493 --- /dev/null +++ b/doc/reference/c++/arrays/python_tools.rst @@ -0,0 +1,18 @@ +.. highlight:: c + +:: + + namespace Py_to_C { + template struct convert{ + static bool possible (boost::python::object x); // returns true iif the conversion of x into a T is possible + static T invoke(boost::python::object x); // do it ! + }; + } + + namespace C_to_Py { + template struct convert { + static boost::python::object invoke (T const & x); // convert T into a python object + }; + } + + diff --git a/doc/reference/c++/arrays/shape.rst b/doc/reference/c++/arrays/shape.rst new file mode 100644 index 00000000..62213a27 --- /dev/null +++ b/doc/reference/c++/arrays/shape.rst @@ -0,0 +1,50 @@ +.. _Shape: + +Shape, resize +================================== + +Lengths +---------- + + +Shape +-------------------- + +* array, matrix and vector have a method shape() that returns a `shape_type` object + i.e. a mini_vector. DOCUMENT THIS ? + +* Example:: + + array A(2,3); + A.shape()[0] == 2; + A.shape()[1] == 3; + +Resize +-------- + +* The value classes array, matrix and vector can be resized. + +* **Synopsis**: + + .. cpp:function:: void resize(size_t, ..., size_t) + +* **Examples** :: + + array A(2,3); + A.resize ( make_shape (5,5) ) + + matrix M; + M.resize( 3,3); + + vector V; + V.resize(10); + +* Views can not be resized. + +resize_or_check_if_view +---------------------------- + +.. cpp:function:: void resize_or_check_if_view(ArrayType const & A, shape_t) + +* If A is a value : resize A +* If A is a view : check that the shape if the shape_t and throw an exception if not. diff --git a/doc/reference/c++/arrays/slicing.rst b/doc/reference/c++/arrays/slicing.rst new file mode 100644 index 00000000..daf271c6 --- /dev/null +++ b/doc/reference/c++/arrays/slicing.rst @@ -0,0 +1,101 @@ +.. highlight:: c + +Partial views +================================== + +Various kind of partial views and slices can be made on arrays and matrices. + +* A `partial view` is defined as a view of a restricted portion of the array while + a `slice` is strictly speaking a partial view of a lower dimension of the original array, + e.g. a column of a matrix. + +* Partial views uses the ( ) operator, as the evaluation of the array:: + + array A(10,10); // defines an array + + A ( 1, range(0,2) ) // 1d slice + A ( 1, range() ) // 1d slice taking all the second dim + + A( range(0,10,2), range(0,10,2)) // a 2d slice viewing every each elements with even coordinates. + + array_view SL( A(0,range(0,3))); // naming the view + auto SL = A(0,range(0,3)); // C++0x with auto [check this] + +* **Return type** : + + * Partial views of array or array_view return an array_view. + * Partial views of vector or vector_view return an vector_view. + * 2d partial views of matrix or matrix_view return matrix_view. + * BUT : (1d) slices of matrix or matrix_view return vector_view. + * 0d slices of anything are converted to the `value_type` of the array. + +The `range` type +^^^^^^^^^^^^^^^^^^^^^ + + `range` mimics the python `range`. It can be constructed with : + + * no argument : it then takes the whole set of indices in the dimension (like `:` in python) :: + + A(range(), 0) // take the first column of A + + * two arguments to specify a range :: + + A(range (0,3), 0) // means A(0,0), A(1,0), A(2,0) + + .. warning:: + the second element is excluded : range(0,3) is 0,1,2, like in Python. + + * three arguments : a range with a step :: + + A(range(0,4,2), 0) // means A(0,0), A(2,0) + + +The `ellipsis` type +^^^^^^^^^^^^^^^^^^^^^^ + +* Ellipsis can be provided in place of `range`, as in python. The type `ellipsis` is similar to range + except that it is implicitely repeated to as much as necessary. + +* Example: + + .. compileblock :: + + #include + using triqs::arrays::array; using triqs::arrays::ellipsis; + int main(){ + array B(2,3,4,5) ; + B(0,ellipsis(),3) ; // same as B(0, range(),range(), 3 ) + B(0,ellipsis(),2,3); // same as B(0, range(), 2, 3 ) + B(ellipsis(),2,3) ; // same as B( range(),range(), 2, 3 ) + } + + +* NB : there can be at most one ellipsis per expression (otherwise it would be meaningless). + +* Example of usage : + + Ellipsis are useful to write generic algorithms. For example, imagine that you want to sum + arrays on their first index : + + .. compileblock :: + + #include + using triqs::arrays::array; using triqs::arrays::ellipsis; + + // a generic function that sum array, array_view or in fact anything + // with the right concept on its first dimension + template + array sum0 (ArrayType const & A) { + array res = A(0,ellipsis()); + for (size_t u =1; u< A.len(0); ++u) res += A(u,ellipsis()); + return res; + } + + // test + int main(){ + array A(5,2); A()=2; + array B(5,2,3); B() = 1; + std::cout<< sum0(A) << sum0(B) < class vector_view; + template class vector; + + ============================ ================================== ========================== ==================================================================== + Template parameter Accepted type Access in the class Meaning + ============================ ================================== ========================== ==================================================================== + ValueType normally a scalar, but any default value_type The type of the element of the vector + constructible type (?). + Opt Option::options< ...> opt_type Compile time options, see below. + ============================ ================================== ========================== ==================================================================== + +Options template parameters are described :ref:`here `. +The memory order is obviously useless here... + +.. _vector_constructors: + +Constructors +----------------- + +Intentionally, vector and vector_view have only a few constructors : + +========================================== =========================================================================================== +Constructors of vector Comments +========================================== =========================================================================================== +vector() - empty vector of size 0 +vector(size_t) - from the dimension. Does **NOT** initialize the elements of the vector to 0 ! +vector(const vector &) - copy construction +vector (PyObject * X) - Construct a new vector from the data of the Python object X. + NB : X is a borrowed reference, vector does affect its counting reference. + - it takes a **copy** of the data of X (or of numpy(X)) into C++. + - X is first transformed into a numpy by the python numpy lib itself + (as if you call numpy.array(X)) if X is not a numpy array or an array of the wrong type + (e.g. you construct an vector from a numpy of int....). +vector(const T & X) - Type T models the :ref:`HasImmutableArrayInterface` concept. + - X must have the appropriate domain (checked at compile time). + - Constructs a new vector of domain X.domain() and fills it with evaluation of X. +========================================== =========================================================================================== + +* Examples :: + + vector A(10,2); + A()=0; // init A to 0 + +.. warning:: + The constructor from the dimensions does **NOT** initialize the vector to 0 + (because it may not be optimal). + If needed, do it explicitely by `a()=0`; + +Constructors of vector_views +---------------------------------------------- + +Automatic construction +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +vector_view are normally automatically constructed by making (partial) views, ref:`Slicing`, e.g. :: + + tqa::vector A(2,2); + A(range(),2) ; // --> this makes a view... + A() ; // --> this makes a view over the full array + + +Explicit construction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To explicitly make a view of an vector, use make_view :: + + vector A(2,2); + make_view(A) //-> a view... + make_view(A) = 13 ; // to assign e.g. + + + +====================================================================== =========================================================================================================== +Constructors of vector_view Comments +====================================================================== =========================================================================================================== +vector_view(const array_view &) - Copy construction (shallow copy) +vector_view(const T & X) - `[Advanced]` T is any type such that X.indexmap() and X.storage() can be used to construct a view. +====================================================================== =========================================================================================================== + + diff --git a/doc/reference/c++/arrays/view_or_not_view.rst b/doc/reference/c++/arrays/view_or_not_view.rst new file mode 100644 index 00000000..987632a5 --- /dev/null +++ b/doc/reference/c++/arrays/view_or_not_view.rst @@ -0,0 +1,54 @@ +.. highlight:: c + +A fundamental distinction : value classes vs view classes +================================================================= + +A fundamental distinction in TRIQS is the difference between the `value class` +and the corresponding `view classes`. + +* The **value classes** : e.g. array, matrix, vector, ... have a `value semantic` : + + * They are default constructible. + * When copied, assigned, they make deep copy. + * They resize themselves under assignment if necessary (like e.g. std::vector). + + In many respect, they behave like a std::vector for these matters. + +* The **view classes** : e.g. array_view, matrix_view, vector_view, ... have a `reference semantic`. + + * They are just partial or complete views of the corresponding value class. + * They never make deep copy, either in copying, constructing, transforming to python, + * They can not be resized. + * They are useful to work on arrays, matrices, or on some part thereof, without making copies + (e.g. on a slice of an array, a column of a matrix). + + +Each class is therefore provided in two flavors, and it is crucial for the user +to learn and understand their difference in order to use them appropriately. + +This distinction extends to more complex objects in TRIQS, such as Green functions. + + +Behaviour comparison table between value and view classes +------------------------------------------------------------ + +A detailed comparison of the behaviour of the two type of classes is provided in the following table. + + +=================== ======================================================================= ====================================================================================== +Topics value class (e.g. array, matrix, vector) view (e.g. array_view, matrix_view, vector_view) +=================== ======================================================================= ====================================================================================== +Contructors - Constructors create a new fresh memory block. - Constructors only make another view of the data. +Default Contructor - Default constructor creates an empty array - No default constructor (what would it view ?). +Copy contructors - Create a new fresh memory block. - Make another view of the data (shallow copy). + - Make a *true* copy of the data. - *Never* copy data, so they are quite quick. +Assignment (=) - The assignment operator creates a new datablock if size mismatchs. - The assignment operator just copy data into the view. + - Hence, assignment never fail for size reason Behaviour is undefined if the size of the view is too small. + (unless there is a memory allocation exception of course) (it throws if the array has option `Tag::BoundCheck` or if + `TRIQS_ARRAYS_ENFORCE_BOUNDCHECK` is defined, Cf below). +Resizing - Can be resized, invalidating all references/pointers to the data. - Can be not be resized. +Invalidation - References/pointers to the data may become invalid after resize, - References/pointers to the data are still valid after assignment. + or assignment. +Data Contiguity - The data are contiguous in memory. - The data may not be contiguous in memory (e.g. a slice). +=================== ======================================================================= ====================================================================================== + diff --git a/doc/reference/c++/arrays/views.rst b/doc/reference/c++/arrays/views.rst new file mode 100644 index 00000000..0148b7f9 --- /dev/null +++ b/doc/reference/c++/arrays/views.rst @@ -0,0 +1,66 @@ +.. highlight:: c + +View classes and their constructors +============================================================================== + +* A view class (array_view, matrix_view, vector_view) is used to present a + partial (or complete) view of an array, matrix, vector. + Basically it should be understood as a reference to the data of the viewed object, + dressed to model the :ref:`MutableArray` concept. + +* A view class behaves like the value class when called, put in expression, ... + but differs from it by its behaviour under copy and assignment. + It has a reference semantics : like a pointer or a reference, it does not make a deep copy of the data + when copied. + +* There are two ways to make a view : + + * explicit construction, by calling a constructor or the make_view function + * automatic construction : views are the results of slicing the array + +* In the following, we will discuss only array_view, since matrix_view and vector_view + behaves exactly in a similar way. + +Explicit construction of a view +---------------------------------------- + +====================================================================== ===================================================================================================== +Constructors of array_view Comments +====================================================================== ===================================================================================================== +array_view(const array_view &) Copy construction (makes a shallow copy) +array_view(const T & X) T is any type such that X.indexmap() and X.storage() can be used to construct a view. + REF to concept here .... +====================================================================== ===================================================================================================== + +The function make_view can also be used to make a view. + +Example :: + + array A(2,2); + array_view V(A); + auto V2 = make_view(A); + + struct view_keeper { + array_view V; + +Memory management +------------------------ + +View classes contains a reference counting system to the memory block they view +(i.e. a std::shared_ptr). + +This guarantees that memory will not be dellocated before the destruction of the view. + +The memory block will be dellocated when its array and all array_view +pointing to it or to a portion of it will be destroyed, and only at that moment. + +Example:: + + array *p = new array (2,3); // create an array p + array_view B(*p); // making a view + delete p; // p is gone... + B(0,0) = 314; cout<` for these classes and functions. + + + diff --git a/doc/reference/c++/arrays_old/IO.rst b/doc/reference/c++/arrays_old/IO.rst new file mode 100644 index 00000000..e07d3d36 --- /dev/null +++ b/doc/reference/c++/arrays_old/IO.rst @@ -0,0 +1,44 @@ +.. highlight:: c + +MPI and serialization +########################################## + +Serialization +============================ + +The `value classes` and the views are compatible with Boost Serialization library. + +MPI +============================ + +The `value classes` (array, matrix, vector) can be bcasted, reduced, +with the boost.mpi library. + + Example:: + + #include < + #include + #include + using namespace triqs::arrays; + namespace mpi=boost::mpi; + + int main() { + mpi::environment env(argc, argv); + mpi::communicator world; + + array A (2,2), B(2,2),C(2,2); + for (int i =0; i<2; ++i) + for (int j=0; j<2; ++j) + { A(i,j) = (1+world.rank())*(10*i+ j);} + + if (world.rank() ==0) cout<<" A = "< >(),0); + + int s= world.size(); + if (world.rank() ==0) cout<<" C = "<( (s*(s+1)/2) * A) < :: + + boost::python::object C_to_Py::convert::invoke (T const & x); // convert T into a python object + +* The opposite conversion consists in constructing a C++ object from the boost::python::object:: + + Py_to_C::convert::possible(boost::python::object x); // returns true iif the conversion of x into a T is possible + T Py_to_C::convert::invoke(boost::python::object x); // do it ! + +* T can be : + + * array, array_view, matrix, matrix_view, vector, vector_view + + * [this is not array lib but triqs] any std::vector, std::pair, boost::unordered_map of those, recursively. + ---> cf the doc of this converters + + +Copy vs View +----------------------- + + The python conversion of the array and array_view follows the policy of the C++ classes : + + * `value classes` (array, matrix, vector) **always** make copies : + + * when returning to python : they present a fresh copy of the data. + * when being contructed from python data, they make their own copy. + + * `view classes` **never** make copies : + + * when returning to python : they return a numpy, which is a view of their data. + By doing this, they transfer ownership of the data to the python interpreter. + Cf memorymanagement. + + * when being contructed from python data, they make view. + If this is not possible (e.g. the python object is not a numpy, but a list, the type are not exactly the same) + they throw an exception (`triqs::runtime_error`). + +Interfacing, wrapping +--------------------------- + +* boost.python + + These converters can be registered to build regular boost.python converter, using, e.g. :: + + triqs::python_tools::register_converter< triqs::arrays::array > (); + +* swig : not implemented [ to do : add the typemap] + + +Examples +----------------------- + + +Example 1 : wrapping a simple function with Boost Python +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* The problem we want to solve : + +- write a simple function in C++ taking an array, and compute something from it. +- wrap this function and use it from python. + +* The function :: + + array_view f( array_view A) { + A(0,0) = 34; // do something + } + +* The wrapping code :: + + #include + #include + BOOST_PYTHON_MODULE(_testarray) { + using namespace boost::python; + triqs::python_tools::register_converter< triqs::arrays::array_view > (); + def("f", f); + } + +* Use it in a python code. + + .. code-block:: python + + import numpy,_testarray + a=numpy.array([[1.0,2],[3,4]]) + _testarray.f(a) + + +Example 2 : wrapping a simple function with Boost Python +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* A variant: we can be more explicit in the type conversion + (in this case, we don't need to register the converter, since we do the job ourselves). + + +* The function :: + + boost::python::object f( boost::python::object M ) { + array_view A(M.ptr()); // make a view of M. Throws if impossible + A(0,0) = 100; // do something + return M; // return it + } + + +* The wrapping code :: + + #include + #include + BOOST_PYTHON_MODULE(_testarray) { + using namespace boost::python; + def("f", f); + } + +* Use it in a python code. + + .. code-block:: python + + import numpy,_testarray + a=numpy.array([[1.0,2],[3,4]]) + print _testarray.f(a) + + + + diff --git a/doc/reference/c++/arrays_old/Iterators.rst b/doc/reference/c++/arrays_old/Iterators.rst new file mode 100644 index 00000000..8ad8b176 --- /dev/null +++ b/doc/reference/c++/arrays_old/Iterators.rst @@ -0,0 +1,2 @@ +.. highlight:: c + diff --git a/doc/reference/c++/arrays_old/STL.rst b/doc/reference/c++/arrays_old/STL.rst new file mode 100644 index 00000000..86c38c78 --- /dev/null +++ b/doc/reference/c++/arrays_old/STL.rst @@ -0,0 +1,92 @@ +.. highlight:: c + +Compatibility with STL and iterators, Interaction with STL +################################################################## + +The arrays are compatible with STL containers and algorithms. + +Iterators +================ + + Standard iterators are provided that model the boost Mutable_ForwardIterator and ForwardIterator concepts + (and hence are STL compliant). + + The iterator implements also two additionnal methods : + + * it can be casted to a bool : it is true iif the iteration is not at end. + * it.indices() : returns const & to the indices at the point of the iteration. + + Examples:: + + array A (2,3); + for (auto it = A.begin(); it; ++it) *it =it.indices()[0] + 10 *it.indices()[1] ; + //for (array::iterator it = A.begin(); it; ++it) *it =it.indices()[0] + 10 *it.indices()[1] ; + +Indices generators +================================ + +The domain have an index generator that enumerates the indices in the domain. + +Examples:: + + array A (2,3); + + for (auto it = A.indexmap().domain().begin(); it; ++it) cout<<" "<<*it<::indexmap_type::domain_type, Permutations::permutation<0,1> > it_type; + for (it_type it(A.indexmap().domain()); it; ++it) cout<<" "<<*it<()); it; ++it) cout<<" "<<*it< A (2,3); + std::vector > VV; + VV.push_back(A); + +* ... or a map :: + + std::map > MAP; + MAP["1"] = A; + +* We can put a std::vector in an array ... :: + + std::vector V (10); + array B(V.size()), C(V.size()); + std::copy(V.begin(),V.end(),B.begin()); + +* ... or in reverse :: + + std::copy(B.begin(),B.end(),V.begin()); + +* ... or use other algorithms of std:: + + bool te(int x) { return (x<25);} + //.... + cout<<" max(B) "<< *std::max_element(B.begin(),B.end())< or + files. + +For example :: + + array A (2,2), B(2,2),C; + C= A + 2*B; + array D( A+ 2*B); + array F( 0.5 * A); // Type promotion is automatic + +The technique is called `expression templates`. It allows the elimination of temporaries, so that the clear +and readable code:: + + Z= A + 2*B + C/2; + +is in fact rewritten by the compiler into :: + + for (i,j,...) indices of A, B : + C(i,j) = A(i,j) + 2* B(i,j) + C(i,j)/2 + +instead of making a chain of temporaries (C/2, 2*B, 2*B + C/2...) that "ordinary" object-oriented programming would produce. +As a result, the produced code is as fast as if you were writing the loop yourself, +but with several advantages : + +* It is more **compact** and **readable** : you don't have to write the loop, and he indices range are computed automatically. +* It is much better for **optimization** : + + * What you want is to tell the compiler/library to compute this expression, not *how* to do it optimally on a given machine. + * For example, since the memory layout is decided at compile time, the library can traverse the data + in an optimal way, allowing machine-dependent optimization. + * The library can perform easy optimisations, e.g. for vector it will use blas if possible. + +Arrays vs matrices +---------------------- + +Because their multiplication is not the same, arrays and matrices don't form the same algebra. +Mixing them in expression would therefore be meaningless and it is therefore not allowed :: + + array A; + matrix M; + M + A; // --> ERROR + +However, you can always make a matrix_view from a array of rank 2 :: + + A + make_matrix_view(M); //--> OK. + +.. note:: + + Making view is very cheap, it only copies the index systems. + +Expressions are lazy +--------------------------- + +This means that constructing an expression is separated from evaluating it :: + + auto e = A + 2*B; // expression, purely formal, no computation is done + cout<< e < D(e); // now really makes the computation and store the result in D. + +The expression type is complicated (the expression in stored in the C++ type), so we used here +the C++0x `auto` to make simple things simple... + +FAQ +---------- + +Where can expressions be used ? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Expressions models :ref:`HasImmutableArrayInterface` concept, so they can used *anywhere* +an object modeling this concept is accepted, e.g. : + +* array, matrix contruction +* operator =, +=, -=, ... + +They behave like an immutable array : they have a domain, they can be evaluated. +When `C` is assigned to the expression in the previous example, +the compiler just needs to compute the new domain for `C`, resize it and fill it by evaluation of the expression. + +What is the cost of this technique ? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Thanks to the Boost Proto library, this can be done : + +* with an acceptable increase in compilation time (try it !). +* in about *2 pages of readable code* ! + diff --git a/doc/reference/c++/arrays_old/all.rst b/doc/reference/c++/arrays_old/all.rst new file mode 100644 index 00000000..3b6a4376 --- /dev/null +++ b/doc/reference/c++/arrays_old/all.rst @@ -0,0 +1,361 @@ +.. highlight:: c + +array and array_view +============================ + +array and array_view are the class for standard d-dimensional cuboid array +and the corresponding view. + +Template parameters +---------------------------- + +* The class has four template parameters (same for array_view). + + .. code-block:: c + + array + + + ============================ ========================== ======================================= + Template parameter Access in the class Meaning + ============================ ========================== ======================================= + ValueType value_type The type of the element of the array + Rank rank The rank of the array *[int]* + IndexOrderTag indexmap_type The ordering in memory : can be Tag::C, Tag::Fortran or a permutation + StorageTag storage_type The storage : Tag::shared_block or Tag::numpy + ============================ ========================== ======================================= + + +* Various IndexOrderTag are possible : + + ================= ==================================================================================================== + IndexOrderTag Meaning + ================= ==================================================================================================== + Tag::C C-style order *[default]* + Tag::Fortran Fortran-style order + P - P is a permutation + - Determined by a permutation P at compile time. Explain here the permutation, the convention. + ================= ==================================================================================================== + + +* Two possible storages : + + ================== ============================================================================ + StorageTag Meaning + ================== ============================================================================ + Tag::shared_block a (shared_ptr on a) C++ block *[default]* + Tag::numpy stored in a numpy array, in which case the array is also a numpy array + and read numpy, be returned as numpy, sliced into a numpy, etc... + ================== ============================================================================ + + +.. _array_constructors: + +Constructors +----------------- + +Intentionally, array and array_view have only a few constructors : + +========================================== =========================================================================================== +Constructors of array Comments +========================================== =========================================================================================== +array() - empty array of size 0 +array(size_t, ...., size_t) - from the dimensions +array(cuboid_domain const &) - a new array with the corresponding cuboid +array(const array &) - copy construction +array(const T & X) - Type T models the :ref:`HasImmutableArrayInterface` concept. + - X must have the appropriate domain (checked at compile time). + - Enabled iif has_immutable_array_interface::value == true. + - Constructs a new array of domain X.domain() and fills it with evaluation of X. +========================================== =========================================================================================== + +====================================================================== ======================================================================================= +Constructors of array_view Comments +====================================================================== ======================================================================================= +array_view(indexmap_type const & I, S_type const &) from a couple of indexmap I and storage of type S_type +array_view(const T & X) T is any type such that X.indexmap() and X.storage(). Models ISP ... +====================================================================== ======================================================================================= + +array_view are typically constructed by slicing (Cf below). + +* Examples :: + + array A(10,2); + array Af (2,2); + + //Higher dim, custom order : + array > A0 (2,3,4); + array > A1 (2,3,4); + array > A2 (2,3,4); + array A3 (2,3,4); + array A4 (2,3,4); + + +Access to data, domain, simple evaluation, ... +-------------------------------------------------------- + +array, array_view, matrix, matrix_view, vector, vector_view model HasImmutableArrayInterface. + + +Assignment & Copy +-------------------- + +Every classes comes in two flavors: C and C_view (with C = array, matrix, vector, etc...). +These two flavors differ in the way they handle their data in construction, copy construction, assignement. +Basically, C owns its data, while C_view if only a view. + +array, matrix, vector +^^^^^^^^^^^^^^^^^^^^^^^^ + +They own their data. In many aspects, they are similar to like std::vector. + +* The data are contiguous in memory. +* Constructors and copy constructors all create a new memory block. If needed, they + make a *true* copy of the data. +* The assignment operator may create a new Storage if size do not match. +* As a result, /pointers to the data/ and reference to the storage are invalid after assignment. +* They can be resized, again invalidating all references. + +array_view, matrix_view, vector_view +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These classes do not own their data, but only present a view of them. + +* The data may not be contiguous in memory (e.g. if the view is the result of a slice). +* Constructors only make another view of the data. +* They *never* copy data, so they are quite quick. + In particular, copy constructor makes shallow copy (i.e. return another view). +* The assignement operator just copy data into the view. Behaviour is undefined if the + size of the view is too small (define the macro ARRAY_CHECK for dynamical debugging checks). +* Pointers to data taken from the views are still valid after assignement. +* Views can be not be resized. + +.. warning:: **Memory management** + + Views carry a reference to the memory block they view, + which guarantees that memory will not be + dellocated before the destruction of the view. + Indeed, the Storage types implement incorporated a reference counting mechanism, + either using boost::shared_ptr for the C++ arrays, or using the python references + for the numpy storage. + The memory block will be dellocated when its array and all array_view + pointing to it or to a portion of it will be destroyed, and only at that moment. + +Examples:: + + array *A = new array (Matrix(2,3)); // create an array A + array_view B(*A); // making a view + delete A; // A is gone... + cout< array & operator=(const RHS & X); + + * RHS models HasImmutableArrayInterface. + * array is first resized to have a domain X.domain(), and then filled + with the evaluation of X (e.g. a copy if X is an array, computing the value if X is an expression). + + +array_view, matrix_view, vector_view +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +//.. cpp:function:: + template array_view & operator=(const RHS & X); + + * RHS models HasImmutableArrayInterface [ or less ? : RHS can be evaluated in the domain_type::value_type, no domain needed.]. + * Dimension of the view must match or behaviour is undefined. + +Iterators and interaction with STL containers and algorithms +---------------------------------------------------------------- + +STL compliant iterators, hence STL algorithms work... + +Examples:: + + array A (2,3); + + // first print the index generator + for (array::indexmap_type::domain_type::generator it = A.indexmap().domain().begin(); !it.at_end(); ++it) + cout<<" "<<*it<::iterator it = A.begin(); !it.at_end(); ++it) + { *it =it.indices().get<0>() + 10 *it.indices().get<1>() ; } + + int u=0; + for (array::iterator it = A.begin(); !it.at_end(); ++it,++u) { *it =u; } + + array A (2,3); + std::vector > VV; VV.push_back(A); + map > MAP; MAP["1"] = A; + + // Trying to put a vector in an array + std::vector V (10); + array B(V.size()), C(V.size()); + for (unsigned int i =0; i<10; ++i) V[i] = 10+i; + + std::copy(V.begin(),V.end(),B.begin()); + std::copy(B.begin(),B.end(),V.begin()); + cout<<" Number of elements <25 : "<< std::count_if(B.begin(), B.end(),te)< A (2,3); + array_view SL( A(range(0,2),0)); + array_view SL2( A(1,range(0,2))); + + +It is the standard way to produce a view. + +NB : + +* we use here the python convention: range(0,3) is 0:3, i.e. 0,1,2 NOT 0,1,2,3. +* Todo : in fact we should wrap the range to python::slice for interoperability with python. + +Serialization +------------------------------------------------- + +* Boost.serialization +* Boost.mpi + +Examples:: + + array A (2,2), B(2,2),C(2,2); + boost::mpi::reduce (world, A,C, std::plus >(),0); + + +* HDF5 (ALPS), eg. + +Examples:: + + array A (2,3),B,vc; + array Af,Bf,vf; + + alps::hdf5::oarchive ar1("data.h5"); + ar1 << alps::make_pvp("Tableau", A); + ar1 << alps::make_pvp("Tableau2", Af); + ar1 << alps::make_pvp("Tableau_view", A(range(),range(1,3))); + + alps::hdf5::iarchive ar2("data.h5"); + ar2 >> alps::make_pvp("Tableau", B); + ar2 >> alps::make_pvp("Tableau", Bf); + ar2 >> alps::make_pvp("Tableau_view", vc); + ar2 >> alps::make_pvp("TableauC",C); + + +blas/lapack interface +------------------------------------------------- + +* matrix, vector and their views are interfaced with blas/lapack, via boost::numerics::bindings. +* If needed (for a view), a temporary (and silent) copy is made to reorganize the +data before calling blas/lapack (impl: cache class). +Of course, performance is altered, but code is simple... + +Examples:: + + namespace blas = boost::numeric::bindings::blas; + namespace lapack = boost::numeric::bindings::lapack; + + triqs_arrays::vector > V(5),V2(5); + triqs_arrays::vector V3(2); + triqs_arrays::matrix M1(2,2), M2(2,2), M3(2,2); + + blas::axpy(2.0,V,V2); + blas::gemm(1.0,M1, M2, 1.0, M3); + blas::ger(1.0,V3,V3,M2); + + // invert + triqs_arrays::vector ipiv(2); + lapack::getrf(M1, ipiv); + lapack::getri(M1, ipiv); + +Transparent use of python arrays +------------------------------------------------- + +* If the storage is Tag::numpy, the memory block is allocated/viewed through the numpy interface. +* One can mix arrays with any storage in expression (they have the same concepts). +* boost python converters are enable for those arrays into numpy and their views [impl :broken for views]. + + +Expression +------------------------------------------------- + +Simple expressions are made using boost.proto. +Examples :: + + array A (2,2), B(2,2),C; + C= A + 2*B; + array D( A+ 2*B); + + // or even in C++0x : + auto e = A + 2*B; // expression, purely formal + array D(e); // really makes the computation + cout<< e < A (2,2), B(2,2),C(2,2); + C= A + 2*B; + C= std::plus >()(A,B); + C = A + Transpose(B); // Transpose(X) returns a lazy object that models HasImmutableArrayInterface. + C = A + Transpose(B + B); // X can also be an expression... + C = Transpose(B); // + array F( 0.5 * A); // Type promotion is automatic + + // non square + array R(2,3),Rt(3,2); + cout<<" R = "<< array(Transpose(R)) < M1(2,2), M2(2,2), M3; + for (int i =0; i<2; ++i) for (int j=0; j<2; ++j) { M1(i,j) = i+j; M2(i,j) = 1 + i -j ; } + + // The central instruction : note that matmul returns a lazy object + // that has ImmutableArray interface, and defines a specialized version assignment + // As a result this is equivalent to matmul_with_lapack(M1,M2,M3) : there is NO intermediate copy. + M3 = matmul(M1,M2); + + std::cout<<"M3 = "< > V(5),V2(5); + triqs_arrays::vector V3(2); + triqs_arrays::matrix M1(2,2), M2(2,2), M3(2,2); + + blas::axpy(2.0,V,V2); + blas::gemm(1.0,M1, M2, 1.0, M3); + blas::ger(1.0,V3,V3,M2); + + // invert + triqs_arrays::vector ipiv(2); + lapack::getrf(M1, ipiv); + lapack::getri(M1, ipiv); + diff --git a/doc/reference/c++/arrays_old/centralconcept.rst b/doc/reference/c++/arrays_old/centralconcept.rst new file mode 100644 index 00000000..aacc28a6 --- /dev/null +++ b/doc/reference/c++/arrays_old/centralconcept.rst @@ -0,0 +1,39 @@ +The central concept : HasImmutableArrayInterface +======================================================= + +The central concept used by the library (both in the colloquial and in the technical acceptance of the word) +is the notion of **Immutable Array Interface**. + +This is just a formal definition of what has an object has to implement ("which concept it has to model") +to look like an array. + +Basically, the answer is simple, an array is a (discrete) map between a domain of indices into an algebra +(typically R, ou C). Therefore it has to defined : + +* a domain of indices, which can be enumerated, e.g. cartesian products of integer ranges. +* an evaluation method [] so that a[ I ] has a `value_type` type for any index I in the domain. + +The precise concept if defined at :ref:`HasImmutableArrayInterface` concept. + +Examples : + +* a matrix has a domain of range(0,n1) x range(0,n2). +* a general array has a domain of dimension rank and values in R, C, other arrays... +* a triangular matrix has a more complex domain... +* any algebraic expression of arrays, matrices are like this (and those one are certainly NOT mutable objects !). + +* What is then a (partial) view/slice of an array ? + + Simply another map on the same data. + +* Do you want to see a 4 indices arrays as a matrix of double indices ? + + Simply change the map... + +* Why is this concept useful ? + + Because if you program another object of your own, which models it, + it is guaranteed to interact properly with arrays.... + + + diff --git a/doc/reference/c++/arrays_old/compound_ops.rst b/doc/reference/c++/arrays_old/compound_ops.rst new file mode 100644 index 00000000..a495d3e9 --- /dev/null +++ b/doc/reference/c++/arrays_old/compound_ops.rst @@ -0,0 +1,21 @@ +.. highlight:: c + +Compound operators (+=, -=, *=, /=) +====================================== + +The `value classes` and the `view classes` behaves similarly. +We will illustrate it on the `array` class, it is the same for `matrix` and `vector`. + + * **Syntax** + + The syntax is natural :: + + template array & operator += (const RHS & X); + template array & operator -= (const RHS & X); + template array & operator *= (const Scalar & S); + template array & operator /= (const Scalar & S); + + * **Behaviour** + + - Domain must match. + - X is evaluated and added term by term. diff --git a/doc/reference/c++/arrays_old/contents.rst b/doc/reference/c++/arrays_old/contents.rst new file mode 100644 index 00000000..8a5fd233 --- /dev/null +++ b/doc/reference/c++/arrays_old/contents.rst @@ -0,0 +1,33 @@ +Array library +**************** + +.. warning:: + This library is beta. + + This manual is not finished: work in progress. + + +.. highlight:: c + +.. toctree:: + :maxdepth: 1 + :numbered: + + introduction + getting_started + view_or_not_view + basic_classes + slicing + shape + debug + assignment + algebras + foreach + functional + STL + H5 + Interop_Python + IO + blas_lapack + FAQ + design/contents diff --git a/doc/reference/c++/arrays_old/debug.rst b/doc/reference/c++/arrays_old/debug.rst new file mode 100644 index 00000000..36891a98 --- /dev/null +++ b/doc/reference/c++/arrays_old/debug.rst @@ -0,0 +1,48 @@ + +.. highlight:: python + +.. _Debug: + +Bound checking and debug macros +=================================== + +To be fast, by default, no check are made on the indices while accessing elements or slicing. +However, checks can be activated in two ways : + +* Adding the `Tag::BoundCheck` option (in the options<...> template of the array, matrix, vector) + +* Defining the debug macro TRIQS_ARRAYS_ENFORCE_BOUNDCHECK, which switches the default option from `Tag::NoBoundCheck` to `Tag::BoundCheck` + for all arrays, matrices and vectors. + +In both cases, if the indices are not within the domain of defintion, an exception triqs::arrays::key_error +will be thrown. It's .what() returns the file and line where the exception occurs, with the stack of all in C++, +e.g. :: + + BOX>./bound_check_nopy + + catching key error in B + triqs::arrays key_error at ..../triqs_source/triqs/arrays/test/C++/./src/IndexMaps/cuboid/./cuboid_domain.hpp : 104 + + Trace is : + + ./bound_check_nopy void triqs::arrays::IndexMaps::cuboid_domain<2>::assert_key_in_domain > \ + (boost::tuples::tuple const&) const 0x181 [0x403e11] + ./bound_check_nopy main 0x916 [0x403016] + /lib/libc.so.6 __libc_start_main 0xfd [0x7f389e6abc4d] + ./bound_check_nopy [0x4023c9] + + key out of domain + key [1] = 3 is not within [0,3[ + +Further information on the line of the error in the stack can be retrieved with the addr2line utility `[linux only]` +which retrieve the source file and line from the address of the function (if you compile with -g). The script in TRIQS_SOURCE_DIR/dev_tools/analyse_stack.py +does it automatically for you (when compiled with -g) :: + + BOX> ./bound_check_nopy 2>&1 | analyse_stack.py + + .... + ./bound_check_nopy main 0x8a7 [0x403477] + ---> /home/parcolle/triqs_source/triqs/arrays/test/C++/bound_check.cpp:83 + + + diff --git a/doc/reference/c++/arrays_old/design/concepts.rst b/doc/reference/c++/arrays_old/design/concepts.rst new file mode 100644 index 00000000..fc5733a5 --- /dev/null +++ b/doc/reference/c++/arrays_old/design/concepts.rst @@ -0,0 +1,270 @@ + +Concepts +============================================================= + +BoostSerializable +------------------------------------------------- + +* define serialize for boost serialize library + +Printable +------------------------------------------------- + + ====================================================== =========================================================== + Elements Comment + ====================================================== =========================================================== + std::ostream & operator << (std::ostream & out, ...) Printing + ====================================================== =========================================================== + +Domain +------------------------------------------------- + +* **Purpose** : The domain of definition of the array, i.e. the possible value of the indices. +* **Refines** : BoostSerializable, Printable +* **Definition** : + + =========================================== =========================================================== + Elements Comment + =========================================== =========================================================== + * static const unsigned int rank rank + * index_value_type type of the multi-index + * default constructor, copy construction + * operator = + * operator ==, != + * size_t number_of_elements() const number of elements + * generator type of the IndexGenerator that generates the indices + * begin() const/ end() const a generator at start/end + =========================================== =========================================================== + +* **Examples** : + + Typically, this is is a multi-index for an array, matrix, ...., e.g. + + * Cuboid : standard hyperrectangular arrays. This is little more than the tuple of the lengths. + * triangle, .... ? + +.. _HasImmutableArrayInterface: + +HasImmutableArrayInterface +------------------------------------------------- + +* **Purpose** : The most abstract definition of something that behaves like an immutable array. + * it has a domain (hence a rank). + * it can be evaluated on any value of the indices in the domain + * By combining the generator of the domain with the evaluation, it is therefore easy to + iterate on the values of such an object. + * NB : It does not need to be stored in memory. A formal expression, e.g. model this concept. + +* **Definition** ([A|B] denotes that the return type maybe A or B). + + ================================================================================================== ============================================================= + Elements Comment + ================================================================================================== ============================================================= + value_type Type of the element of the array + domain_type Type of the domain. + [domain_type const & | domain_type] domain() const Access to the domain. + [ value_type | value_type const &] operator[] (domain_type::index_value_type const &) const Evaluation. + ================================================================================================== ============================================================= + +* **Examples** : + * array, array_view, matrix, matrix_view, vector, vector_view (all implemented as Indexmap_Storage_Pair) + * array expressions (in which case the returns are not const & since they are computed, not stored). + +IndexGenerator +------------------------------------------------- +* **Purpose** : Generate the indices of a domain. + +* **Definition** : + + ============================================================== ================================================================================================== + Elements Comment + ============================================================== ================================================================================================== + domain_type Type of the domain whose indices are generated. + default contruction, copy construction + construction from (domain_type const &, bool atend=false) + IndexGenerator & operator=(const IndexGenerator & ) + operator ++ + operator = + operator ==, != + domain_type::index_value_type const & operator * () const Access to the value of the multi-index + bool at_end() const True iif the generator has reached the last value + ============================================================== ================================================================================================== + + +* **Examples** : + + * cuboid_index_generator + +IndexMap +------------------------------------------------- + +* **Purpose** : + + * Store the mapping of the index domain to a linear array. + * It is basically a function : indices --> 1d position, the bijection between the indices + of an element and its position in the memory block. +* **Refines** : BoostSerializable, Printable +* **Definition** : + + ======================================================================== ================================================================================================== + Elements Comment + ======================================================================== ================================================================================================== + * domain_type The type of the domain. + * domain_type const & domain() const The domain. + * default constructor, copy construction Cpy is a true copy. + * can be constructed from domain_type const & + * size_t operator[] (domain_type::index_value_type const & key ) const The mapping itself. + * iterator A type modeling IndexMapIterator, which is the optimal memory traversal. + NB : the order of indices is chosen for optimal traversal of memory, it + does not need to be "natural". + cuboid_map also provides a natural_iterator for that purpose. + ======================================================================== ================================================================================================== + +* The type also has to define two free functions and to specialize a template : + + ========================================================== ================================================================================================== + Elements Comment + ========================================================== ================================================================================================== + * bool compatible_for_assignment (M1, M2) Returns whether an array/matrix/vector with map M1 can be equated to a array/matrix/vector with + map M2 + * bool raw_copy_possible (M1, M2) Is the assignment of an array/matrix/vector with map M2 into an array/matrix/vector with map M1 + doable with raw copy + * struct indexmap_iterator_adapter< It, I > Metafunction : + + - I is the IndexMap class + - It any similar IndexMapIterator which returns (in ::type) the IndexMapIterator on I + with the same order traversal as It. + + Example : It is a IndexMapIterator on I1 stored in C order, I is in Fortran order, + the result will be an IndexMapIterator on I that presents the data of I in C order + This is used in copying array with different indexmaps. + ========================================================== ================================================================================================== + + +* **Examples** : + * cuboid_map : a map of the cuboid indices in a fixed order in memory. + +IndexMapIterator +------------------------------------------------- + +* **Purpose** : + * A basic iterator on an IndexMap which can be dereferenced into the shift of successive elements compared to the start of the memory block. + * These iterators are kept as simple as possible, so that it is easy to implement new indices maps and their iterators. + * NB : In particular, they are *not* necessary STL-compliant. The array_iterator class will + take such an iterator and a Storage and produce a true, STL compliant iterator on the array (iterator_adapter). + +* **Definition** : + + ========================================================== ================================================================================================== + Elements Comment + ========================================================== ================================================================================================== + indexmap_type The index_map on which the iterator is iterating + domain_type Type of the domain whose indices are generated. + default contruction, copy construction + construction from (domain_type const &, bool atend=false) + IndexMapIterator & operator=(const IndexMapIterator & ) + IndexMapIterator & operator ++ + operator ==, != + std::ptrdiff_t operator*() const Dereference as a shift from the beginning of the array + domain_type::index_value_type const & indices () const Access to the value of the multi-index at the iterator position + bool at_end() const True iif the generator has reached the last value (in practice quicker that it = XX.end()). + ========================================================== ================================================================================================== + +* **Example(s)** : + + * cuboid_map_iterator + +Storage +------------------------------------------------- + +* **Purpose** : + * The storage of the array in memory, e.g. plain C++ array, a numpy, etc... + * A Storage keeps the reference to the memory block where the array is stored. + * NB : This memory block can be typically shared between various arrays and views, + so the Storage is just a reference. The memory is deallocated only + when all storages referencing it has been destroyed. +* **Refines** : BoostSerializable +* **Definition** : + + ====================================================== ================================================================================================== + Elements Comment + ====================================================== ================================================================================================== + value_type Type of the element stored, e.g. int, const int, double, const double, ... + default construction Makes a storage of size 0 + copy construction a shallow copy (another reference to the same data). + the copy construction is possible from another storage of the same value_type + up to the const qualifier. + The construction of a storage with value_type=T from a storage with value_type const T + is forbidden at compile time. + void operator = (const STO &) A shallow copy of the reference to the data. + + clone() const Create a clone of the data. + const_clone() const Create a clone of the data with const value_type (e.g. int--> const int). + + void raw_copy_from(const STO & X) Copy all the data from X to *this. Behaviour undefined if sizes do not match. + + size_t size() const Number of elements in the storage + + value_type & operator[](size_t p) const Access to the data. Behaviour is undefined if empty()==true. + ====================================================== ================================================================================================== + + +* **Examples** : + * shared_block : basically a shared_ptr to a basic C++ array, dressed to model the Storage concept. + * numpy : a dressing of a python numpy object to model the Storage concept. + + +StorageOrder concept +------------------------------------------------- + +* **Purpose** : + + * Store the order of indices in memory. + * Can be fixed at compile time, or dynamically (not implemented). + +* **Refines** : BoostSerializable +* **Definition** : + + ====================================================== ================================================================================================== + Elements Comment + ====================================================== ================================================================================================== + size_t index_number(size_t i) + static unsigned int rank + default construction + copy construction + bool is_Fortran() const Is it Fortran-style ordering ? + bool is_C() const Is it C-style ordering ? + + ====================================================== ================================================================================================== + + +* The type also has to define the == operator : + + ========================================================== ================================================================================================== + Elements Comment + ========================================================== ================================================================================================== + Operator == Defined between any of the ordering. + ========================================================== ================================================================================================== + + +* **Examples** :: + + storage_order_C // canonical C ordering + + storage_order_fortran // canonical Fortran ordering + + storage_order_custom

// custom storage given by a permutation P + + * Details on the custom order : + + * P = [p_1,... p_r] : p_1 is the fastest index, p_r the slowest. + + * Example:: + + storage_order_C == storage_order_custom< Permutations::reverse_identity > + + storage_order_fortran == storage_order_custom< Permutations::identity > + + storage_order_custom > // the fastest index in memory is 0, then 1, then 2. + + diff --git a/doc/reference/c++/arrays_old/design/contents.rst b/doc/reference/c++/arrays_old/design/contents.rst new file mode 100644 index 00000000..80e6c14c --- /dev/null +++ b/doc/reference/c++/arrays_old/design/contents.rst @@ -0,0 +1,10 @@ +Design & Implementation +========================= + +.. toctree:: + :maxdepth: 2 + + strategy + slicing + concepts + cuboid_formula diff --git a/doc/reference/c++/arrays_old/design/cuboid_formula.rst b/doc/reference/c++/arrays_old/design/cuboid_formula.rst new file mode 100644 index 00000000..e2185c11 --- /dev/null +++ b/doc/reference/c++/arrays_old/design/cuboid_formula.rst @@ -0,0 +1,60 @@ + +.. _cuboid_formula: + +Cuboid formula +====================== + +* **Notations** : + + * R = rank + * index : (i0,...,i_{R-1}) + * Lengths : (L0, ... , L_{R-1}) + * Strides : (S0, ... , S_{R-1}) + * position = start_shift + \sum_{j=0}^{R-1} i_j S_j + +* **Strides for compact cuboid** : + + If :math:`\sigma(i)` is the i-th index in memory (0 the first, R-1 the last one), we have + + .. math:: + :nowrap: + + \begin{align*} + S_{\sigma(0)} &= 1\\ + S_{\sigma(1)} &= L_{\sigma(0)} S_{\sigma(0)} = L_{\sigma(0)}\\ + S_{\sigma(i)} &= L_{\sigma(i-1)} S_{\sigma(i-1)} = \prod_{j=i-1}^{0} L_{\sigma(j)} + \end{align*} + + +* **Slicing the cuboid** : + + + * Argument of the slice : (R0, R1, ..., R_{R-1}), with R_i = range : (start,end,step) + for the moment, if R_i = E_i, a number, consider it as a special range of length 1. + * new index (k0,...., k_{R-1}). + i_u = R_u.start + k_u * R_u.step + * Compute the new strides : Sn_j + + .. math:: + :nowrap: + + \def\offset{\text{offset}} + \begin{align*} + position &= \offset + \sum_{j=0}^{R-1} i_j S_j \\ + &= \offset + \sum_{j=0}^{R-1} (k_j* R_j.step + R_j.start) S_j \\ + &= (\offset + \sum_{j=0}^{R-1} (k_j* R_j.step + R_j.start) S_j ) + \sum_{j=0}^{R-1} k_j (S_j * R_j.start) + \\ + \offset_\text{new} &= \offset + \sum_{j=0}^{R-1} (k_j* R_j.step + R_j.start) S_j \\ + &= position( R_j.start) \\ + Sn_j &= S_j * R_j.start + \end{align*} + + * Now : for the cases R_i = E_i, just drop the index. + + + + + + + + diff --git a/doc/reference/c++/arrays_old/design/slicing.rst b/doc/reference/c++/arrays_old/design/slicing.rst new file mode 100644 index 00000000..6f21a8d4 --- /dev/null +++ b/doc/reference/c++/arrays_old/design/slicing.rst @@ -0,0 +1,51 @@ +.. _DesignSlicing: + +Slicing +============================================================= + +In this section, IM denotes some IndexMaps. + +* We refer here to any partial view of the arrays as "slicing", i.e. subarrays, true slices, etc... + A slicing is any (meta)-function that take an indexmap and return another one. + + * It is a meta-function that computes the type of the resulting indexmap + * It is a function that computes the resulting indexmap. + +* The array/matrix/vector classes and their views, when called with the () operator, will : + + * forward all the arguments and their types to IndexMaps::slice, to compute the new indexmap IM2. + * If IM2 is of dimension 0, return a value_type & or const & (it is a simple number, not an array). + * Otherwise : return a new view, made of IM2 and the same data as for the original object. + +* Possible slices are defined by the IndexMap type. + Slicing an class C with IndexMap I1 produces a class C2_view, with IndexMap I2, + i.e. a new sliced IndexMap on the same data. + +* **Examples** : + * array and array_view can be sliced : +`` + array A(10,10); : defines an array + A(1,2) : element access. + A ( 1, range(0,2) ) : 1d slice + A( range(0,10,2), range(0,10,2)) : a 2d slice viewing every each elements with even coordinates. +`` + * matrix, matrix_view when sliced, return vector_view or matrix_view. + +* One can be much more general : e.g. slicing the diagonal of a matrix, etc... + + + +* Implementation is entirely done in the IndexMaps classes, by specializing 2 templates + (basically by writing the function IM1-> IM2). + The rest is done by indexmap_storage_pair class, which will compute the correct view class + depending on the view class and IM2 (view_from_tag_I_S template). + +:: + //In namespace IndexMaps::result_of + template + struct slice< IM, ArgsTuple> { typedef IM2 type; }; + + //In namespace IndexMaps : + template + typename result_of::slice::type slice(IM const &, ArgsTuple args); + diff --git a/doc/reference/c++/arrays_old/design/strategy.rst b/doc/reference/c++/arrays_old/design/strategy.rst new file mode 100644 index 00000000..d985e716 --- /dev/null +++ b/doc/reference/c++/arrays_old/design/strategy.rst @@ -0,0 +1,62 @@ +.. _Design: + +Strategy +============================================================= + +All the classes are a combination of a system of indices (called IndexMap I in the following) +and a physical storage S in the computer (a block of memory), denoted as an IndexMap_Storage_Pair (I,S). + +* I models the IndexMap concept [REF below]. + + * It is the bijection between the a set of indices and the position in the memory block. It can be though as a coordinate system on the (linear) memory block. + * Various types of indices are possible (only the first is implemented now). + + * cuboid (the standard hypercubic array, the only one currently implemented) + * triangular arrays + * band matrix + * multi-indices, with indices made of pair e.g. + +* S models the Storage concept [REF]. + + * It is a handle to the memory block containing the actual data. + * It can be e.g.: + + * a C++ shared pointer to a memory block. + * a reference to a numpy array. + +This design has several consequences : + +* **Interoperability** : classes are widely interoperable, e.g. one can add a array and a matrix (if dimensions are ok of course). + one can also add a python numpy and a C++ array without any further coding. + +* It is straighforward to construct a matrix_view from an array, since it is the same couple , + just interpreted differently. + +* It is easy to view a array as a matrix by gathering indices (properly ordered in memory) : + one just has to provide a new IndexMap I2 to see the same data. + [ --> very useful for vertex computation in many body...] + +* Slicing, or partial view is very natural : it is just a function on indexmaps : I--> I2, + independantly of any storage. + + +Quick guide through the implementation +============================================================= + +The implementation is divided into basically 4 parts : + +* Storages : implements two storages shared_block and numpy + +* IndexMaps : implements cuboid index map, its domain and iterators + +* impl/indexmap_storage_pair.hpp : the basic implementation class for all user class. + It is basically just a couple of an indexmap and a storage, with shallow copy. + It also forward the slices to the indexmap and construct the correct views. + +* upper level : + * user class : array, array_view, matrix, matrix_view, vector, vector_view + * expression.hpp : boost proto expression + * numpy_interface.hpp : helper to get numpy into array + * lapack/blas interface + * hdf5 support. + diff --git a/doc/reference/c++/arrays_old/expr_arith.rst b/doc/reference/c++/arrays_old/expr_arith.rst new file mode 100644 index 00000000..87e824e5 --- /dev/null +++ b/doc/reference/c++/arrays_old/expr_arith.rst @@ -0,0 +1,104 @@ +.. highlight:: c + +.. _arith_expression: + +Arithmetic Expressions +------------------------------------------------- + +* **Definition** : + + By `expression`, we mean here an object, typically representing a mathematical expression, + which models the :ref:`HasImmutableArrayInterface` concept. + +* **Use** : + + Expression can be used : + - as RHS (Right Hand Side) of various operators (=, +=, -=, ...) + - at any place where an `expression` is expected. + +* **How to make expression ?** + + Expressions can be build easily in various ways : + + - Using arithmetic operators, e.g. A + 2*B + Examples :: + + array A (2,2), B(2,2),C; + C= A + 2*B; + array D( A+ 2*B); + array F( 0.5 * A); // Type promotion is automatic + + // or even in C++0x : + auto e = A + 2*B; // expression, purely formal + array D(e); // really makes the computation + cout<< e < M1(2,2), M2(2,2), M3; + M3 = matmul(M1,M2); + + will do the following : + - matmul returns a lazy object modelling the :ref:`Expression` concept. + - a result this is compiled as some `matmul_with_lapack(M1,M2,M3)` : **there is NO intermediate copy**. + + - mat_vec_mul + + - Building custom expressions. The transpose example... + + Describe the concept, what to implement, etc.... + + - Transpose:: + + array A (2,2), B(2,2),C(2,2); + C= A + 2*B; + C = A + Transpose(B); // Transpose(X) returns a lazy object that models HasImmutableArrayInterface. + C = A + Transpose(B + B); // X can also be an expression... + C = Transpose(B); // + + // non square + array R(2,3),Rt(3,2); + cout<<" R = "<< array(Transpose(R)) < + using namespace triqs::arrays; + + h5::H5File file( "ess.h5", H5F_ACC_TRUNC ); + + // first create a 'big' array in the file (no temporary is made in memory, it uses directly the HDF5 API). + const size_t N = 100; + h5::array_proxy Pn( file, "Z", make_shape(N,2,2) ); + + // a slice... + array the_slice (2,2); the_slice() = 1; + + // write the large array slice by slice + for (int u = 0; u + using namespace triqs::arrays; + + h5::H5File file ("ess.h5", H5F_ACC_RDONLY ); + h5::array_proxy P(file, "A"); + + array a_slice ; + for (int u = 0; u` for this class. + diff --git a/doc/reference/c++/arrays_old/h5_rw.rst b/doc/reference/c++/arrays_old/h5_rw.rst new file mode 100644 index 00000000..db02a8e1 --- /dev/null +++ b/doc/reference/c++/arrays_old/h5_rw.rst @@ -0,0 +1,20 @@ +.. highlight:: c + +Simple read/write operations of an array (or a view) +============================================================================ + +Given an array (or an array_view), the functions `h5::write` and `h5::read` write and read it to/from the file +or any subgroup thereof. For example : + +.. literalinclude:: examples_code/h5_rw.cpp + +Note that : + + * The data in the hdf5 file are stored in C order. + + * The data is reordered in Fortran (or custom) order if necessary when reading/writing. + + * It also works with matrix and vector (but the storage is the same in HDF5). + + * It also works with the corresponding views. TO BE ILLUSTRATED. + diff --git a/doc/reference/c++/arrays_old/h5_stack.rst b/doc/reference/c++/arrays_old/h5_stack.rst new file mode 100644 index 00000000..af79cc96 --- /dev/null +++ b/doc/reference/c++/arrays_old/h5_stack.rst @@ -0,0 +1,42 @@ +.. highlight:: c + +h5::array_stack : stacking arrays or scalars +================================================================ + +h5::array_stack writes a sequences of arrays of the same shape (or of scalars) into an hdf5 array with one more dimension, unlimited in the stacking direction. + +It is typically used to store a Monte-Carlo data series for later analysis. + +* If the base of the stack is an array of rank R, the resulting hdf5 array will be of rank R+1. + +* If the base of the stack is a simple number (double, int, ...), R=0. + +* The syntax is simple : + + * The << operator piles up an array/scalar onto the stack. + * The ++ operator advances by one slice in the stack. + * The () operator returns a view on the current slice of the stack. + +* The stack is bufferized in memory (`bufsize` parameter), so that the file access does not happen too often. + +* NB : beware to complex numbers ---> REF TO COMPLEX + +Reference +------------ + +Here is the :arrays_doxy:`full C++ documentation` for this class. + + +Tutorial +----------- + +A simple example with a stack of double: + +.. literalinclude:: examples_code/h5_stack_ex_sca.cpp + +A simple example with a stack of array of rank 2 : + +.. literalinclude:: examples_code/h5_stack_ex.cpp + + + diff --git a/doc/reference/c++/arrays_old/introduction.rst b/doc/reference/c++/arrays_old/introduction.rst new file mode 100644 index 00000000..5bf1aa54 --- /dev/null +++ b/doc/reference/c++/arrays_old/introduction.rst @@ -0,0 +1,67 @@ +Motivation +=========================== + +.. highlight:: c + + +This library provides a multi-dimensionnal array library +for numerical computations with the following characteristics/goals : + +* **Simplicity of use**. + + Arrays must be as simple to use as in python (numpy) or fortran. + This library is designed to be used by physicists, not only by professionnal programmers, + We do *a lot* of array manipulations, and we want to maintain *readable* codes. + + Examples:: + + using namespace triqs::arrays; // All classes of this library are here. We will omit in the following + array A(4,2,3); // creating an array + A(0,1,2) // access an element + A(range(1,2), range(), 4) // a partial_view (or slice). + +* Various interoperable forms of arrays : + + * array : the general cuboid n-dimensional array, with **custom memory ordering** at compile time. + * matrix : a matrix class, with C or Fortran order at compile time. + * vector : a vector class. + +* **Genericity, abstraction and performance** : + + We want to have simple, readeable code, with the same (or better) speed than manually written low level code. + Most optimisations should be delegated to the library and the compiler. + + For example, we allow the use of **expression templates** for the algebra of arrays or matrices :: + + array A(4,2),B(4,2),C; + // fill A, B.... + C = 2* A + B/2 + + Expressions templates allows the elimination of temporaries and hence compact and readable code + with the speed of manually written codes. Thanks to boost::proto library, this can nowadays be achieved + while maintaining a good compilation time, and with a short and readable code. + +* **Compilation time** is (at far as tested) kept under control. + +* **Complete interoperability with python numpy arrays**. + + This library is used a lot with mixed C++/python codes. + It handles quick conversion between the C++ and python world, e.g. : + + * work on a view of a numpy, + * create a array in C++, and return it as a numpy. + * mix the various kind of arrays transparently in C++ expressions. + +* **HDF5** : simple interface to hdf5 library for an easy storing/retrieving into/from HDF5 files. + +* **STL compliance**. + + The arrays are compliant with STL (algorithms, std::vector >, iterators, map, etc...). + +* **Simple interface to Blas/Lapack** for matrices, vectors. + +* **MPI** : compatibility with boost::mpi interface. + + + + diff --git a/doc/reference/c++/arrays_old/matrix.rst b/doc/reference/c++/arrays_old/matrix.rst new file mode 100644 index 00000000..8df0214e --- /dev/null +++ b/doc/reference/c++/arrays_old/matrix.rst @@ -0,0 +1,101 @@ +.. highlight:: c + +matrix and matrix_view +============================ + +matrix and matrix_view : + +* are the class for matrix and the corresponding view. +* allow **custom memory ordering** (C or Fortran) at compile time. +* model the :ref:`HasImmutableArrayInterface` concept. + +Template parameters +---------------------------- + +* The classes have two template parameters. + + .. code-block:: c + + template class matrix_view; + template class matrix; + + ============================ ================================== ========================== ==================================================================== + Template parameter Accepted type Access in the class Meaning + ============================ ================================== ========================== ==================================================================== + ValueType normally a scalar, but any default value_type The type of the element of the array + constructible type (?). + Opt Option::options< ...> opt_type Compile time options, see below. + ============================ ================================== ========================== ==================================================================== + +Options template parameters are described :ref:`here `. +The memory order must obviously be only C or Fortran (memory_order is fine, but useless here...). + +.. _matrix_constructors: + +Constructors +----------------- + +Intentionally, matrix and matrix_view have only a few constructors : + +========================================== =========================================================================================== +Constructors of matrix Comments +========================================== =========================================================================================== +matrix() - empty matrix of size 0 +matrix(size_t, size_t) - from the dimensions. Does NOT initialize the elements of matrix to 0 ! +matrix(const matrix &) - copy construction +matrix (PyObject * X) - Construct a new matrix from the data of the Python object X. + NB : X is a borrowed reference, matrix does affect its counting reference. + - it takes a **copy** of the data of X (or of numpy(X)) into C++. + - X is first transformed into a numpy by the python numpy lib itself + (as if you call numpy.array(X)) if X is not a numpy array or an array of the wrong type + (e.g. you construct an matrix from a numpy of int....). +matrix(const T & X) - Type T models the :ref:`HasImmutableArrayInterface` concept. + - X must have the appropriate domain dimension (checked at compile time). + - Constructs a new matrix of domain X.domain() and fills it with evaluation of X. +========================================== =========================================================================================== + +* Examples :: + + matrix Mc(2,2); + matrix Mf(2,2); + +.. warning:: + The constructor from the dimensions does **NOT** initialize the matrix to 0 + (because it may not be optimal). + If needed, do it explicitely by `a()=0`; + + + +Constructors of matrix_views +---------------------------------------------- + +Automatic construction +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +matrix_view are normally automatically constructed by making (partial) views, ref:`Slicing`, e.g. :: + + matrix A(2,2); + A(range(),2) ; // --> this makes a view... + A() ; // --> this makes a view over the full array + + +Explicit construction +^^^^^^^^^^^^^^^^^^^^^^^^ + +To explicitly make a view of an matrix, use make_view or () :: + + matrix A(2,2); + make_view(A) //-> a view... + make_view(A) = 13 ; // to assign e.g. + A() = 13; // idem + + + +====================================================================== =========================================================================================================== +Constructors of matrix_view Comments +====================================================================== =========================================================================================================== +matrix_view(const matrix_view &) - Copy construction (shallow copy) +matrix_view(const T & X) - `[Advanced]` T is any type such that X.indexmap() and X.storage() can be used to construct a view. +====================================================================== =========================================================================================================== + + diff --git a/doc/reference/c++/arrays_old/memory_management.rst b/doc/reference/c++/arrays_old/memory_management.rst new file mode 100644 index 00000000..46116973 --- /dev/null +++ b/doc/reference/c++/arrays_old/memory_management.rst @@ -0,0 +1,40 @@ +Memory management +======================== + +.. highlight:: c + +* `View classes` contains a **reference counting** system to the memory block they view. + + This guarantees that memory will not be dellocated before the destruction of the view. + + The memory block will be dellocated when its array and all array_view + pointing to it or to a portion of it will be destroyed, and only at that moment. + + Example:: + + array *p = new array (2,3); // create an array p + array_view B(*p); // making a view + delete p; // p is gone... + B(0,0) = 314; cout< res; + /// I compute res + return boost::python::object(array_view(res)); // Cf section for convertion... + } + + The interpreter then take the responsability of destroying the data when needed (meaning here, long after f has returned, + when the python object returned will be cleaned). + + diff --git a/doc/reference/c++/arrays_old/options.rst b/doc/reference/c++/arrays_old/options.rst new file mode 100644 index 00000000..7a677e89 --- /dev/null +++ b/doc/reference/c++/arrays_old/options.rst @@ -0,0 +1,79 @@ +.. highlight:: c + +.. _option_template: + +Options template parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The `Option::options` template can take several parameters that determine various aspects of `array` (resp. `matrix`, `vector`) at **compile time**. +These parameters can be given in any order in the `options` template, but only at most only (they all have a default, that can also be changed +using macros for maximum flexibility). +These options parameters determine : + +* the storage order of indices in memory at **compile time**. + + =============================== =========================================================================================== + Template parameter Meaning + =============================== =========================================================================================== + `Tag::C` `[default]` C-style order + `Tag::Fortran` Fortran-style order ( NB the base index is still 0, not 1 !) + memory_order The tuple of size rank determines the storage order of indices in memory + memory_order_p

P is a triqs::arrays::Permutations::permutation that determines the storage order in memory + P[0] is the fastest index, P[rank - 1] the slowest index + =============================== =========================================================================================== + + Example of custom order :: + + custom > // same as index_order_Fortran, the first index is the fastest + custom > // same as index_order_C, the last index is the fastest + custom > // if indices are (i,j,k) : index j is fastest, then k, then i + +* whether bound check are done while accessing array elements or slicing the arrays. + + =============================== ==================================================================================================== + Template parameter Meaning + =============================== ==================================================================================================== + `Tag::NoBoundCheck` `[default]` Do no bound check at all. This is the default, for speed ! + `Tag::BoundCheck` Do bound checks. Boundary errors throw triqs::arrays::key_error exception (See ??) + =============================== ==================================================================================================== + + The macro `TRIQS_ARRAYS_ENFORCE_BOUNDCHECK` change the default to `Tag::BoundCheck` (for debugging purposes). + + Rational : one may want for some array to activate bound check and catch the exception, while keeping faster unchecked arrays elsewhere. + +* whether arrays are initialized at construction. + + =============================== ==================================================================================================== + Template parameter Meaning + =============================== ==================================================================================================== + `Tag::no_init` `[default]` No initialization of the array at construction (fastest). + `Tag::default_init` Initialize with the default constructor of ValueType + `Tag::nan_inf_init` Initialize to nan for floating type and std::limits::infinity() for integer type + as in D e.g. mainly for detecting easily lack of initialization errors. + =============================== ==================================================================================================== + + Note that : + + * The macro `TRIQS_ARRAYS_ENFORCE_INIT_NAN_INF` change the default to `Tag::nan_inf_init`. + * The macro `TRIQS_ARRAYS_ENFORCE_INIT_DEFAULT` change the default to `Tag::default_init`. + +* Several simple aliases are defined in the namespace Option for the most current cases : + + =============================== =============================== + Option aliases + =============================== =============================== + Option::C Option::options<`Tag::C`> + Option::Default Option::options<`Tag::C`> + Option::Fortran Option::options<`Tag::Fortran>` + =============================== =============================== + + +* Examples :: + + array > > A0 (2,3,4); + array > > A1 (2,3,4); + array > > A2 (2,3,4); + array A4 (2,3,4); + + + diff --git a/doc/reference/c++/arrays_old/python_tools.rst b/doc/reference/c++/arrays_old/python_tools.rst new file mode 100644 index 00000000..a3055493 --- /dev/null +++ b/doc/reference/c++/arrays_old/python_tools.rst @@ -0,0 +1,18 @@ +.. highlight:: c + +:: + + namespace Py_to_C { + template struct convert{ + static bool possible (boost::python::object x); // returns true iif the conversion of x into a T is possible + static T invoke(boost::python::object x); // do it ! + }; + } + + namespace C_to_Py { + template struct convert { + static boost::python::object invoke (T const & x); // convert T into a python object + }; + } + + diff --git a/doc/reference/c++/arrays_old/shape.rst b/doc/reference/c++/arrays_old/shape.rst new file mode 100644 index 00000000..b4f6b074 --- /dev/null +++ b/doc/reference/c++/arrays_old/shape.rst @@ -0,0 +1,33 @@ + +.. _Shape: + +Shape, resize +================================== + +Shape +-------------------- + +* array, matrix and vector have a method shape() that returns a `shape_type` object + i.e. a mini_vector + +* Tutorial:: + + array A(2,3); + A.shape()[0] == 2; + A.shape()[1] == 3; + +Resize +-------- + +* The `value class` array, matrix and vector can be resized:: + + array A(2,3); + A.resize ( make_shape (5,5) ) + + matrix M; + M.resize( 3,3); + + vector V; + V.resize(10); + + diff --git a/doc/reference/c++/arrays_old/slicing.rst b/doc/reference/c++/arrays_old/slicing.rst new file mode 100644 index 00000000..fc8cfbfb --- /dev/null +++ b/doc/reference/c++/arrays_old/slicing.rst @@ -0,0 +1,101 @@ +.. highlight:: c + +.. _Slicing: + +Element access & partial views +================================== + +Element access +-------------------- + +* The elements of the arrays can be naturally accessed using the ( ) operator:: + + array A(10,10); // defines an array + A(1,2) =10 // element access. + +Partial view, slices +------------------------ + +Various kind of partial views and slices can be made on arrays and matrices. + +* A `partial view` is defined as a view of a restricted portion of the array while + a `slice` is strictly speaking a partial view of a lower dimension of the original array, + e.g. a column of a matrix. + +* Partial views uses the ( ) operator, as the evaluation of the array:: + + array A(10,10); // defines an array + + A ( 1, range(0,2) ) // 1d slice + A ( 1, range() ) // 1d slice taking all the second dim + + A( range(0,10,2), range(0,10,2)) // a 2d slice viewing every each elements with even coordinates. + + array_view SL( A(0,range(0,3))); // naming the view + auto SL = A(0,range(0,3)); // C++0x with auto [check this] + +* **Return type** : + + * Partial views of array or array_view return an array_view. + * Partial views of vector or vector_view return an vector_view. + * 2d partial views of matrix or matrix_view return matrix_view. + * BUT : (1d) slices of matrix or matrix_view return vector_view. + * 0d slices of anything are converted to the `value_type` of the array. + +The `range` type +^^^^^^^^^^^^^^^^^^^^^ + + `range` mimics the python `range`. It can be constructed with : + + * no argument : it then takes the whole set of indices in the dimension (like `:` in python) :: + + A(range(), 0) // take the first column of A + + * two arguments to specify a range :: + + A(range (0,3), 0) // means A(0,0), A(1,0), A(2,0) + + .. warning:: + the second element is excluded : range(0,3) is 0,1,2, like in Python. + + * three arguments : a range with a step :: + + A(range(0,4,2), 0) // means A(0,0), A(2,0) + + +The `ellipsis` type +^^^^^^^^^^^^^^^^^^^^^^ + +* Ellipsis can be provided in place of `range`, as in python. The type `ellipsis` is similar to range + except that it is implicitely repeated to as much as necessary. + +* Example :: + + array B(2,3,4,5) ; + + B(0, ellipsis(), 3 ) ; // same as B(0, range(),range(), 3 ) + B(0, ellipsis(),2, 3 ) ; // same as B(0, range(), 2, 3 ) + B( ellipsis(),2, 3 ) ; // same as B( range(),range(), 2, 3 ) + +* NB : there can be at most one ellipsis per expression (otherwise it would be meaning less). + +* Example of usage : + + Ellipsis are useful to write generic algorithms. For example, imagine that you want to sum + arrays on their first index :: + + template + array_view sum0 (ArrayType const & A) { + array res = A(0,ellipsis()); + for (size_t u =1; u< A.shape()[0]; ++u) res += A(u,ellipsis()); + return res; + } + + ///..... + + array A(5,2); + array B(5,2,3); + std::cout<< sum0(A) << sum0(B) < class vector_view; + template class vector; + + ============================ ================================== ========================== ==================================================================== + Template parameter Accepted type Access in the class Meaning + ============================ ================================== ========================== ==================================================================== + ValueType normally a scalar, but any default value_type The type of the element of the vector + constructible type (?). + Opt Option::options< ...> opt_type Compile time options, see below. + ============================ ================================== ========================== ==================================================================== + +Options template parameters are described :ref:`here `. +The memory order is obviously useless here... + +.. _vector_constructors: + +Constructors +----------------- + +Intentionally, vector and vector_view have only a few constructors : + +========================================== =========================================================================================== +Constructors of vector Comments +========================================== =========================================================================================== +vector() - empty vector of size 0 +vector(size_t) - from the dimension. Does **NOT** initialize the elements of the vector to 0 ! +vector(const vector &) - copy construction +vector (PyObject * X) - Construct a new vector from the data of the Python object X. + NB : X is a borrowed reference, vector does affect its counting reference. + - it takes a **copy** of the data of X (or of numpy(X)) into C++. + - X is first transformed into a numpy by the python numpy lib itself + (as if you call numpy.array(X)) if X is not a numpy array or an array of the wrong type + (e.g. you construct an vector from a numpy of int....). +vector(const T & X) - Type T models the :ref:`HasImmutableArrayInterface` concept. + - X must have the appropriate domain (checked at compile time). + - Constructs a new vector of domain X.domain() and fills it with evaluation of X. +========================================== =========================================================================================== + +* Examples :: + + vector A(10,2); + A()=0; // init A to 0 + +.. warning:: + The constructor from the dimensions does **NOT** initialize the vector to 0 + (because it may not be optimal). + If needed, do it explicitely by `a()=0`; + +Constructors of vector_views +---------------------------------------------- + +Automatic construction +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +vector_view are normally automatically constructed by making (partial) views, ref:`Slicing`, e.g. :: + + tqa::vector A(2,2); + A(range(),2) ; // --> this makes a view... + A() ; // --> this makes a view over the full array + + +Explicit construction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To explicitly make a view of an vector, use make_view :: + + vector A(2,2); + make_view(A) //-> a view... + make_view(A) = 13 ; // to assign e.g. + + + +====================================================================== =========================================================================================================== +Constructors of vector_view Comments +====================================================================== =========================================================================================================== +vector_view(const array_view &) - Copy construction (shallow copy) +vector_view(const T & X) - `[Advanced]` T is any type such that X.indexmap() and X.storage() can be used to construct a view. +====================================================================== =========================================================================================================== + + diff --git a/doc/reference/c++/arrays_old/view_or_not_view.rst b/doc/reference/c++/arrays_old/view_or_not_view.rst new file mode 100644 index 00000000..9239a8d3 --- /dev/null +++ b/doc/reference/c++/arrays_old/view_or_not_view.rst @@ -0,0 +1,80 @@ +.. highlight:: c + +A fundamental distinction : value classes vs view classes +================================================================= + +A fundamental distinction in TRIQS is the difference between the `value class` +and the corresponding `view classes`. + +* The **value classes** : e.g. array, matrix, vector, ... + + * They own their data. + * They have a `value semantic`. + * When copied, assigned, they make deep copy. + * They are default constructible. + * They resize themselves under assignment if necessary (like e.g. std::vector). + * They can be put in standard STL containers. + + +* The **view classes** : e.g. array_view, matrix_view, vector_view, ... + + * They are just partial views of the corresponding value class. + * They do not own their data. + * They have a `view semantic`, with reference counting to the data. + * They never make deep copy, either in copying, constructing, transforming to python, + * They can not be resized. + * They are useful to work on arrays, matrices, or on some part thereof, without making copies + (e.g. on a slice of an array, a column of a matrix). + + +Each class is therefore provided in two flavors, and it is crucial for the user +to learn and understand their difference in order to use them appropriately. + +This distinction extends to more complex objects in TRIQS, such as Green functions. + + +Behaviour comparison table between value and view classes +------------------------------------------------------------ + +A detailed comparison of the behaviour of the two type of classes is provided in the following table. + + + +=================== ======================================================================= ====================================================================================== +Topics value class (e.g. array, matrix, vector0 view (e.g. array_view, matrix_view, vector_view) +=================== ======================================================================= ====================================================================================== +Contructors - Constructors create a new fresh memory block. - Constructors only make another view of the data. +Default Contructor - Default constructor creates an empty array - No default constructor (what would it view ?). +Copy contructors - Create a new fresh memory block. - Make another view of the data (shallow copy). + - Make a *true* copy of the data. - *Never* copy data, so they are quite quick. +Assignment (=) - The assignment operator creates a new datablock if size mismatchs. - The assignment operator just copy data into the view. + - Hence, assignment never fail for size reason Behaviour is undefined if the size of the view is too small. + (unless there is a memory allocation exception of course) (it throws if the array has option `Tag::BoundCheck` or if + `TRIQS_ARRAYS_ENFORCE_BOUNDCHECK` is defined, Cf below). +Resizing - Can be resized, invalidating all references/pointers to the data. - Can be not be resized. +Invalidation - References/pointers to the data may become invalid after resize, - References/pointers to the data are still valid after assignment. + or assignment. +STL - Can be used with STL container and algorithms - Can not be put in STL containers, but have STL compliant iterators. +Data Contiguity - The data are contiguous in memory. - The data may not be contiguous in memory (e.g. a slice). +=================== ======================================================================= ====================================================================================== + +An example +-------------- + +To be written.... + +A simple example :: + + array f(size_t n) { + array res(n,n); + res() = 0; + return res; + } + + array_view f(size_t n) { + array res(n,n); + res() = 0; + return res; + } + + diff --git a/doc/reference/c++/clef/CMakeLists.txt b/doc/reference/c++/clef/CMakeLists.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/doc/reference/c++/clef/CMakeLists.txt @@ -0,0 +1 @@ + diff --git a/doc/reference/c++/clef/assign.rst b/doc/reference/c++/clef/assign.rst new file mode 100644 index 00000000..7467905c --- /dev/null +++ b/doc/reference/c++/clef/assign.rst @@ -0,0 +1,114 @@ +.. highlight:: c + +Automatic assignment +======================= + +Principle +---------------- + +It is possible to use a subset of possible expressions as Left Hand Side (LHS) in an assignment statement, e.g. :: + + A(x_) = some_expression_of_x_ + A[i_] = some_expression_of_i_ + A(x_)(i_,j_) = some_expression_of_x_i_j + A[x_](i_,j_) = some_expression_of_x_i_j + +* Right Hand Side (RHS) of the = statement can be any expression. +* Left Hand Side (LHS) of the = sign. A must be a `lazy-assignable`, called by [] or (), one or several time. + +This writing means that a regular function :: + + x_ -> some_expression_of_x_ + +will be given to A so that it can fill itself by evaluating this function. +A determines the range of value of x on which the function is called. + +Example +--------- + +.. compileblock:: + + #include "triqs/clef.hpp" + #include "triqs/clef/adapters/vector.hpp" + #include + + int main() { + int N = 10; + double pi = std::acos(-1); + std::vector V(N); + + // automatic assignment of vector and use of lazy math function + triqs::clef::placeholder <0> k_; + triqs::clef::lazy(V) [k_] << cos( (2* pi* k_)/ N ); + + // check result... + for (size_t u=0; u void triqs_clef_auto_assign (Obj & x, Fnt f); + +The compiler will rewrite :: + + obj(x_,y_, ...) = expression + +into :: + + triqs_clef_auto_assign (obj, make_function( expression, x_, y_, ....)) + +The function is found by ADL. It is therefore useful to implement it e.g. as a friend function. + +Similarly, for [ ], adding a function :: + + template void triqs_clef_auto_assign_subscript (Obj & x, Fnt f); + +The compiler will rewrite :: + + obj[i_] = expression + +into :: + + triqs_clef_auto_assign_subscript (obj, make_function( expression, i_)) + + + +A complete example : + +.. compileblock:: + + #include + #include + + struct Obj{ + double v; + Obj(double v_): v(v_){} + + // lazy call : cf ... + template< typename... Args> + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) const { return make_expr_call (std::ref(* this),args...);} + + // The non const version (which then stores a non-const reference ....) + template< typename... Args> + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) { return make_expr_call (std::ref(* this),args...);} + + template friend void triqs_clef_auto_assign (Obj & x, Fnt f) { + x.v++; std::cout<< " called triqs_clef_auto_assign "<< f(100)< x_; + std::cout<< f.v << std::endl; + f(x_ ) << 8*x_ ; + //f(x_ + y_) = 8*x_; // leads to a compile error as expected + std::cout<< f.v << std::endl; + } + diff --git a/doc/reference/c++/clef/contents.rst b/doc/reference/c++/clef/contents.rst new file mode 100644 index 00000000..85484075 --- /dev/null +++ b/doc/reference/c++/clef/contents.rst @@ -0,0 +1,23 @@ +Clef expressions library +************************************* + +.. highlight:: c + +.. warning:: + + This library is still a prototype, of alpha quality. + +The little CLEF library (Compile time Lazy Expression and Function) +is a simple lambda library for C++11, to store and code formal expressions +using placeholders. + +.. toctree:: + :maxdepth: 1 + + expressions_form + expressions_eval + function + lazy_call + assign + lazy_function_cls + examples/contents diff --git a/doc/reference/c++/clef/copy_policy.rst b/doc/reference/c++/clef/copy_policy.rst new file mode 100644 index 00000000..c6e259b4 --- /dev/null +++ b/doc/reference/c++/clef/copy_policy.rst @@ -0,0 +1,40 @@ + +Copy policy in building expressions [Advanced] +==================================================== + +When building expressions, a problem can appear for the object at the leaves of the expressions tree +(scalar, placeholders, various callable objects, etc...). + +The question is whether they should be captured by value or by reference. + +In the lazy library, the choice has been made to capture them **by value**. + +This means that, by default, *all objects appearing in a lazy expression are copied, rather than captured by reference*. + +This is necessary to store expressions (with auto like above) for future reuse, transform them into new expressions +(e.g. make partial evaluation). Expressions are objects. +Capturing the leaves by reference easily produces dangling references. +[Basically, an expression is a function of its placeholder. The leaves are the parameters of the function, +they must leave as long as the expression live. In other words, we need to have a closure of the function]. + +The drawback of this approach is that it can generate unless copies of large objects. +There are several solutions to this issue : + +* The object is very small (like a double), hence making a copy in not a problem. +* You *know* that the object `A` will survive the expression, so using a reference is not a problem. + You can use the `lazy(A)` expression that will wrap the reference to the object. +* The object has a compagnon view object (like array, array_view). In this case, + one wishes to put a view of the object rather than a copy in the expression. + There are two cases. + + * TRIQS objects like array, matrix, vector will do it automatically. + + * For another object, if the object defines the tag `has_view_type_tag` as :: + + typedef void has_view_type_tag; + typedef MY_VIEW_TYPE view_type; + + the instance of the object will be replaced by an instance of its view_type in building the expression. + +For an illustration, Cf.... + diff --git a/doc/reference/c++/clef/examples/contents.rst b/doc/reference/c++/clef/examples/contents.rst new file mode 100644 index 00000000..5deac3bc --- /dev/null +++ b/doc/reference/c++/clef/examples/contents.rst @@ -0,0 +1,12 @@ +.. highlight:: c + +Examples +======================= + +.. toctree:: + :maxdepth: 1 + + vector_and_math + lazy_sum + lazy_function + diff --git a/doc/reference/c++/clef/examples/lazy_function.rst b/doc/reference/c++/clef/examples/lazy_function.rst new file mode 100644 index 00000000..50ba4f66 --- /dev/null +++ b/doc/reference/c++/clef/examples/lazy_function.rst @@ -0,0 +1,16 @@ + +.. highlight:: c + +.. _lazy_function_ex: + +Using clef::function +----------------------------- + +The following code : + +.. literalinclude:: src/lazyfunction.cpp + +will print : + +.. literalinclude:: src/lazyfunction2.output + diff --git a/doc/reference/c++/clef/examples/lazy_sum.rst b/doc/reference/c++/clef/examples/lazy_sum.rst new file mode 100644 index 00000000..9e25d264 --- /dev/null +++ b/doc/reference/c++/clef/examples/lazy_sum.rst @@ -0,0 +1,20 @@ +.. highlight:: c + +A lazy sum +-------------- + +Problem : we want + +* a functional `sum` that sums a function f over various domains, with various methods. + +* that this functionnal accepts lazy expressions as arguments. + +This is done by the little code: + +.. literalinclude:: src/sum_functional.cpp + +which will print : + +.. literalinclude:: src/sum_functional2.output + + diff --git a/doc/reference/c++/clef/examples/vector_and_math.rst b/doc/reference/c++/clef/examples/vector_and_math.rst new file mode 100644 index 00000000..320ba60e --- /dev/null +++ b/doc/reference/c++/clef/examples/vector_and_math.rst @@ -0,0 +1,25 @@ + +.. highlight:: c + +std::vector and math +--------------------------------- + +A simple example using std::vector. + +.. compileblock:: + + #include "triqs/clef.hpp" + + int main() { + // init some variables + int N = 10; double pi = std::acos(-1); std::vector V(N); + + // Filling the vector automatically from an expression of k_ + triqs::clef::placeholder<0> k_; + triqs::clef::lazy(V) [k_] << cos( (2* pi* k_)/ N ); + + // check result... + for (size_t u=0; u, <, >=, <=, ==)` +* Callable objects (see below) called on expressions +* Conditional if_else expressions + +Placeholders +---------------- + +Placeholders are only defined by their type, they contain no data :: + + triqs::lazy_expressions::placeholder x_; + triqs::lazy_expressions::placeholder y_; + +.. warning:: + As a consequence, if you define:: + + triqs::clef::placeholder y_; + + then `x_` is the same as `y_` : `x_` == `y_` will be always true. + + +Callable objects +-------------------- + +* The header `math.hpp` contains the declaration to make + the basic function of std `math.h` accept lazy_expressions. + Example :: + + #include + cos(2*x_+1) (x_=2) ; + abs(2*x_-1) (x_=2) ; + floor(2*x_-1) (x_=2.3) ; + pow(2*x_+1,2) (x_=2) ; + + +* To make your object callable, or to overload a function to accept lazy argument, see :ref:`callable_object`. + + +Copy policy +-------------------- + +.. warning:: All objects appearing in a lazy expressions are copied, rather than captured by reference. + +This is necessary to store expressions, make partial evaluation. +In order to avoid unncessary copies for large objects, it is necessary to use view type objects ( or shared_ptr). + +**NB** : for array, matrix, vector of the triqs::arrays library, this is automatic : triqs::clef +takes a *view* of the objects when building the expression tree. + +Evaluating lazy expressions +=============================== + +Complete evaluation +-------------------- + +Expressions are evaluated used named arguments, following the pattern :: + + expression ( placeholder_1 = value_1, placeholder_2 = value_2, ...) + +Example :: + + (x_ + 2*y_) ( x_=1, y_ = 2) + + // or (in C++11) + auto e = x_ + 2*y_; + auto r = e ( x_=1, y_ = 2); + +Note that : + +* The order of placeholder does not matter +* It is an error to put the same placeholder twice. + +Partial evaluation +-------------------- + +The evaluation can also be partial, in which case the compiler replaces the placeholder whose value is provided +and rebuild a new expression tree. + +Example :: + + auto expr = x_ + 2*y_; + expr (x_ =1); // ---> 1 + (2 * y_) + expr (x_ =x_ + y_); // ---> ((x_ + y_) + (2 * y_)) + expr(x_ =x_ + y_)( x_ = 1, y_ = 2)); //---> 7 + +During the partial evaluation, all subtrees that can evaluated are evaluated. +For example :: + + (x_ + f(y_)) (y_=1); // --> x + f(1) + +Assignment +------------ + +Some objects are `lazy-assignable`, which means that calling them on placeholders is a possible LHS. +Expressions like :: + + F(x_,y_) = an_expression_of(x_,y_); + +are rewritten by the compiler into :: + + F.set_from( make_function( an_expression_of(x_,y_), x_, y_) ); + + + + + diff --git a/doc/reference/c++/clef/expressions_eval.rst b/doc/reference/c++/clef/expressions_eval.rst new file mode 100644 index 00000000..7f6808f3 --- /dev/null +++ b/doc/reference/c++/clef/expressions_eval.rst @@ -0,0 +1,60 @@ + +.. highlight:: c + +Evaluating clef expressions +=============================== + +Forming expressions is nice, but completely useless unless one can *evaluate* them +by affecting some values to the placeholder and actually *do* the computation. + +Expressions are evaluated with the eval function :: + + eval ( expression , placeholder_1 = value_1, placeholder_2 = value_2, ...) + +The evaluation can be : + +* *complete* : when a value has been affected to every placeholder, so the result is not + an expression any more, but the result of the computation.... + +* *partial* : when some placeholder are still free (no value has been affected to them). + The result is another expression where the parts that could be computed have been computed. + +Complete evaluation +-------------------- + +Example :: + + eval (x_ + 2*y_ , x_=1, y_ = 2) + + auto e = x_ + 2*y_; + auto r = eval( e , x_=1, y_ = 2); + +Note that : + +* The order of placeholder does not matter in calling eval. +* It is an error to put the same placeholder twice. +* The correct version of eval is found by ADL (Argument Dependent Lookup). + (It if the clef::eval since arguments are defined in the clef namespace) + +Partial evaluation +-------------------- + +The evaluation can also be partial, in which case the compiler replaces the placeholder whose value is provided +and rebuild a new expression tree. + +Example :: + + auto e1 = x_ + 2*y_; + // return type ---> value + auto r = eval( e1 , x_ =1); // expression ---> 1 + (2 * y_) + auto e2 = eval( e1 , x_ =x_ + y_); // expression ---> ((x_ + y_) + (2 * y_)) + auto r = eval( e2, x_ = 1, y_ = 2); // int ---> 7 + +During the partial evaluation, all subtrees that can evaluated are evaluated. +For example :: + + eval(x_ + f(y_) , y_=1); // --> x + f(1) + +In this case, the function f is called by eval. + + diff --git a/doc/reference/c++/clef/expressions_form.rst b/doc/reference/c++/clef/expressions_form.rst new file mode 100644 index 00000000..da327d01 --- /dev/null +++ b/doc/reference/c++/clef/expressions_form.rst @@ -0,0 +1,132 @@ +.. highlight:: c + +Introduction +=========================== + +The first step consists in forming lazy expressions, before evaluating them. + +Placeholders +---------------- + +Loosely speaking, a placeholder is a "variable name" used to build an expression. +Technically, it is a trivial object, with a type but containing no data. +Placeholders are declared as :: + + placeholder Name; + +This declares a placeholder called Name (an empty object for C++). + +Example :: + + placeholder <1> x_; + placeholder <2> y_; + +Note that the only thing of significance in a placeholder is its type, since it contains no data. +In other words, a placeholder is **empty**. It contains **no value** at runtime. + + .. warning:: + + As a consequence, defining :: + + placeholder <1> y_; + + would imply that `x_` is the same as `y_` : `x_` == `y_` will be always true. + +Forming an expression +------------------------- + +Using simple operators, one can form a more complex expression, e.g.:: + + auto e = x_ + 2* y_; + +e has a complicated type (it is an expression template), which encodes the structure of the expression. +Typically here something like :: + + expr, expr > + +It is worth noting that : + +* As a user, one *never* has to write such a type + One always use expression "on the fly", or use auto. + +* Having the whole structure of the expression at compile time allows + efficient evaluation (it is the principle of expression template : add a ref here). + +* Declaring an expression does not do any computation, hence the name of the library (lazy ...). + It just stores the expression tree (its structure in the type, and the leaves of the tree). + +What is allowed in clef expressions ? +========================================== + +Expressions are composed of : + +* Placeholders +* Binary operations on expressions `(+, -, *, /, >, <, >=, <=, ==)` +* Conditional if_else expressions +* Callable objects (see below) called on expressions + +Callable objects +-------------------- + +* Objects can overload the operator () for lazy expressions in order to build more complex + expressions. + +* For example, the header `math.hpp` contains the declaration to make + the basic function of std `math.h` accept lazy_expressions. + + .. compileblock:: + + #include + int main () { + triqs::clef::placeholder <1> x_; + + auto e1 = cos(2*x_+1); + auto e2 = abs(2*x_-1); + auto e3 = floor(2*x_-1); + auto e4 = pow(2*x_+1,2); + } + +* To make your object callable, or to overload a function to accept lazy argument, see :ref:`callable_object`. + +*lazy* function +------------------- + +The *lazy* function can be called on any object to make it lazy, e.g. + +.. compileblock:: + + #include + #include + namespace tql = triqs::clef; + int main () { + std::vector V; + tql::placeholder<1> i_; + auto e1 = tql::lazy(V)[i_]; + } + +Copy policy in building expressions +--------------------------------------------------- + +A central question when forming expressions is whether the object at the leaves of the expressions tree +(scalar, placeholders, various callable objects, etc...) should be captured by value or by reference. + +In the clef library, the choice has been made to capture them **by value**, i.e. : + + *By default, all objects appearing in a clef expression are* **copied**, *rather than captured by reference*. + +This is necessary to store expressions (with auto like above) for future reuse, transform them into new expressions +(e.g. make partial evaluation). Expressions are ordinary objects. +If the leaves of the expression tree were captured by reference, a guarantee would have to be made that +they will live at least as long as the expression itself, or one gets dangling references. + +The drawback of this approach is that it can generate useless copies of large objects. +There are two simple solutions to this issue : + +* If you *know* that the object `A` will survive the expression, so using a reference is not a problem + and use std::reference_wrapper instead of A in the tree. + +* If the object has a compagnon view object (like array, array_view). In this case, + one wishes to put a view of the object rather than a copy in the expression. + + + diff --git a/doc/reference/c++/clef/function.rst b/doc/reference/c++/clef/function.rst new file mode 100644 index 00000000..0366b982 --- /dev/null +++ b/doc/reference/c++/clef/function.rst @@ -0,0 +1,98 @@ + +.. highlight:: c + +Clef expressions vs functions +===================================================================== + +Clef expressions are **NOT** functions. In short, + +* clef expressions are *evaluated* (the order of argument *does not* matter) :: + + eval( expr, x_=1, y_=2, ...); + +* while functions are *called*, as usual (the order of argument *does* matter !) :: + + f(1,2) + +It is however possible to transform expressions into functions, *as soon as you specify the order of the placeholders*, +and back. + +Function to clef expressions +------------------------------------- + +This is immediate, if the function accept lazy arguments, cf :ref:`callable_object`:: + + auto e1 = f(x_); + + +Transforming clef expressions into functions +---------------------------------------------------- + +make_function +..................... + +Given any expression with placeholder `x_`, `y_`, `z_`, ..., `make_function` +transform them into a regular function. If we say :: + + auto f = make_function( clef_expression, placeholder_1, placeholder_2, placeholder_3, ...) + +then f is :: + + a function (placeholder_1, placeholder_2, placeholder_3, ...) --> RESULT + +where RESULT is : + +* the result of the complete evaluation of the expression if the list of placeholder exhausts the placeholders of the expression. +* otherwise a clef_expression of the remaining placeholders, returning a **function**. + +Examples : + +* With one variable:: + + auto e1 = 2*x_ + 1; + auto f = make_function( e1, x_); + f(3) == 7; // ok + std::function F(f); // ok + +* With two variables :: + + auto e2 = 2*x_ + y_ + 1; + auto f = make_function( e2, x_, y_); + f(3,4) == 11; // ok + std::function F(f); // ok + +* Make a function partially :: + + auto f = make_function( 2*x_ + y_ + 1, x_); + // f is a lazy expression expression with placeholder y_, returning a function... + auto f1 = eval (f, y_=1); // f1 is a function x-> 2*x + 2 + f1 (10) == 22; + +* Currifying a function :: + auto f = make_function ( make_function( 2*x\_ + y\_ + 1, x\_), y\_); + // f a function y-> x-> 2x+y+1 + // f(y) returns a function x-> 2x+y+1 + + +Short notation with >> operator +..................................... + +For function of *one* variable, the make_function notation can be simplified into :: + + // same + auto f = make_function( 2*x_ + y_ + 1, x_); + auto f = x_ >> 2*x_ + y_ + 1; + + // same + auto f = make_function ( make_function( 2*x_ + y_ + 1, y_), x_); + auto f = x_ >> (y_ >> 2*x_ + y_ + 1) ; + +.. warning:: + The notation :: + + `x_` >> `y_` >> expression + + is banned because it conflicts with the standard priority of >>. + Use parenthesis. + + diff --git a/doc/reference/c++/clef/introduction.rst b/doc/reference/c++/clef/introduction.rst new file mode 100644 index 00000000..4ce51ca3 --- /dev/null +++ b/doc/reference/c++/clef/introduction.rst @@ -0,0 +1,15 @@ +.. highlight:: c + + +Motivation +======================= + + +The purpose of the Named Parameter Lambda (nplambda) library is to help +the manipulation of formal expressions. + +Functional programming techniques are now widely used. For example, boost::phoenix library +provides simple lambda techniques. + +NPL is + diff --git a/doc/reference/c++/clef/lazy_call.rst b/doc/reference/c++/clef/lazy_call.rst new file mode 100644 index 00000000..ebdad992 --- /dev/null +++ b/doc/reference/c++/clef/lazy_call.rst @@ -0,0 +1,226 @@ + +.. highlight:: c + +.. _callable_object: + +Overloading functions and callable objects for clef expression arguments +============================================================================= + +Given a callable object or a function, it is possible to overload it for clef expression arguments, returning a clef expression. +In all cases: + + *Overloads that are activated iif at least one argument is a clef expression*. + +Functions +------------ + +std math functions +^^^^^^^^^^^^^^^^^^^^^^^^ + +The overload is defined by clef automatically for usual functions : + +.. compileblock:: + + #include + #include + int main() { + triqs::clef::placeholder<3> x_; + std::cout << 2.0 + std::cos(2.0) << std::endl; + std::cout << eval( x_ + cos(x_), x_ = 2) << std::endl; // NB : note the absence of std:: + } + +Overloading a function for clef expressions arguments +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The `TRIQS_CLEF_MAKE_FNT_LAZY` macro defines the overload for clef expressions arguments of a function. Synopsis is :: + + namespace triqs { namespace clef { + TRIQS_CLEF_MAKE_FNT_LAZY (function_to_make_lazy); + }} + +For example: + +.. compileblock:: + + #include + #include + + double foo(double x) { return x/2;} + int foo(int x) { return x*2;} + + namespace triqs { namespace clef { TRIQS_CLEF_MAKE_FNT_LAZY (foo) ; }} + + int main() { + triqs::clef::placeholder<3> x_; + std::cout << foo(2.0) << std::endl; + std::cout << eval( x_ + foo(x_), x_ = 3) << std::endl; + std::cout << eval( x_ + foo(x_), x_ = 3.5) << std::endl; + } + +Note that : + + * This overload **must** be defined in the triqs::clef namespace, since it is found by ADL. + * The function `foo` can have many overloads. + * The function foo can be a template, BUT then the template must be disabled for lazy expressions, as in :: + +.. compileblock:: + + #include + #include + + template + typename std::enable_if::value,T>::type + foo (T const & x) { return x+1;} + + namespace triqs { namespace clef { TRIQS_CLEF_MAKE_FNT_LAZY (foo) ; }} + + int main() { + triqs::clef::placeholder<3> x_; + std::cout << foo(2.0) << std::endl; + std::cout << eval( x_ + foo(x_), x_ = 3) << std::endl; + std::cout << eval( x_ + foo(x_), x_ = 3.5) << std::endl; + } + +Callable objects +-------------------- + +Similarly to functions, classes can define an `operator()` for lazy expressions arguments. +It is an ordinary operator() that must : + +* Be enabled only when one argument is a clef expression + +* Return a clef expression. + +The function make_expr_call helps. + +Object stored by copy (default) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The default behaviour is to store the object by copy in the expression tree... + +.. compileblock:: + + #include + + struct Obj { + double v; // put something in it + Obj(double v_): v(v_){} // constructor + + // The "normal", non lazy call operator .... + double operator() (double x) const { return 10*x;} + + // Call operator for const object + // make_expr_call creates a clef expression with a "call" node at the top + // calling this object on the arguments. + // Obj is stored by making a copy in the expression tree. + // NB : the make_expr_call trait enabled only if one of the arguments is lazy + // hence if none of the Args are clef expression, the template is disabled by SFINAE. + template< typename... Args> + typename triqs::clef::result_of::make_expr_call::type + operator()( Args&&... args ) const { return make_expr_call(* this,args...);} + + // Just to print itself nicely in the expressions + friend std::ostream & operator<<(std::ostream & out, Obj const & x) { return out<<"Obj";} + }; + + int main() { + Obj f(7); + triqs::clef::placeholder<3> x_; + triqs::clef::placeholder<4> y_; + std::cout << "Clef expression : "<< f(y_) + 2*x_ << std::endl ; + std::cout << "Complete evaluation : "<< eval(f(x_) + 2*x_, x_=1) << std::endl ; + std::cout << "Partial evaluation : "<< eval(f(y_) + 2*x_, y_=1) << std::endl ; + std::cout << "Complete evalution : "<< eval(f(y_) + 2*x_, x_=3, y_=1) << std::endl ; + } + +Object stored by reference +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes, one want to escape the copy of the object in the tree. +In that case, just use a std::reference_wrapper in place of the object. +You have then to guarantee that the object will live longer that the expression +that you form. + +.. compileblock:: + + #include + + struct Obj { + double v; // put something in it + Obj(double v_): v(v_){} // constructor + Obj(Obj const &) = delete; // a non copyable object + + // The "normal", non lazy call operator .... + double operator() (double x) const { return 10*x;} + + // Same as above, but now we stored a ref to the object and not a copy of the object. + // Reference are encapsulated in std::reference_wrapper (Cf C++ documentation). + template< typename... Args> + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) const { return make_expr_call (std::ref(* this),args...);} + + // The non const version (which then stores a non-const reference ....) + template< typename... Args> + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) { return make_expr_call (std::ref(* this),args...);} + + // Just to print itself nicely in the expressions + friend std::ostream & operator<<(std::ostream & out, Obj const & x) { return out<<"Obj";} + }; + + int main() { + Obj f(7); + triqs::clef::placeholder<3> x_; + triqs::clef::placeholder<4> y_; + std::cout << "Clef expression : "<< f(y_) + 2*x_ << std::endl ; + std::cout << "Complete evaluation : "<< eval(f(x_) + 2*x_, x_=1) << std::endl ; + std::cout << "Partial evaluation : "<< eval(f(y_) + 2*x_, y_=1) << std::endl ; + std::cout << "Complete evalution : "<< eval(f(y_) + 2*x_, x_=3, y_=1) << std::endl ; + } + +.. note : one can of course replace the reference_wrapper by a view of the object, e.g.... + + +NB: When non lazy operator() is already a template ? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Then it must be disabled for clef expression argument, using the trait :: + + clef::is_any_lazy :: value // true iif one of the T is a clef expression + +Example, derived from the previous one : + +.. compileblock:: + + #include + #include + + struct Obj { + double v; // put something in it + Obj(double v_): v(v_){} // constructor + + // The "normal", non lazy call operator is now a template + template + typename std::enable_if::value, T>::type // correct + // T operator() (T const & x) const { return 10*x;} would be ambiguous ! + operator() (T const & x) const { return 10*x;} + + // lazy expression + template< typename... Args> + typename triqs::clef::result_of::make_expr_call::type + operator()( Args&&... args ) const { return make_expr_call(* this,args...);} + + // Just to print itself nicely in the expressions + friend std::ostream & operator<<(std::ostream & out, Obj const & x) { return out<<"Obj";} + }; + + int main() { + Obj f(7); + triqs::clef::placeholder<3> x_; + triqs::clef::placeholder<4> y_; + std::cout << "Clef expression : "<< f(y_) + 2*x_ << std::endl ; + std::cout << "Partial evaluation : "<< eval(f(y_) + 2*x_, y_=1) << std::endl ; + std::cout << "Complete evalution : "<< eval(f(y_) + 2*x_, x_=3, y_=1) << std::endl ; + } + + diff --git a/doc/reference/c++/clef/lazy_function_cls.rst b/doc/reference/c++/clef/lazy_function_cls.rst new file mode 100644 index 00000000..fdcac15a --- /dev/null +++ b/doc/reference/c++/clef/lazy_function_cls.rst @@ -0,0 +1,16 @@ +.. highlight:: c + +clef::function class +========================== + +The class triqs::clef::function is similar to boost::function (std::function), +except that : + +* it can be constructed from an expression and an ordered list of placeholders. +* it is `lazy-callable` and `lazy-assignable` + +.. note:: + It stores the expression polymorphically, by erasing its type. (You can put various expressions into it, cf below). + This might lead to some performance penalty in some case, even though tests do not show that at present... + +Example of usage is given in :ref:`lazy_function_ex`. diff --git a/doc/reference/c++/conf.py.in b/doc/reference/c++/conf.py.in new file mode 100644 index 00000000..aad61309 --- /dev/null +++ b/doc/reference/c++/conf.py.in @@ -0,0 +1,235 @@ +# -*- coding: utf-8 -*- +# +# TRIQS documentation build configuration file, created by +# sphinx-quickstart on Tue Sep 21 10:50:39 2010. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed automatically). +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If your extensions are in another directory, add it here. If the directory +# is relative to the documentation root, use os.path.abspath to make it +# absolute, like shown here. +#sys.path.append(os.path.abspath('.')) + +# General configuration +# --------------------- + +sys.path +=["@CMAKE_BINARY_DIR@/doc/breathe", +"@CMAKE_BINARY_DIR@/doc/mpl","@CMAKE_BINARY_DIR@/doc/autocompile", +"@CMAKE_BINARY_DIR@/doc/sandbox","@CMAKE_BINARY_DIR@/doc"] + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +#extensions = ['sphinx.ext.autodoc','sphinx.ext.pngmath'] +extensions = ['sphinx.ext.autodoc','sphinx.ext.@SPHINX_MATH_GENERATOR@','breathe','doxylink'] + +# adding support for matplotlib plots +extensions += [ + 'matplotlib.sphinxext.only_directives', + 'plot_directive', + # 'matplotlib.sphinxext.ipython_directive', + # 'ipython_console_highlighting', + # 'inheritance_diagram', + 'numpydoc'] + +extensions += ['autocompile'] +#extensions += ['sandbox'] + +autocompile_opts = dict(compiler = "@CMAKE_CXX_COMPILER@", + link = "@DOC_AUTOCOMPILE_LINK@".replace(';',' '), + ld_library_path = "@DOC_AUTOCOMPILE_LD_LIBRARY_PATH@".replace(';',' '), + include =''.join([ " -I%s"%arg for arg in "@DOC_AUTOCOMPILE_INCLUDE@".split(';')] ), + definitions =''.join([ " %s"%arg for arg in "@DOC_AUTOCOMPILE_DEFINITIONS@".split(';')] ) + ) +autoclass_content = "both" + +#pngmath_dvipng_args = ['-gamma 1.2', '-D 150', '-bg Transparent'] +mathjax_path = "@MATHJAX_PATH@/MathJax.js?config=default" + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['@TRIQS_SOURCE_DIR@/doc/developer_manual/.templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'contents' + +# General information about the project. +project = u'TRIQS' +copyright = u'2011, the TRIQS collaboration' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = ['build','html'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# Options for breathe extension +# ----------------------------- + +breathe_projects = { + "mc_tools":"@CMAKE_CURRENT_BINARY_DIR@/xml/", + "arrays":"@CMAKE_CURRENT_BINARY_DIR@/xml/", + } + +breathe_default_project = "mc_tools" + +# Options for doxylink extension +# ----------------------------- + +doxylink = { 'doxy' : ('@CMAKE_CURRENT_BINARY_DIR@/doxy.tag', 'doxy_triqs') } + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +#html_style = 'default.css' +html_theme_path = ["@TRIQS_SOURCE_DIR@/doc/themes/"] +html_theme = "agogo" +#html_theme = "default" + +#html_theme_options = { "pagewidth": "80em", "documentwidth" : "60em" } + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = '@TRIQS_SOURCE_DIR@/Doc/misc/python-powered-w-200x80.png' + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +#html_static_path = ['@TRIQS_SOURCE_DIR@/doc/developer_manual/.static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +html_additional_pages = { 'index':'index.html' } + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, the reST sources are included in the HTML build as _sources/. +#html_copy_source = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'TRIQSdoc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +latex_documents = [ + ('contents', 'TRIQS.tex', ur'TRIQS Documentation', + ur'2011, M. Ferrero and O. Parcollet', 'manual'), + ] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True diff --git a/doc/reference/c++/contents.rst b/doc/reference/c++/contents.rst new file mode 100644 index 00000000..02cf5254 --- /dev/null +++ b/doc/reference/c++/contents.rst @@ -0,0 +1,16 @@ +Reference: C++ librairies +########################## + +.. toctree:: + :maxdepth: 1 + + learn/intro + arrays/contents + mctools/intro + det_manip/det_manip + gf/contents + parameters/parameters + gf/intro + clef/contents + lectures/contents + utilities/intro.rst diff --git a/doc/reference/c++/det_manip/CMakeLists.txt b/doc/reference/c++/det_manip/CMakeLists.txt new file mode 100644 index 00000000..fb1df62f --- /dev/null +++ b/doc/reference/c++/det_manip/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright Olivier Parcollet 2010 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Sphinx sources +#set_property(GLOBAL APPEND PROPERTY SPHINX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/det_manip.rst) + +# Doxygen sources +set_property(GLOBAL APPEND PROPERTY DOXYGEN_SOURCES ${TRIQS_SOURCE_DIR}/triqs/det_manip/det_manip.hpp) + diff --git a/doc/reference/c++/det_manip/contents.rst b/doc/reference/c++/det_manip/contents.rst new file mode 100644 index 00000000..723d3bc4 --- /dev/null +++ b/doc/reference/c++/det_manip/contents.rst @@ -0,0 +1,37 @@ +.. highlight:: c + +Manipulations of determinants +============================= + +The purpose of this little class is to regroup standard block manipulations on determinant, used in several +QMC. + +Given a function :math:`F(x,y)`, and two sets of values :math:`x_i,y_i \ 0\leq i < N`, +we can define the square :math:`N\times N` matrix + +.. math:: + + M_{i,j} = F(x_i,y_j) + +When adding/removing a line and column (i.e. a value of x, y), +:math:`M^{-1}` and :math:`det M` can be fast updated using standard block matrix computations. +This class implements these general operations. It contains : + +* Data : + + * :math:`M^{-1}` and :math:`det M` + * a vector containing :math:`x_i,y_i \ 0\leq i \leq N` + +* Methods to quickly update :math:`M^{-1}` and :math:`\det M` when one : + + * adds/removes a line and a column (i.e. adding or removing one x and one y) + * adds/removes two lines and two columns (i.e. adding or removing two x and two y) + * changes a line/colum, etc... + + + +.. toctree:: + :maxdepth: 2 + + det_manip + cookbook diff --git a/doc/reference/c++/det_manip/cookbook.rst b/doc/reference/c++/det_manip/cookbook.rst new file mode 100644 index 00000000..f89b9536 --- /dev/null +++ b/doc/reference/c++/det_manip/cookbook.rst @@ -0,0 +1,70 @@ +Cookbook +======== + +Basics +------ + +Here, an exemple of creation of a class det_manip, of use of insert and remove. + +.. compileblock:: + + #include + + struct fun { + + typedef double result_type; + typedef double argument_type; + + //gives the coefficients of the matrix + double operator()(double x, double y) const { + return(x-y); + } + }; + + int main() { + + //creation of the class det_manip + fun f; + int init_size=100; + triqs::det_manip::det_manip D(f,init_size); + //the initial matrix is empty: + std::cout<` is available here. + +Example +------------- + +.. code-block:: c + + struct fun { + + typedef double result_type; + typedef double argument_type; + + double operator()(double x, double y) const { + const double pi = acos(-1); + const double beta = 10.0; + const double epsi = 0.1; + double tau = x-y; + bool s = (tau>0); + tau = (s ? tau : beta + tau); + double r = epsi + tau/beta * (1-2*epsi); + return - 2*(pi/beta)/ std::sin ( pi*r); + } + }; + + int main() { + + fun f; + triqs::det_manip::det_manip D; + + /// .... + double x=2, y=9, detratio; + detratio = D.try_insert(1,3, x,y); + D.complete_operation(); + + ///... + detratio = D.try_remove(2,1); + D.complete_operation(); + } + + + + + + diff --git a/doc/reference/c++/gf/CMakeLists.txt b/doc/reference/c++/gf/CMakeLists.txt new file mode 100644 index 00000000..b0c467d5 --- /dev/null +++ b/doc/reference/c++/gf/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright Olivier Parcollet 2010 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Sphinx sources +#set_property(GLOBAL APPEND PROPERTY SPHINX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/det_manip.rst) + +# Doxygen sources +set_property(GLOBAL APPEND PROPERTY DOXYGEN_SOURCES ${TRIQS_SOURCE_DIR}/triqs/gf/gf.hpp) + diff --git a/doc/reference/c++/gf/concepts.rst b/doc/reference/c++/gf/concepts.rst new file mode 100644 index 00000000..f0edf3cc --- /dev/null +++ b/doc/reference/c++/gf/concepts.rst @@ -0,0 +1,314 @@ +.. highlight:: c + +Green functions +################# + +Here are the concepts and techniques related to the Green functions. + +All Green functions are implemented as a gf and gf_view where : + +* Descriptor contains everything specific to the Green function + (number of variables, domain of definition, interpolation techniques, etc...). + +* The gf/gf_view class implements the generic part (hdf5, view mechanism, interaction with clef library, etc...). + +We first present the concept of the Descriptor, and the concepts of its elements. +In a second part, we present a more detailed description of gf/gf_view. + +Pure functions on domains +============================== + +This formalize a mathematical function : + +* it has a domain of definition +* it can be called on any point of the domain, as a *pure* function, i.e. without any side effect. + +Domain concept +------------------------------------------------- + +* **Purpose** : The domain of definition of a function. It is a mathematical definition of the domain, + and does not contain any mesh, or details on its representation in a computer. + +* **Refines** : CopyConstructible, DefaultContructible, EqualComparable, BoostSerializable, H5-serializable. + +* **Definition** : + ++----------------------------------------------------------------------------+---------------------------------------------------------------------+ +| Elements | Comment | ++============================================================================+=====================================================================+ +| point_t | Type of element in the domain (int, int, double, k_vector, ...) as | +| | in the call of a function over this domain. In particular, in | +| | Matsubara, it is a complex. | ++----------------------------------------------------------------------------+---------------------------------------------------------------------+ + +* **Examples** : + + * Matsubara frequencies (boson/fermion) + * Matsubara time + * Real frequencies + * Real time + * Brillouin zone + + +PureFunctionOnDomain +----------------------- + +* **Purpose** : A function from a domain to a target space. + +* **Refines** : + +* **Definition** : + ++--------------------------------------+----------------------------------------------------------+ +| Elements | Comment | ++======================================+==========================================================+ +| domain_t | Type of the Domain represented, modelling Domain concept | ++--------------------------------------+----------------------------------------------------------+ +| domain_t const & domain() const | Returns the domain | ++--------------------------------------+----------------------------------------------------------+ +| operator (domain_t::point_t) const | Calling for all elements of the Domain (including infty | +| | if it is in the domain... | ++--------------------------------------+----------------------------------------------------------+ + +* NB : Note that the return type of the function is *NOT* part of the concept, + it has to be deduced by the compiler (using C++11 decltype, std::result_of, eg..). + +Functions stored on a mesh +================================ + +A special kind of function is those stored on a mesh. +The mesh can be regular or not, multi-dimensionnal. + +We first define the concept of a mesh, and then the concept of a function discretized over that mesh. + +Mesh concept +------------------------------------------------- + +* **Purpose** : A mesh over a domain, and more generally the practical representation of the domain in a computer. + It does not really need to be a mesh : e.g. if the function is represented on a polynomial basis, + it is the parameters of this representation (max number of coordinates, e.g.) + +* **Refines** : CopyConstructible, DefaultContructible, EqualComparable, BoostSerializable, H5-serializable. + +* **Definition** : + ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ +| Elements | Comment | ++==============================================================+===============================================================================+ +| domain_t | Type of the Domain represented, modeling the Domain concept | ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ +| domain_t const & domain() const | Access to the domain | ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ +| index_t | Type of indices of a point on the grid. Typically a tuple of long or a long | ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ +| size_t size() const | The number of points in the mesh. | ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ +| domain_t::point_t index_to_point(index_t) const | From the index of a mesh point, compute the corresponding point in the domain | ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ +| size_t index_to_linear(index_t const &) const | Flattening the index of the mesh into a contiguous linear index | ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ +| mesh_point_t | See below | ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ +| mesh_point_t operator[](index_t const & index ) const | From an index, return a mesh_point_t containing this a ref to this mesh and | +| | the index. | ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ +| mesh_pt_generator iterator | A generator of all the mesh points. | ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ +| iterator begin()/end() const | Standard access to iterator on the mesh | ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ +| friend bool operator == (mesh_t const& M1, mesh_t const &M2) | Comparison between meshes | ++--------------------------------------------------------------+-------------------------------------------------------------------------------+ + + +* **Examples** : Some domains and the corresponding possible meshes. + ++-----------------------------------------------------+--------------------------------------------------------+ +| Domain Type | What does the corresponding mesh type contain ? | ++=====================================================+========================================================+ +| Matsubara frequencies | Nmax, the max number of Matsubara Freq. | ++-----------------------------------------------------+--------------------------------------------------------+ +| Matsubara time | The time slicing is on a mesh, or the Legendre mesh is | +| | we store the function with Legendre representation. | ++-----------------------------------------------------+--------------------------------------------------------+ +| Real frequencies | Parameters of the mesh in frequency | ++-----------------------------------------------------+--------------------------------------------------------+ +| Real time | | ++-----------------------------------------------------+--------------------------------------------------------+ +| Brillouin zone | parameters of the mesh over the BZ, symmetry ? | ++-----------------------------------------------------+--------------------------------------------------------+ + + +MeshPoint concept +------------------------------------------------- + +* **Purpose** : Abstraction of a point on a mesh. A little more than a ref to the mesh and a index. + +* **Refines** : CopyConstructible. + +* **Definition** : + ++------------------------------------------------+-----------------------------------------------------------------------------+ +| Elements | Comment | ++================================================+=============================================================================+ +| mesh_t | Type of the mesh | ++------------------------------------------------+-----------------------------------------------------------------------------+ +| mesh_t const * m | A pointer to the mesh to which the point belongs. | ++------------------------------------------------+-----------------------------------------------------------------------------+ +| mesh_t::index_t index | The index of the point | ++------------------------------------------------+-----------------------------------------------------------------------------+ +| mesh_point_t( mesh_t const &, index_t const &) | Constructor | ++------------------------------------------------+-----------------------------------------------------------------------------+ +| mesh_t::index_t [const &|] index() const | The index corresponding to the point | ++------------------------------------------------+-----------------------------------------------------------------------------+ +| size_t linear_index() const | The linear index of the point (same as m->index_to_linear(index()) | ++------------------------------------------------+-----------------------------------------------------------------------------+ +| void advance() | Advance to the next point on the mesh (used by iterators). | ++------------------------------------------------+-----------------------------------------------------------------------------+ +| void at_end() | Is the point at the end of the grid | ++------------------------------------------------+-----------------------------------------------------------------------------+ +| void reset() | Reset the mesh point to the first point | ++------------------------------------------------+-----------------------------------------------------------------------------+ +| operator mesh_t::domain_t::point_t() const | cast to the corresponding domain point | ++------------------------------------------------+-----------------------------------------------------------------------------+ +| Implements the basic operations on the domain | Only for non composite mesh | +| by using the cast operation | | ++------------------------------------------------+-----------------------------------------------------------------------------+ + +The MeshPoint mechanism +--------------------------- + +A MeshPoint is just a storage of a reference to the mesh and the index of the point in a custom structure. +The interest of having such a structure is that : + +* The gf function has a operator()(mesh_t::mesh_point_t) (see below) which is a direct access to the data on the grid. + Hence if MP is a such a MeshPoint, g(MP) is equivalent to something like g.data_on_grid_at_index( MP.index) + +* MP however can be casted to a point in the domain and therefore it *is* a domain_t::point_t as well. + + As a result, g(MP) = 1/(MP + 2) makes senses iif it makes senses in the domain. + +* Moreover, because of the iterator on the mesh, one can write :: + + // example of g, a Green function in Matsubara frequencies w + for (auto w : g.mesh()) + g(w) = 1/(w + 2) + // This runs overs the mesh, and fills the function with 1/(w+2) + // In this expression, w is casted to the domain_t::point_t, here a complex + // which allows to evaluate the function + + +FunctionOnMesh concept +----------------------------- + +* **Purpose** : A function from a domain to a target space, represented in a mesh. + This function can only be evaluated on the mesh points. + +* **Refines** : BoostSerializable, H5-serializable. + +* **Definition** : + ++--------------------------------------------------+------------------------------------------------------------------------+ +| Elements | Comment | ++==================================================+========================================================================+ +| mesh_t | Type of the mesh representing the domain. | ++--------------------------------------------------+------------------------------------------------------------------------+ +| mesh_t const & mesh() const | Returns the mesh. | ++--------------------------------------------------+------------------------------------------------------------------------+ +| auto operator ( grid_pt const &) const | Calling on a grid_pt gives direct access to the value on a grid point. | +| auto & operator ( grid_pt const &) | Const and non const version. | ++--------------------------------------------------+------------------------------------------------------------------------+ + +* **NB** : the result type of the () operator is deduced. Not needed in the concept. + + +descriptors +====================================== + +A descriptor is a structure that contains everything specific to the Green function +(number of variables, domain of definition, interpolation techniques, etc...). + + +Descriptor concept +--------------------------- + +* **Purpose** : + +* **Refines** : + +* **NB** : Pure static, does NOT contains any data. + +* **Definition** : + ++------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+ +| Elements | Comment | ++====================================================================================+===============================================================================+ +| struct tag {}; | A tag for the gf | ++------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+ +| mesh_t | Mesh for the gf, modeling Mesh concept | ++------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+ +| storage_t | The type of the storage of the data (array, vector, etc....) | ++------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+ +| singularity_t | Type of object storing the singularities of the gf. It is used e.g. in the | +| | Fourier transformation, density computation, etc... For a simple g(omega), | +| | g(t), it is typically a high frequency tail. For a more complex function | +| | g(nu,nu'), it can be different. | ++------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+ +| symmetry_t | Type of the object storing the symmetry property of the Green function. It is | +| | *nothing* by default. This type must be a value (DefaultConstructible, | +| | CopyConstructible, Assignable) | ++------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+ +| target_indices_t | Type of the indices of the gf, typically array | ++------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+ +| static const int arity | Number of variable authorized in calling the gf (just for compile time check | +| | and nice error message, it is not really necessary) | ++------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+ +| struct evaluator { auto operator()( mesh_t const &, DATA_t const &, S_t const &, | All the permitted const call of the gf ! (DATA_t defined below) with the | +| Args&&... args) .... as many overload as necessary } | parenthesis operator The gf<...> function create such a struct, so it can | +| | hold some data ... | ++------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+ +| static std::string h5_name() | Name for hdf5 naming (attribute of the tree in which the gf is stored). | ++------------------------------------------------------------------------------------+-------------------------------------------------------------------------------+ + +* **Values vs Views** + target_t, singularity_t, indices_t are expected to be *values*. + The corresponding views, i.e., target_view_t, singularity_view_t, indices_view_t will be deduced from the value type, and + replaced by the value_type if no view is available. + +* S_t is singularity_t or its corresponding view type (if it exists). + + +The gf/gf_view class +==================== + +The gf/gf_view classes are generic Green function, templated on Descriptor. + +They handle : + +* view/non view aspect, copy, etc... +* hdf5 interface +* clef interface +* the MeshPoint mechanism as explained above. +* perfect forwarding of all other const call of operator() to Descriptor. + +Constructors are limited to a minimal number : + +* empty one for gf (value semantics). +* copy construction, from gf and gf_view of the same descriptor. +* construction from the data of the GF. + +The other custom construction are delegated to make_gf functions:: + + gf make_gf (Descriptor, my_favorite arguments). + +We use here the simplest dispatch using the fact that Descriptor is an empty struct, +so we can dispath the make_gf. Example of use :: + + auto G = make_gf (matsubara_freq(), beta, Fermion, make_shape(2,2)); + + + +Doxygen documentation +====================== + +The :doxy:`full C++ documentation` is available here. + diff --git a/doc/reference/c++/gf/contents.rst b/doc/reference/c++/gf/contents.rst new file mode 100644 index 00000000..1ac2ccab --- /dev/null +++ b/doc/reference/c++/gf/contents.rst @@ -0,0 +1,38 @@ +.. _greenfunctions: + +The Green function class +======================== + +The TRIQS library has a class called ``gf`` which allows you to manipulate easily a whole set of Green functions. + +You can use as variable(s) + +* real time(s), + +* real frequency(ies), + +* Matsubara time(s), + +* Matsubara frequency(ies), + +* or other variables that you can define. + +More generally, the variable is a point of a ``domain`` + +The value of the Green function can be a scalar, a matrix or whatever you want (this type is called type ``target_t``). + +You can group several green functions into *blocks* (for example, one block per orbital, or per wave vector...). + +Fourier transforms are implemented for these Green functions: + + real time <-> real frequency + + Matsubara time <-> Matsubara frequency + + +.. toctree:: + :maxdepth: 2 + + concepts + fourier + cookbook/contents diff --git a/doc/reference/c++/gf/cookbook/contents.rst b/doc/reference/c++/gf/cookbook/contents.rst new file mode 100644 index 00000000..c1bb5c7e --- /dev/null +++ b/doc/reference/c++/gf/cookbook/contents.rst @@ -0,0 +1,11 @@ +.. _greenfunctions: + +Green's function cookbook +========================== + + +.. toctree:: + :maxdepth: 2 + + real + imaginary diff --git a/doc/reference/c++/gf/cookbook/imaginary.rst b/doc/reference/c++/gf/cookbook/imaginary.rst new file mode 100644 index 00000000..5e16b453 --- /dev/null +++ b/doc/reference/c++/gf/cookbook/imaginary.rst @@ -0,0 +1,61 @@ + +Create a Matsubara frequency Green function +------------------------------------------- + +The particularity here is that the statistics influences the position of the Matsubara frequencies. + +.. compileblock:: + + #include + #include + + using triqs::gf::make_gf; + using triqs::gf::imfreq; + + int main() { + double beta=1; //inverse temperature + triqs::gf::statistic_enum stat=triqs::gf::Fermion; + //we will have 5 points including iw=0 and iw=beta + size_t n_freq=5; + auto shape = triqs::arrays::make_shape(1,1); + auto GF=make_gf(beta, stat, shape, n_freq); + }; + + +An alternative declaration with an explicit construction of the underlying mesh: + +.. compileblock:: + + + #include + using namespace triqs::gf; + int main(){ + double beta=10; + int Nfreq =100; + auto fermionic_imfreq_mesh = make_gf_mesh(beta,triqs::gf::Fermion,Nfreq); + auto GF = make_gf(fermionic_imfreq_mesh, triqs::arrays::make_shape(1,1), local::tail(1,1)); + } + + +Learn more in the full referencen, see :ref:`greenfunctions` + +Create a Matsubara time Green function +-------------------------------------- +.. compileblock:: + + #include + #include + using triqs::gf::make_gf; + using triqs::gf::imtime; + + int main() { + double beta=1; //inverse temperature + triqs::gf::statistic_enum stat=triqs::gf::Fermion; + size_t n_times=5; + auto shape = triqs::arrays::make_shape(1,1); + auto GF=make_gf(beta, stat, shape, n_times); + }; + + + + diff --git a/doc/reference/c++/gf/cookbook/real.rst b/doc/reference/c++/gf/cookbook/real.rst new file mode 100644 index 00000000..a2763da2 --- /dev/null +++ b/doc/reference/c++/gf/cookbook/real.rst @@ -0,0 +1,41 @@ +Create a real time Green function +--------------------------------- + +.. compileblock:: + + #include + #include + + using triqs::gf::make_gf; + using triqs::gf::retime; + + int main() { + double tmin=0; + double tmax=10; + //we will have 5 points + size_t n_times=5; + //we want a Green function whose values are complex numbers + auto shape = triqs::arrays::make_shape(1,1); + // the type of GF is triqs::gf::gf + auto GF=make_gf(tmin, tmax, n_times, shape); + }; + +Create a real frequency Green function +-------------------------------------- +.. compileblock:: + + #include + #include + + using triqs::gf::make_gf; + using triqs::gf::refreq; + + int main() { + double wmin=0; + double wmax=10; + size_t n_freq=5; + //we want a Green function whose values are 2*2 matrices of complex numbers + auto shape = triqs::arrays::make_shape(2,2); + auto GF=make_gf(wmin, wmax, n_freq, shape); + }; + diff --git a/doc/reference/c++/gf/fourier.rst b/doc/reference/c++/gf/fourier.rst new file mode 100644 index 00000000..79ae42df --- /dev/null +++ b/doc/reference/c++/gf/fourier.rst @@ -0,0 +1,40 @@ +.. highlight:: c + +Fourier transforms +################### + +Convention +============== + + .. math:: \tilde f(\omega)=\int_{-\infty}^\infty dt f(t)e^{i\omega t} + + .. math:: f(t)=\int_{-\infty}^\infty \frac{d\omega}{2\pi} \tilde f(\omega)e^{-i\omega t} + + +Effect of a TF on the tail +=========================== + +The tail is unchanged during a TF, but its value is used to limit the errors. + +The components 1 and 2 of the tail (:math:`t_1` and :math:`t_2`) are used to improve the computation of the GF in the following way: +in the large :math:`\omega` limit, + .. math:: G(\omega)\simeq \frac{t_1}{\omega}+\frac{t_2}{\omega^2}\simeq \frac{a_1}{\omega+i}+\frac{a_2}{\omega-i} +with :math:`a_1=\frac{t_1+it_2}{2}` and :math:`a_2=\frac{t_1-it_2}{2}`. + +As these large w terms are badly taken into account if we naively Fourier transform the function described by its values on the mesh in w, we substract them, do the Fourier transform and add their Fourier transform to the result. + +We use the following Fourier tranforms: + + .. math:: \frac{2a}{\omega^2+a^2} \leftrightarrow e^{-a|x|} + + .. math:: \frac{1}{\omega+i} \leftrightarrow -i e^{-x} \theta(x) + + .. math:: \frac{1}{\omega-i} \leftrightarrow i e^{x} \theta(-x) + +For the inverse Fourier transform, the inverse procedure is used. + + + + + + diff --git a/doc/reference/c++/intro.rst b/doc/reference/c++/intro.rst new file mode 100644 index 00000000..5061ae0b --- /dev/null +++ b/doc/reference/c++/intro.rst @@ -0,0 +1,8 @@ +* At lower level, a few general purpose libraries in Python and C++, e.g. : + + * A new C++ multi-dimensional array library (triqs::arrays). + * A simple dictionary-like python :ref:`interface to HDF5 files`, which is the main data format in TRIQS. + * A thin :ref:`interface to matplotlib` to visualize various objects via the definition of a :ref:`plot protocol`. + + + diff --git a/doc/reference/c++/learn/first_mc.rst b/doc/reference/c++/learn/first_mc.rst new file mode 100644 index 00000000..f09a586b --- /dev/null +++ b/doc/reference/c++/learn/first_mc.rst @@ -0,0 +1,64 @@ + +A first external code +===================== + +.. highlight:: c + +As a first exercise you can try to write a Monte Carlo code for an Ising chain +in a magnetic field. Your goal is to write this code as an external project and +to use the Monte Carlo class provided by TRIQS. + +Take some time to read the :ref:`Monte Carlo ` chapter, but don't +read the complete example at the end of the chapter because it is precisely +what you need to do here. You can check your implementation later. + +.. _isingex: + +Ising chain in magnetic field +----------------------------- + +Here's the Hamiltonian for the problem of Ising spins in a magnetic field + +.. math:: + + \mathcal{H} = -J \sum_{i=1}^N \sigma_i \sigma_{i+1} - h \sum_{i=1}^N \sigma_i. + +The goal is to find the magnetization per spin :math:`m` of the system for +:math:`J = -1.0`, a magnetic field :math:`h = 0.5` as a function of +the inverse temperature :math:`\beta`. You can see how the results +change with the length of the chain :math:`N`. + +Implementation hints +-------------------- + +Here are a couple of implementation hints that you might want to follow. + +* In most Monte Carlo programs there is a *configuration* which is modified + along the simulation. Take enough time to think how this configuration + can be efficiently described and implement it in a separate file, say + :file:`configuration.hpp`. In this example, the configuration is a + collection of spins that can e.g. be described by a vector of integers. + +1 would be a spin up and -1 a spin down. If you're worried with memory + space, you could use a vector of booleans (true for up spins, false for + down spins). + +* More to come... + + +Solution +-------- + +In the limit :math:`N \rightarrow \infty`, the solution for the magnetization +is + +.. math:: + + m = \frac{\sinh(\beta h) + \frac{\sinh(\beta h)\cosh(\beta h)}{\sqrt{\sinh^2(\beta h) + e^{-4\beta J}}}} + {\cosh(\beta h) + \sqrt{\sinh^2(\beta h) + e^{-4\beta J}}}. + +Here's a plot of :math:`m` versus :math:`\beta` for different values of :math:`N`: + +.. image:: m_vs_beta.png + :width: 700 + :align: center + diff --git a/doc/reference/c++/learn/intro.rst b/doc/reference/c++/learn/intro.rst new file mode 100644 index 00000000..c82809f0 --- /dev/null +++ b/doc/reference/c++/learn/intro.rst @@ -0,0 +1,24 @@ + +Developing a project with TRIQS +=============================== + +Welcome to this tutorial! The goal of these notes is to give a practical +introduction to the development of a code that uses the TRIQS headers and +libraries. Rather than being completely general this tutorial will guide you +through the development of a simple CT-INT impurity solver. + +At first, we will see how to write a code that uses TRIQS but that is not meant +to become part of TRIQS. This is especially relevant when you write a pure C++ +code for your personal use. You will learn how to write a Monte Carlo +simulation with a simple example. + +The next step will be to *pythonize* your code. This is very convenient to +change parameters or do simple pre-simulation calculations. It is also +the way most of TRIQS applications are done. + + +.. toctree:: + :maxdepth: 2 + + triqs_library + first_mc diff --git a/doc/reference/c++/learn/m_vs_beta.png b/doc/reference/c++/learn/m_vs_beta.png new file mode 100644 index 0000000000000000000000000000000000000000..aa60a2bd2efa35d528aedc56bd9a0f0ee5cc420d GIT binary patch literal 5290 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 TRIQS is installed here + /home/project/src --> the sources of my project + /home/project/build --> the directory where I will compile my code + +Basically, this structure means that you have successfully installed TRIQS in +:file:`/home/triqs/install` and that you plan to have your new project under +:file:`/home/project`. Obviously you can choose any other directory but this +structure will be assumed below. + + +Start your project +------------------ + +As we just said, we will start our project in a directory +:file:`/home/project`. We will have the sources in :file:`/home/project/src` +and later build (compile) the project in :file:`/home/project/build`. Let's +start by writing some sources: + +.. code-block :: bash + + $ cd /home + $ mkdir project + $ cd project + $ mkdir src + $ cd src + +OK, our project will be just one :file:`main.cpp` file, e.g.:: + + #include + + namespace tqa = triqs::arrays; + + int main(){ + + tqa::array A(10), B(10); + A()=2; B()=3; + tqa::array C = A+B; + std::cout << "C = "<< C << std::endl; + + } + +As you can see, the code includes headers from TRIQS. Along with +:file:`main.cpp` we write a :file:`CMakeLists.txt` file to compile our project. +In order to make this easy, there is a file called :file:`TRIQSConfig.cmake` +in :file:`/home/triqs/install/share/triqs/cmake`. Including this file in +your :file:`CMakeLists.txt` automatically defines a certain number of useful +variables, especially the include directories related to the TRIQS headers and +the location of the TRIQS libraries. Here is what your simple +:file:`CMakeLists.txt` can be: + +.. code-block :: bash + + cmake_minimum_required(VERSION 2.8) + + project(myproj CXX) + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + + set(CMAKE_BUILD_TYPE Release) + + SET(CMAKE_INSTALL_RPATH "${TRIQS_PATH}/lib") + SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) + + include(${TRIQS_PATH}/share/triqs/cmake/TRIQSConfig.cmake) + + add_executable(example main.cpp) + + include_directories(${TRIQS_INCLUDE} ${EXTRA_INCLUDE} ${CBLAS_INCLUDE} ${FFTW_INCLUDE}) + target_link_libraries(example ${TRIQS_LIBRARY} ${EXTRA_LIBRARY}) + +We're all set! Everything is ready to compile our project. If we want to build +everything in :file:`/home/project/build`, we do as follows: + +.. code-block :: bash + + $ cd /home/project + $ mkdir build + $ cd build + $ cmake -DTRIQS_PATH=/home/triqs/install /home/project/src + $ make + $ ./example + +That's it! You can modify your sources and then recompile with make. Obviously +with bigger projects your :file:`CMakeLists.txt` file will change, but the +principle remains the same. + diff --git a/doc/reference/c++/lectures/basic/C++11.rst b/doc/reference/c++/lectures/basic/C++11.rst new file mode 100644 index 00000000..ee680d75 --- /dev/null +++ b/doc/reference/c++/lectures/basic/C++11.rst @@ -0,0 +1,326 @@ +.. highlight:: c + +The new C++11 standard +=============================== + +C++11 is the new standard of the C++, voted in 2011 by the International C++ Standard Committee. +It brings several improvements to the C++. +The goal of this page is to highlight a few constructs, which may be useful for us in scientific computing +in order to make C++ more accessible and ease library writing. + +A simple presentation of C++11 is given in `wikipedia `_. + +Implementation +----------------- + +The first thing is to know if/whether this standard is usable, i.e. implemented in compilers. +It turns out that recent versions of compilers (gcc, clang, icc) have already most of the features, +and the implementation is very rapidely progressing. + +A simple `page `_ present what is implemented in various compilers. +A detailed table of the implemented features with versions exists for `gcc `_ +and for `clang `_. + +.. note:: + To use C++11, pass the option -std=c++0x (all compilers), or -std=c++11 (gcc >= 4.7, clang >= 3.0). + +Rational for using C++11 +---------------------------- + +C++11 add some libraries (standardizing several boost libraries, e.g. shared_ptr), +but also and most importantly several new features in the language itself. +Some are basically *syntactic sugar*, some have a deep effect on the programming style. + +Some of these features allow a much cleaner programming with : + +* functionnal programming : introduction of lambda, in particular, also auto, decltype. +* metaprogramming (variadic template, auto, decltype, etc). + +C++11 allows : + +* Write simpler code for the User of libraries +* A lot of simplification in the writing of libraries themselves. + +In my opinion the gain in clarity that one can achieve with C++11 vastly outweigh the +cost in portability (to old versions of compilers). + +There are already many articles on C++11, and soon books, so I will only focuss on +a few examples and basic explanations. + +**Except when specified, the examples below compiles with gcc 4.6 (Ubuntu 12.04 LTS default) and clang 3.1 (current stable)** + +Rvalue references +----------------------- + +Probably one of the most useful feature is the *move semantics*, or rvalue references. + +The problem +^^^^^^^^^^^^^ + + *How to return efficiently a big object built by a function ?* + +Example : I have a function that creates a new std::vector (or any array, Green functions). +How do I return it ? + +A simple solution:: + + std::vector f ( my_parameters) { + std::vector res( vec_size); + // fill res + res[0]=1; //... + return res; + } + /// usage + std::vector v = f(1,2); // constructed a new v from the result of f call. + v = f(3,2); // reassign an already constructed v to the result of v + +Normally, this solution has a major defect : *res* is **copied** when returned from the function, +hence there is a (potentially huge) performance penalty in doing such simple code. +Most current compilers will already elide (remove) the copy in the first case, but it is not guaranteed. +And in the second case, there will be a copy. + +This situation has lead to several workarounds idioms, obscuring the coding style in C++, like :: + + // solution 1 : use pointers + std::vector * f (my_parameters) { // <---- return a pointer + std::vector res = new std::vector(vec_size); // <--- dynamical allocation + // fill res + (*res)[0] = 1; /// <---- not so nice to write + return res; + } + /// usage + std::vector * v = f(1,2); // <--- put this in shared_ptr ?? + *v = f(3,2); // <--- Oops : memory leak ! + +This has a big pb too : who is going to take care of deallocating the pointer (see shared_ptr section) ?? + +Another solution is :: + + // solution 2 : pass by reference + void f( std::vector & res, my_parameters) { // <---- pass a vector and change it + /// fill res.... + } + // usage + std::vector v; + f(v,1,2); // <------ not nice, not natural + + +The C++11 solution +^^^^^^^^^^^^^^^^^^^^^^ + +The **efficient** C++11 code is now **the simplest one** in this situation :: + + std::vector f (my_parameters) { + std::vector res(vec_size); + res[0]=1; // fill res ... + return res; + } + + /// usage + std::vector v = f(1,2); // no copy (copy elision) ! + v = f(2,3); // no copy (move operator =) !! + +In that case, there will be no useless copy. The data of the temporary will be "stolen" by v. +Since the temporary is ... temporary, this is a good strategy. Note that : + +* This is transparent in this code. The user of the vector object, + simply write the **simplest, natural code**. (it is a good idea still to understand the basic idea, see below). + +* The charge of implementing the move semantics rely on the **library writer, not the user of the class**. + +* Still, implementing this is not hard (see example below). + +* A detailed series of (readable) articles on copy elision, and move semantics by D. Abrahams + can be found `here `_. + +An example of a move constructor +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Let us now make a minimal vector class to illustrate the idea and how to implement move semantics. + +In a situation like above, the vector (or anything that provides a **move constructor**) will +alleviate the copy by *stealing the data from the returned temporary*. +The temporary will be discarded, so there is no pb in stealing its data. + +Typically a class with move semantics will provide : + +* a copy constructor, an operator =, as in C++03. +* a move constructor, a move operator= + +.. compileblock:: + + #include + #include + class my_vector { + double * data; // a piece of memory + size_t size_; // size of the piece + public : + my_vector(int s=0): data(s>0 ? new double[s] : NULL ), size_(s){} // basic constructor. Just allocate memory + ~my_vector() { if (data) delete[] data;} // free the pointer + + my_vector(my_vector const & x) { // copy contructor + std::cout << "copy construction"<< std::endl; + size_ = x.size(); data = new double[size_]; + memcpy(this->data, x.data, x.size()*sizeof(double)); // copy data in memory (low level C) + } + + my_vector & operator=( my_vector const & x) { // normal = operator + std::cout <<" normal ="<< std::endl; + size_ = x.size(); if (data) delete[] data; data = new double[size_]; + memcpy(this->data, x.data, x.size()*sizeof(double)); // copy data in memory (low level C) + return * this; + } + + my_vector(my_vector && V) { // C++11 move constructor + std::cout <<" move constructor"<< std::endl; + data = V.data; V.data = NULL; // swap the data with V and let V empty ! + size_ = V.size_; V.size_ = 0; + } + + my_vector & operator=( my_vector && V) { // C++11 move = operator + std::cout <<" Move ="<< std::endl; + std::swap(V.data, this->data); // swap data + std::swap(V.size_, this->size_); + return * this; + } + // ------ standard interface to vector (minimal) -------------------- + double const & operator[](size_t i) const { return (data)[i];} + double & operator[](size_t i) { return (data)[i];} + size_t size() const { return size_;} + friend std::ostream & operator <<( std::ostream & out, my_vector const & v) { + for (size_t i =0; i A(2,3), B(2,3); + auto expr = A + 2*B; + + +for range loop +----------------- + +For any object that have iterators (in fact it is more general ....), a simpler syntax to iterate on them is. +Example :: + + std::vector V = {1,2,3}; + for (auto & x : V) { + // do something with x ....(it is a reference) + } + + +Initializer list +------------------ + +Example :: + + std::vector V = {1,2,3}; + triqs::arrays::matrix M = {{1,2},{3,4}}; // not implemented yet.... + +Lambda +------------ + +As in python, C++11 now supports simple lambda functions :: + + auto f = [](int) { return x+1;} + int u = f(3); // use as a regular function... + +* It still allow inlining. + +* This is particularly useful with the STL algorithms, or similar iteration algorithms : + +.. + .. literalinclude:: count_if.cpp + +.. compileblock:: + + #include + #include + #include + + int main() + { + std::vector v = { -1, -2, -3, 4, -4, 3, -7, 8, 9, 10 }; + int num_items1 = std::count_if(v.begin(), v.end(), [](double i) {return i>0;}); + std::cout << "number of >0 : " << num_items1 << '\n'; + + int bound = 3; + num_items1 = std::count_if(v.begin(), v.end(), [&bound](double i) {return i>bound;}); + std::cout << "number of >bound : " << num_items1 << '\n'; + } + + +Variadic template +--------------------- + +Improvement of the standard library +--------------------------------------- + +Most notably : + +* std::shared_ptr, and std::unique_ptr (see Smart Pointers). +* std::unordered_map + +In most cases, this is a standardisation of some boost libraries. + diff --git a/doc/reference/c++/lectures/basic/compile_time_decision.rst b/doc/reference/c++/lectures/basic/compile_time_decision.rst new file mode 100644 index 00000000..fb1a1114 --- /dev/null +++ b/doc/reference/c++/lectures/basic/compile_time_decision.rst @@ -0,0 +1,13 @@ +Various ways to take a decision at compile time +############################################### + +* Overloading : often forgotten. Use of tags + +* std::conditionnal or mpl::if\_ + +* std::enable_if + In combination with a template <> + 1 default ... + +* template technique : specialisation, traits ... + + diff --git a/doc/reference/c++/lectures/basic/contents.rst b/doc/reference/c++/lectures/basic/contents.rst new file mode 100644 index 00000000..3fa06ed3 --- /dev/null +++ b/doc/reference/c++/lectures/basic/contents.rst @@ -0,0 +1,16 @@ +General C++ techniques and idioms +************************************************************************************ + +.. highlight:: c + +.. toctree:: + :maxdepth: 1 + :numbered: + + C++11 + concepts + smart_ptr + functions + compile_time_decision + + diff --git a/doc/reference/c++/lectures/basic/functions.rst b/doc/reference/c++/lectures/basic/functions.rst new file mode 100644 index 00000000..13c73c1f --- /dev/null +++ b/doc/reference/c++/lectures/basic/functions.rst @@ -0,0 +1,14 @@ +Functions becomes first class citizens ... +################################################# + +* functional programming : another paradigm ... + +* std::function : store a function in a an object +* currifying: std::bind, std::placeholders. +* Do not USE function pointers.... +* Function objects : wrap functions into an objects.... +* lambda : example of use, STL.... + + + + diff --git a/doc/reference/c++/lectures/basic/smart_ptr.rst b/doc/reference/c++/lectures/basic/smart_ptr.rst new file mode 100644 index 00000000..067969dc --- /dev/null +++ b/doc/reference/c++/lectures/basic/smart_ptr.rst @@ -0,0 +1,182 @@ +.. highlight:: c + +Pointers : from the evil to the smart... +###################################################### + +Raw pointers +=============== + +Raw pointers are ordinary C/C++ pointers. + +Pointers allow to manipulate objects by reference (or indirectly). + +RefTo : stack/heap. Pointers in C++... + +They are used e.g. to allocate a new object on the heap :: + + { + A * p = new A( constructor_arguments); // allocated and constructed on the heap. + A a( constructor_arguments); // constructed on the stack + + delete p; // release memory + } + +Raw pointers are the source of many bugs in C++. Two main dangers are : + +* memory leak : when one forget to release the memory allocated to the pointer:: + + { + A * p = new A( constructor_arguments); // allocated and constructed on the heap. + // + // forgot to delete. but p is gone.... + } + +* a more subtle memory leak :: + + { + A * p = new A( constructor_arguments); // allocated and constructed on the heap. + // working with p... + delete p; + } + + What happens if there is an exception during the work ?? + The pointer is not deallocated (but all objects on stack would be destroyed). + +* dangling pointers : reusing a pointer after the object has been deleted :: + + { + A * p = new A( constructor_arguments); // allocated and constructed on the heap. + //... + A *q =p; a copy of the pointer is made somewhere + //... + delete p; + // ... + q->method(..) ; // DEAD : segfault. + } + +To conclude : + +* pointers are a low level object + +* pointers induce many dangers... + +The solution +==================== + +Smart pointer are a way to manipulate objects by reference with strong guarantee +that such common problems will **never** happen. + +The bottom line can be summarized as : + + *Smart pointers are pointers with strong guarantee to avoid dangling references and memory leaks.* + + +In order to avoid pointers problems, the style recommendation are : + +#. Try to avoid pointers ! Use object by value, and objects like std::vector + which hide the dynamic allocation of memory from the user in a safe manner. + +#. If you need a pointer to an object A which is pointed to by exactly one pointer + (a local object), then use std::unique_ptr (or boost:scoped_ptr if you insist on non C++11). + +#. If you need an object A shared by multiple objects, i.e. pointed to by several pointers + use a std::shared_ptr. + +#. Only when other options are not good, and in practice only at low level libraries, + use raw pointers to allocate objects, with new and delete. + +std::unique_ptr +--------------------- + +Example :: + + { + std::unique_ptr p( new A( constructor_arguments) ); // allocated and constructed on the heap and stored. + // + // working with p. p has the semantics of a pointer : + // p-> method(), p->data, etc ... + // NO DELETE : when the std::unique_ptr is getting out of scope and is destroyed the + // underlying raw pointer are freed. + } + +Note that : + +* a unique_ptr **can not be copied**. If you put it as a member of a class, this class can therefore not be copied. + +* a unique_ptr **can be moved** (see lecture on move semantics). + +* This writing is exception-safe. If an exception occurs in the treatment, then C++ guarantees + the all the local objects are destroyed, hence p and the underlying raw pointer is deleted. + +* unique_ptr has little if no overhead in critical code. + + +std::shared_ptr +--------------------- + +(or boost::shared_ptr < C++11). + +In the case where we want to **share** an object, i.e. that multiple pointers points to an object, +we have to use std::shared_ptr. + +A shared_ptr is no more than : + +* a pointer to the object + +* a reference counter, counting how many shared_ptr point to the objects. + + +When the shared_ptr are copied, assigned, the reference counter is updated accordingly. + +* When a shared_ptr is created, copied, ref_counter is increased by 1. +* When a shared_ptr is deleted, ref_counter is decreased by 1. + +When the last shared_ptr to an object is destroyed, the reference counter gets +to 0 and the pointed objects is deleted. + +Example :: + + class A; + + boost::shared_ptr p (construction_parameters); + + // work with p like a pointer + // p has pointer semantic. *p, p->method as for raw pointer + + // NO delete + + +Example :: + + class A; + + boost::shared_ptr p1 (construction_parameters); + boost::shared_ptr p2 (construction_parameters); + + // p1 ----> ( a1, ref_counter = 1 ) + // p2 ----> ( a2, ref_counter = 1 ) + + { // group start + boost::shared_ptr p3 = p2; + // p1 ----> ( a1, ref_counter = 1 ) + // p2 ----> ( a2, ref_counter = 2 ) + // p3 ----> ( a2, ref_counter = 2 ) + + } // group ends ... p3 is deleted + + // p1 ----> ( a1, ref_counter = 1 ) + // p2 ----> ( a2, ref_counter = 1 ) + + p1 = p2; + // p1 ----> ( a1, ref_counter = 2 ) + // p2 ----> ( a1, ref_counter = 2 ) + // a2 has been destroyed. + + + + + + + + + diff --git a/doc/reference/c++/lectures/contents.rst b/doc/reference/c++/lectures/contents.rst new file mode 100644 index 00000000..50a6520c --- /dev/null +++ b/doc/reference/c++/lectures/contents.rst @@ -0,0 +1,30 @@ +Notes for TRIQS C++ contributor +********************************* + + *Our goal : write clear, readeable, high-level and yet efficient programs.* + +The goal of these notes is to be : + +* a starting point for learning modern C++ for scientific computation : + Traditionnally, it is often said that genericity, abstraction (i.e. high-level) programming + is not compatible with the efficency that we need in scientific computations. + The goal of these lectures is to show that we can achieve these goals with today C++ and libraries. + +* a style guide for the TRIQS project (C++ part). + +Most of the content is more general (and independant of the TRIQS project). +They are a few notes on modern C++ for scientific computations. + +The intended audience is physicists with a basic knowledge of C++ (??). +These lectures do not focuss on basic syntax, but on useful **idioms**. + + +.. highlight:: c + +.. toctree:: + :maxdepth: 1 + :numbered: + + basic/contents + patterns/contents + concepts/contents diff --git a/doc/reference/c++/lectures/goal.rst b/doc/reference/c++/lectures/goal.rst new file mode 100644 index 00000000..9c1b9197 --- /dev/null +++ b/doc/reference/c++/lectures/goal.rst @@ -0,0 +1,25 @@ +Introduction +============ + +*Our goal : write clear, readeable, high-level and yet efficient programs.* + +This is the motto of the lectures. +Traditionnally, it is often said that genericity, abstraction (i.e. high-level) programming +is not compatible with the efficency that we need in scientific computations. +The goal of these lectures is to show that we can achieve these goals with today C++ and libraries. + +Why is it important? +-------------------- + +* Our codes are changing all the times. We want to have code reuse. + +* more to come here + + +Goal of the lectures +-------------------- + +* Present some patterns and techniques which are useful to write high level and efficient codes. +* Fix the "pattern" design of TRIQS. One problem : one standardised solution. + + diff --git a/doc/reference/c++/lectures/intro.rst b/doc/reference/c++/lectures/intro.rst new file mode 100644 index 00000000..c2306552 --- /dev/null +++ b/doc/reference/c++/lectures/intro.rst @@ -0,0 +1,31 @@ + +User Manual : the complete (?) reference +******************************************* + +.. warning:: + This library is beta. + + This manual is not finished: work in progress. + + +.. highlight:: c + +.. toctree:: + :maxdepth: 2 + :numbered: + + view_or_not_view + basic_classes + slicing + shape + debug + assignment + algebras + foreach + functional + STL + H5 + Interop_Python + IO + blas_lapack + FAQ diff --git a/doc/reference/c++/lectures/patterns/assign_delegation.rst b/doc/reference/c++/lectures/patterns/assign_delegation.rst new file mode 100644 index 00000000..b243a4e2 --- /dev/null +++ b/doc/reference/c++/lectures/patterns/assign_delegation.rst @@ -0,0 +1,133 @@ +.. highlight:: c + + +Assignment Delegation +=============================== + +Problem +------------ + +Given a class A which defines an `operator =`, we would like to +be able to implement various optimisation depending on the RHS (right hand side). + +Normally, we can simply define various operator in class A :: + + class A { + // ... + template A & operator = (RHS rhs); + } + +maybe with some enabler to choose for different types. + +Normally RHS are expected to model some precise concept (e.g. array, green function, etc...). +In other words, RHS are looking "like an A". +It is then easy to implement a generic version of operator = that uses just the concept. + +We would like to be able to implement various optimisations depending on the RHS (right hand side). +This optimisation are decided are compile time and maybe also at run time. + +Of course, we could split the definition of operator = into cases with enable_if. +But we want a non-intrusive solution, i.e. be able to add an optimisation +for a new type of RHS, without modifying the class A. + +Real life examples +^^^^^^^^^^^^^^^^^^^^^^^^ + +* array, matrix, vector, with RHS a generic proto expression. For example in triqs::arrays :: + + M = inverse(M); // (1) + M = 2*inverse(M); // (2) + + inverse returns an inverse_lazy object. We would like that the inversion is done in place, *without + temporary* in this (1), but obviously not for a general expression like (2). + +* Green function, for example in the case :: + + gf = fourier (gt) ; + + The Fourier transformation could be done directly in the gf data, without a temporary, + if this becomes a bottleneck the code (?). + + The point here is also that we can first implement a generic algorithm. If we need, + we know that we will be able to optimise this temporary *without any change in the user code*. + +Solution +------------------ + +A simple solution is to delegate the assignement and simply use overload e.g. :: + + template + void assign_delegation (LHS & lhs, RHS const & rhs) { + // implement the generic algorithm + } + + class A { + // ... + template A & operator = (RHS const & rhs) { assign_delegation(*this, rhs);} + } + +And then later when defining MyRHS_with_optimisation :: + + class MyRHS_with_optimisation { + // .... implement the object ... + + template + friend void assign_delegation (LHS & lhs, MyRHS_with_optimisation const & rhs) { + // implement the special algorithm + } + }; + +**NB** : Adding the function as a friend in the class has 2 advantages over defining it outside: + + * It is friend, hence it can access the data of rhs. + * It will be injected in the namespace where the class MyRHS_with_optimisation, and therefore it will be found by ADL. + +Variant +^^^^^^^^^^ + +With the same technique, one can also delegate the compound assignments : +=, -=, *=, /=. + +Let us label these operators by a char :A, S, M, D. We can then differentiate between the various +case by adding an additionnal dummy parameter of mpl::char_ type:: + + template + void compound_assign_delegation (LHS & lhs, RHS const & rhs, mpl::char_) { + // implement the generic algorithm + } + + class A { + + template A & operator += (RHS const & rhs) { + compound_assign_delegation(*this, rhs, mpl::char_<'A'>() ); + } + + // and so on... + } + +And then later when defining MyRHS_with_optimisation :: + + class MyRHS_with_optimisation { + // .... implement the object ... + + template + friend void compound_assign_delegation (LHS & lhs, MyRHS_with_optimisation const & rhs,mpl::char_<'E'>) { + // implement the special algorithm + } + }; + +**NB** : + +* One can then overload some or all of the operations for a given class. + +* mpl::char_<'A'> is a different **type** than mpl::char_<'S'>, so the standard overload mechanism of C++ will + choose the right function at compile time (the `mpl::char_` object is tiny, and will be optimized away). + It better than passing a simple char and make a switch at run time (because there is no compile time choice in this case). + +* One could a priori also add a char OP in the template parameter list, but then in the MyRHS_with_optimisation class, we would need + to specialize a function, which results in less readeable code, IMHO. + +Examples +----------- + +Used in triqs::arrays. + diff --git a/doc/reference/c++/lectures/patterns/contents.rst b/doc/reference/c++/lectures/patterns/contents.rst new file mode 100644 index 00000000..817cb031 --- /dev/null +++ b/doc/reference/c++/lectures/patterns/contents.rst @@ -0,0 +1,24 @@ +.. highlight:: c + +Some useful idioms and patterns +####################################### + +The goal of this list of patterns is to : + +* illustrate some useful (?) patterns in C++. +* document TRIQS code and standardize the way things are implemented in TRIQS + + +.. toctree:: + :maxdepth: 1 + + h5_read_write + lazy_objects + type_erasure + python + assign_delegation + proto + preproc + iterator + + diff --git a/doc/reference/c++/lectures/patterns/h5_read_write.rst b/doc/reference/c++/lectures/patterns/h5_read_write.rst new file mode 100644 index 00000000..f2695e3c --- /dev/null +++ b/doc/reference/c++/lectures/patterns/h5_read_write.rst @@ -0,0 +1,148 @@ +.. highlight:: c + +HDF5 write/read convention +================================ + + +All TRIQS objects that can be h5-serialized (i.e. put into an hdf5 file and reconstructed from it) +follow the following convention. + +Convention +-------------- + +For each h5-serializable TRIQS object, one defines **free functions** *h5_read*, *h5_write* with the synopsis :: + + // Write the object into the group or file F, either directly (for array, basic type) + // or by opening a subgroup and writing its components into this subgroup. + h5_read ( h5::group_or_file F, std::string const & Name, MyNiceObject & obj); + + // The inverse operation. It fills the object from the file. The object must exists before. + h5_write ( h5::group_or_file F, std::string const & Name, MyNiceObject const & obj); | + +* h5::group_or_file is a little opaque object that can be transparently constructed + from the two types H5::Group and H5::H5File (respectively the Group and the File in the HDF5 library). + +* Recommended practice : **define these functions as friend functions of the class**. + + *Rational* : they will access the data and by resolved by ADL. + +Example : +---------- + +Suppose I have an object with one array A and a string: + +.. compileblock:: + + #include + #include + namespace tqa= triqs::arrays; + + class MyNiceObject { + tqa::array A; + double x; + std::string s; + public : + MyNiceObject(): A(2,3), x(3), s("wonderful") { A() = 3;} + + friend void h5_write (triqs::h5::group fg, std::string subgroup_name, MyNiceObject const & obj) { + auto g = fg.create_group(subgroup_name); + h5_write(g,"A",obj.A); + h5_write(g,"x",obj.x); + h5_write(g,"s",obj.s); + } + + friend void h5_read (triqs::h5::group fg, std::string subgroup_name, MyNiceObject & obj){ + auto g = fg.open_group(subgroup_name); + h5_read(g,"A",obj.A); + h5_read(g,"x",obj.x); + h5_read(g,"s",obj.s); + } + }; + + int main() { + H5::H5File file("ess.h5", H5F_ACC_TRUNC ); + MyNiceObject a; + h5_write(file, "a1", a); + h5_write(file, "a2", a); + } + +The generated file looks like:: + + > h5ls -r ess.h5 + / Group + /a1 Group + /a1/A Dataset {2, 3} + /a1/s Dataset {SCALAR} + /a1/x Dataset {SCALAR} + /a2 Group + /a2/A Dataset {2, 3} + /a2/s Dataset {SCALAR} + /a2/x Dataset {SCALAR} + +and the full dump as :: + + HDF5 "ess.h5" { + GROUP "/" { + GROUP "a1" { + DATASET "A" { + DATATYPE H5T_IEEE_F64LE + DATASPACE SIMPLE { ( 2, 3 ) / ( 2, 3 ) } + DATA { + (0,0): 3, 3, 3, + (1,0): 3, 3, 3 + } + } + DATASET "s" { + DATATYPE H5T_STRING { + STRSIZE 9; + STRPAD H5T_STR_NULLTERM; + CSET H5T_CSET_ASCII; + CTYPE H5T_C_S1; + } + DATASPACE SCALAR + DATA { + (0): "wonderful" + } + } + DATASET "x" { + DATATYPE H5T_IEEE_F64LE + DATASPACE SCALAR + DATA { + (0): 3 + } + } + } + GROUP "a2" { + DATASET "A" { + DATATYPE H5T_IEEE_F64LE + DATASPACE SIMPLE { ( 2, 3 ) / ( 2, 3 ) } + DATA { + (0,0): 3, 3, 3, + (1,0): 3, 3, 3 + } + } + DATASET "s" { + DATATYPE H5T_STRING { + STRSIZE 9; + STRPAD H5T_STR_NULLTERM; + CSET H5T_CSET_ASCII; + CTYPE H5T_C_S1; + } + DATASPACE SCALAR + DATA { + (0): "wonderful" + } + } + DATASET "x" { + DATATYPE H5T_IEEE_F64LE + DATASPACE SCALAR + DATA { + (0): 3 + } + } + } + } + } + + + diff --git a/doc/reference/c++/lectures/patterns/lazy_objects.rst b/doc/reference/c++/lectures/patterns/lazy_objects.rst new file mode 100644 index 00000000..6a0ae9d7 --- /dev/null +++ b/doc/reference/c++/lectures/patterns/lazy_objects.rst @@ -0,0 +1,47 @@ +.. highlight:: c + +Lazy Objects +==================== + +PreCompute in Lazy Object +----------------------------- + +* why a lazy object +* example + +* idea : keep a view or a copy and then implement the concept. +* add possibly some optimisation + +* When precomputation are needed. + --> LazyPreCompute pattern with the shared_ptr + + Ex :: + + class MyLazyObject { + + // .. + private: + + struct internal_data { + // contains the data for the precomputation + // e.g. std::vector data; + internal_data(MyLazyObject const & P) { + // do the computation and fill the data + // data = ...; + } + }; + friend struct internal_data; // internal_data can read the parent object P + mutable boost::shared_ptr _id; // holds the data + void activate() const { if (!_id) _id= boost::make_shared(*this);} + + } + +Comments : + +* The data is hold in a specialized struct `internal_data`, which contains the precomputation. +* The data is hold by a shared_ptr, _id : + + * The copy of MyLazyObject is then cheap and safe with shared_ptr. + * If the computation is not necessary, _id is empty, there is no memory usage. + * activate() activates the calculation of the internal data. + * _id is mutable : the precomputation is private, so even a const object should be able to activate safely. diff --git a/doc/reference/c++/lectures/patterns/python.rst b/doc/reference/c++/lectures/patterns/python.rst new file mode 100644 index 00000000..93b5b447 --- /dev/null +++ b/doc/reference/c++/lectures/patterns/python.rst @@ -0,0 +1,57 @@ +Python bindings +##################### + +All the idioms that we use from boost.python .... + +Introduction to boost.python +============================== + +* wrapping versus converting. + +Example of wrapping a function, a class, with an array. + +Using a more complex converters. + +Wrapping enable a converter. + +* converting : principle. + Ref to doc. + The simple triqs way to build a converter. + Example of range ! + +* Passing a pyobject. + +* Difference between PyObject* and bpy::object + Reference counting. + +* More sophisticated data structure. + +* THE TRIQS tools : a thin layer (converter) for recursive conversion + (e.g. vector , unordered_map, ....) + + +boost.python : a C++ API for python +====================================== + +Code injection +================= + +The problem. + +The solution : injection and documentation. + +Examples +========== + +Passing a dict for parameters in a routine. + +Passing a list of gf_view into a vector of gf_view... +---> make it a const vector to avoid changing it.... + +Other options +============== + +* Swig +* Cython + + diff --git a/doc/reference/c++/lectures/patterns/type_erasure.rst b/doc/reference/c++/lectures/patterns/type_erasure.rst new file mode 100644 index 00000000..270c74db --- /dev/null +++ b/doc/reference/c++/lectures/patterns/type_erasure.rst @@ -0,0 +1,55 @@ +Type erasure : from static to dynamical polymorphism +############################################################ + +* What is the issue ? +* A basic example : std::function +* Example : +* A real life example : QMC class. +* The classical C++ solution with virtual functions + + + +Polymorphism +================ + +Static polymorphism (template, generic programming) +--------------------------------------------------------- + +Dynamical polymorphism. + +The crossing : why ? How ? +Concepts. When is the decision taken : at compile time or a run time ? + +A simple example : std::function +Can handle any function or object which ahs the concept double(int,int) e.g. +It **erases** the type of the object. + +The pb : find an envelop for an object with : + * the concept + * one type, that can handle any type. +---> Add Abrahams definitions ( contruct + =). + +An example : + +Pb is twofold : +* keep the undelying alive +* call its methods wihout remembering its type. + +--> show a solution +Use std::function + std::bind variant without lambdas. +Use shared_ptr +* shared_ptr the universal handle + +--> Hum : pb : restore the value semantics ! + +* The traditionnal C++ way using 3 classes. ugly... + +The envelop as a concept checker ??? +--> It does not compile it T does not model the concept. + +Python : a general type eraser : PyObject * or boost::python::object. + +2 frontiers : template, C++ polymorphism, Python : in easy and in speed. + + + diff --git a/doc/reference/c++/lectures/patterns/view_value.rst b/doc/reference/c++/lectures/patterns/view_value.rst new file mode 100644 index 00000000..8a4fcb02 --- /dev/null +++ b/doc/reference/c++/lectures/patterns/view_value.rst @@ -0,0 +1,18 @@ +ViewValue pattern in TRIQS +################################## + +* for array, matrix, vector, tail, gf of any kind. +* always of the same form. + +* A value class with value semantics +* A view class to take partial views & slices, with view semantics. + +How to implement ? + +* X_impl + --> X and X_view by derivation : reimplement only construction (PATTERN) and =. + +* Rational : + do NOT derive X from X_view ! + + diff --git a/doc/reference/c++/lectures/patterns/writing_an_iterator.rst b/doc/reference/c++/lectures/patterns/writing_an_iterator.rst new file mode 100644 index 00000000..865089d1 --- /dev/null +++ b/doc/reference/c++/lectures/patterns/writing_an_iterator.rst @@ -0,0 +1,42 @@ +How to write quickly and efficently an iterator +====================================================== + +* Do not use too much iterators, usually for loops are more efficient. + +* Iterators are mainly useful in combination with STL. + +* The best way to have an STL compliant iterator is to use the boost::iterator_facade documented + `here `_ + +Example (stupid since std::vector already has an iterator) :: + + #include + + template + class my_iterator : public boost::iterator_facade< my_iterator , const std::ptrdiff_t , boost::forward_traversal_tag > { + public: + typedef CuboidMap indexmap_type; + typedef typename indexmap_type::domain_type domain_type; + typedef IterationOrder iteration_order; + typedef typename domain_type::index_value_type indices_type; + typedef const std::ptrdiff_t return_type; + + my_iterator (): Parent(NULL), pos(0),atend(true) {} + my_iterator (const indexmap_type & P, bool atEnd=false): Parent(&P), pos(Parent->start_shift()),atend(atEnd) {} + + indices_type const & indices() const { return indices_tuple; } + operator bool() const { return !atend;} + + private: + friend class boost::iterator_core_access; + void increment(); // below + bool equal(my_iterator const & other) const {return ((other.Parent==Parent)&&(other.atend==atend)&&(other.pos==pos));} + return_type & dereference() const { assert (!atend); return pos; } + + const indexmap_type * Parent; + indices_type indices_tuple; + std::ptrdiff_t pos; + bool atend; + }; + + diff --git a/doc/reference/c++/lectures/smart_pointers.cpp b/doc/reference/c++/lectures/smart_pointers.cpp new file mode 100644 index 00000000..f4b95197 --- /dev/null +++ b/doc/reference/c++/lectures/smart_pointers.cpp @@ -0,0 +1,91 @@ +#include +#include + + +class myObject{ + + int i; + + public: + + myObject(){} + myObject(int i_):i(i_){} + int getValue() const {return i;} +}; + + + +struct A{ + + +}; + +struct B{ + int data; + boost::shared_ptr p; +}; + +struct C{ + boost::shared_ptr p; +}; + + +int main(){ + + /* WHY POINTERS? */ + + + + + myObject A(0); // object is allocated on the stack + + /* stack VS heap */ + // small variables on the stack + // dynamical memory on the heap == "new" + + //when running, the OS has allocated the stack size... + //when allocatinh by new ==> HEAP, one asks the kernel for space in the system ... takes time! + //RULE: in critical loops, do not allocate using new ! + + //stack: only for objects whose size is known at compile time + + //array lib : minivector on stack, to avoid allocation problems (ulimit... + + + std::cout << A.getValue()<getValue() << std::endl; + std::cout << (*p1).getValue() << std::endl; + + + + /* THE ISSUE */ + delete(p1); // deletes the pointer but not the underlying data + + + + /* SHARED POINTER */ + boost::shared_ptr p1_sh(new myObject(1)); + + std::cout << p1_sh->getValue()< p2_sh = p1_sh; + + std::cout << p2_sh->getValue()<`. + +The configuration +***************** + +We start by defining a configuration class on which the move and measure +classes will act. We write this class in a file :file:`configuration.hpp`:: + + #ifndef configuration_hpp + #define configuration_hpp + + // The configuration of the system + struct configuration { + + // N is the length of the chain, M the total magnetization + // beta the inverse temperature, J the coupling , field the magnetic field and energy the energy of the configuration + // field the magnetic field and energy the energy of the configuration + int N, M; + double beta, J, field, energy; + + // the chain of spins: true means "up", false means "down" + std::vector chain; + + // constructor + configuration(int N_, double beta_, double J_, double field_): + N(N_), M(-N), beta(beta_), J(J_), field(field_), energy(-N*(J-field)), chain(N,false) {} + + }; + + #endif + +The move +******** + +The move class should have three methods: `attempt()`, `accept()` and `reject()`:: + + #ifndef moves_hpp + #define moves_hpp + + #include + #include + #include "configuration.hpp" + + // A move flipping a random spin + struct flip { + + configuration * config; + triqs::mc_tools::random_generator &RNG; + + int site; + double delta_energy; + + // constructor + flip(configuration & config_, triqs::mc_tools::random_generator & RNG_) : + config(&config_), RNG(RNG_) {} + + double attempt() { + // pick a random site + site = RNG(config->N); + + // find the neighbors with periodicity + int left = (site==0 ? config->N-1 : site-1); + int right = (site==config->N-1 ? 0 : site+1); + + // compute energy difference from field + delta_energy = (config->chain[site] ? 2 : -2) * config->field; + + // compute energy difference from J + if(config->chain[left] == config->chain[right]) { + delta_energy += (config->chain[left] == config->chain[site] ? 4 : -4) * config->J; + } + + // return Metroplis ratio + return std::exp(-config->beta * delta_energy); + } + + // if move accepted just flip site and update energy and magnetization + double accept() { + config->M += (config->chain[site] ? -2 : 2); + config->chain[site] = !config->chain[site]; + config->energy += delta_energy; + + return 1.0; + } + + // nothing to do if the move is rejected + void reject() {} + }; + + #endif + + +Measure +******* + +The measure class has two methods, `accumulate` and `collect_results`:: + + + #ifndef MEASURES_HPP + #define MEASURES_HPP + + #include "configuration.hpp" + + // The measure of the magnetization + struct compute_m { + + configuration * config; + double Z, M; + + compute_m(configuration & config_) : config(&config_), Z(0), M(0) {} + + // accumulate Z and magnetization + void accumulate(int sign) { + + Z += sign; + M += config->M; + + } + + // get final answer M / (Z*N) + void collect_results(boost::mpi::communicator const &c) { + + double sum_Z, sum_M; + boost::mpi::reduce(c, Z, sum_Z, std::plus(), 0); + boost::mpi::reduce(c, M, sum_M, std::plus(), 0); + + if (c.rank() == 0) { + std::cout << "Magnetization: " << sum_M / (sum_Z*config->N) << std::endl << std::endl; + } + + } + + }; + + #endif + + +Main program +************ + +The Monte-Carlo itself can now be written:: + + #include + #include + #include + #include + + #include "moves.hpp" + #include "configuration.hpp" + #include "measures.hpp" + + int main(int argc, char* argv[]) { + + // initialize mpi + boost::mpi::environment env(argc, argv); + boost::mpi::communicator world; + + // greeting + if (world.rank() == 0) std::cout << "Ising chain" << std::endl; + + // Prepare the MC parameters + int N_Cycles = 500000; + int Length_Cycle = 50; + int N_Warmup_Cycles = 100000; + std::string Random_Name = ""; + int Random_Seed = 374982 + world.rank() * 273894; + int Verbosity = (world.rank() == 0 ? 2 : 0); + + // Construct a Monte Carlo loop + triqs::mc_tools::mc_generic IsingMC(N_Cycles, Length_Cycle, N_Warmup_Cycles, + Random_Name, Random_Seed, Verbosity); + + // parameters of the model + int length = 100; + double J = -1.0; + double field = 0.5; + double beta = 0.5; + + // construct configuration + configuration config(length, beta, J, field); + + // add moves and measures + IsingMC.add_move(flip(config, IsingMC.RandomGenerator), "spin flip"); + IsingMC.add_measure(compute_m(config), "measure magnetization"); + + // Run and collect results + IsingMC.start(1.0, triqs::utility::clock_callback(-1)); + IsingMC.collect_results(world); + + return 0; + } + + +This yields:: + + Ising chain + + 1%; 2%; 3%; 4%; 5%; 6%; 7%; 8%; 9%; 10%; 11%; 12%; 13%; 14%; 15%; 16%; 17%; + 18%; 19%; 20%; 21%; 22%; 23%; 24%; 25%; 26%; 27%; 28%; 29%; 30%; 31%; 32%; 33%; + 34%; 35%; 36%; 37%; 38%; 39%; 40%; 41%; 42%; 43%; 44%; 45%; 46%; 47%; 48%; 49%; + 50%; 51%; 52%; 53%; 54%; 55%; 56%; 57%; 58%; 59%; 60%; 61%; 62%; 63%; 64%; 65%; + 66%; 67%; 68%; 69%; 70%; 71%; 72%; 73%; 74%; 75%; 76%; 77%; 78%; 79%; 80%; 81%; + 82%; 83%; 84%; 85%; 86%; 87%; 88%; 89%; 90%; 91%; 92%; 93%; 94%; 95%; 96%; 97%; + 98%; 99%; 100%; + + Total number of measures: 500000 + Average sign: 1 + + Magnetization: 0.0927603 + diff --git a/doc/reference/c++/mctools/loop.png b/doc/reference/c++/mctools/loop.png new file mode 100644 index 0000000000000000000000000000000000000000..1410698cbd9777a50a0a55e02071741535212f87 GIT binary patch literal 59821 zcmce;c|6qX`#(NHlq~63N=OSuQ3***aY_;@TO}q5iJ|O_8M3yBQx3AHg^(@GU@)XO zvL^I9x@#*0 z0ueU4@cUH=gdYWg@Fojx2H&U|U91NmJYH7~^*5cVMScPQ*>eBFbuS1+N}ThL$2sF0 zcm%T3``k5ea}OtPKYLF{h>44Xr-v8#-ySn3Cl?3DV6w&o2xRJr(eGz1{QGAIx0LU; zOw(eA7wtR$<(Y}J)^6wDdHfoM`38PeQ4a2{&ntN(ChNT0+Udkr)i;6<&P9YHg&E>2 ze>98mTzRDO_)+qM&C#b`K30DeEdL=mt)`o1Wo_*T{!-*KCKfMLnx*BQvc%-hAcAR2 zsb;8!I6y7MVgQE8FI`)jPnU;h(62xlve+r0~Ck%v?r-cg|NLuH-SfQ zCA~T;JrbrPqv!VGrN9}OMIm<6E%5N>IN@F4$8?KI9#X0#3W@8B`0C-Z?GRSU!ZITx zVe7+*N-eN<2R^7{PxSEFG-0IHGq^$sk972XVbg*ypI~5$wUq5(3Y}Lu7m54t`&(#) zJYtVPA(LSiRK~$!H86m;X^Zfum$DswB)^hg&0;bi4#F#h!Wb8PNfAPU*(Y61?}|0d zhL{TAGW-3Sdzrl=>UEU%V39NOZ$pW)w_}Y8nij!B5XjOIr4xbJ_lG--o6z=$Yx@m0;7<}PcOp*c;V2_7y zwr>%+i=;9>B$50EPeIo9NHFz`sX`D)?HNz~u%k`_7F3}`qe%6}+MjSv$iW zQ|tAAjaf7Qe~($%@&6n{!HS0Hi7|ofk5W^C@cMWpn41JSd;4R9KPF*Bd0q!)_Vq&h zOPe7{FbXq*HGj=z}dqs(gwTwPtdESq|KM>3XkpFU&j@0`-X6x>L}H; zP5;|7%5?s^LXtIS+aVj2z;`j(g8$bnu_(UioJtbLY{quwo!ZXz-Ju*M+noL%s>^C$ z=8B>axHd=F+HGQw#yzfTY&*T78vM9Dbh3f8jWCiQ$9*#L#KsRP{5V%UghL>CxH17b zFNCzgzZd@}gJj>3v}Eo$9yvV;@BC3O8k=RRqtQ>z*TIT3TEPO1N+)$G1ywb-DAv}W z@~v0}IC9V3)d!8Ohpi>pvUZ{rQO{sRMfKU@w#k##;2K?0$k0QZ#evJ8SY#II-~I> zS66=jsca=Azt-gES5Mr`-OAG&sY7wgYoDGmhIXH9x#2TcQGwL3Q9M#A^PRooiLi!w z8V!@(dfLC|Wcv;pYE4+~gd+lGdx(LqrBt|wD?+wUPqLaZXe(d%8d?)6OP{Zn%{%vjq78x14|uD=)IOuRu{e3ej30N~$48 zaT$&6{|0~`k3Ckc0}Ha}<)IQvgK04j%Q z*WLF{_4lt;xZxCHv=uDqf%~2^c7n~;!YGMh@=S;A)+1J!&gTCrL`>XUhq@s!t+Rm_=oE0+{)#57}r4`e0RR{^q=N|C_A5T zXsJfkDmyL5-#uq@9c*PAtB#g+u0){i-MR>p4I0>>l45t~ZBfH7MMJr!{&0e8>XUr@ zIF~+>3g4Y`Yab$U0dVUyFVh3>FX9r?R5PzW@4bWls9^OjusoJQ$Ri)A%vZ43#&drN z(f3MQ_PnO6){{C9rAAf6;Ty78t2&R9B2%>|Rb<$jHn8kE%Bz?P?n;ka{$om_!6&ay ze|jfLmXh&<$oVYFmg#-918XCh4`rhj}9 zCOGjnSvDsuldF{b(X$Sim9Hu@F@uphbCdoyDbGACCvnycok<5h!G9Umj@``2`|mA_ z{v?;A)q1YtadtL`cCTaq^0e1^a@cx>qfjOA{we6SwI;Kk!!n_5ukF3B`F;;0S~V6- zYInh<356`#rDIZDV|xD6QyiwV>O{|9v@QSsnzfeVQBXJz@0^Gvc&JtBK9yAcz*1k1 zR}nfQ)&DNhhB+)sbL1G0{eWcEwB<7Fnj}usXQAl`{&~JXeB$O`ItA6I3ZI~5BOUN_ znoC~60?7Z;AMemG;@)QO9Wl#+eIIEUJVEADa}^b{>wA9nk0+m47*{~7-EORDJ0YrZtkdIME+`)VkAontvoGWbp)Ov_iqm71x%Dv!g-F}L(dWYTm18i*jZ8K{ zgooj6Cjr;l)>x3{*kg-;m(IR)cpc$^bTu5g*|4&__+M)C9ymUo5Tx+g+i%2<@kKkv zI6~X=9tfcpW6a<8i|_!>xbNy^$L#x;FWn-7GI$^Fj+-p1zbKrcAFQ!h&@iL&@#b^# z^cVI@AY$=D4fWH&lzfjJDxeE4lsU4WA4itMe!cnKcFtPR&oyhrf5t|oF%Nc@wkP&~ z=oYO;YeTmZWs%ndJHxGKeZe92Na@YH_uHr9?pc@?|5hZ|I+{eQ;ryHqT@L1w1E(5CqHcaqjpB5TL$ z-eyOYTZ`yCDF&gLd_;URX2|yYCS~g)xJYM|6KYDrn0q3bH-m{jm71@1?*8vmd?Y3r;Pz#01-Y9g3aR z`%pdmQQraj{=aR*0oX=}+w$rJo=<<6C}g+#wg2KLI&sFMJX5L8;}2VyW5M_DzWl>P zAJ}UNH7RsO2FC%kx;vku3)$b-BsB}oebRKMRaC;KmLq+K%e-$9S_353z7}Z7=8nUI zu@7B#HmbTA4oZyyY19{0_o1Ee1S5HuJ{KAN^(no2y@+G2o3UZ1{->_4wq0lv8oH6g z=Yog9%G*uRDoYu{-zor5dKAXkW{<=T_Bdv& z2MyNbW7npWmq*j~Jwv$j=Xi$8@=PEw2Gvh9SJ>dh~C7qW;Hk? zXsWR|Z{>Q`H}o>w33G@U?0fnK++(t&Ytcolu?qGt-~jMJo^|Y>m3v%2qls)&k;a(A z|1!#~I?CX_cY2p(^2r!nTz&Dre_|g&v z8xqW|q7P=dL3hu89FQLp@%DR!%RV$~#n1Dk?;S1}{bgHQQ4vumegBE!LSe%SF|u4Q zHo5^wOGq>Van~Uq`~F9894l>ijO_J)x%&V02^+sn9RmL~48q;~29o7O=Ls#IN#1`l zQfBXA!S;*4Ef2z-Wk`x#2{=$8LB@c8UNG>e?1t|eMeEFWF#U>7%py`9@ zl-r+jp*7gaiX~*}EHsp8(Tg>Tgh+!Q>nOdlVBy+p0=S$aKRdUsUf0{Mx9yRM4RUG_ zkoVQ@i6-#CC7A`4!XbK-=cp+;RN;pd_1n#HwOV9yQ{_09p^7JeVMU081aq9PCN@TP z2gBBMQif^k);zry&T%`Tu!iA~ttg%bMSAO{nWF1gTNzI`KlGrM-N}tAsySl80?=9z zwKI{o|1iCpYz0|+MIdQej@bwY!Q`-Sj7W^MUf7p(NrIjx6m5A`;lniG)fwtjl2pi9 zew=pKsnZ91_2X)3_~O_`J86WS8>ZK^xUm6k+P(~c^0vsTt#xYEq9~7Qez1}K91^IL z`#T0Z_E1^K*_Pg#V(ZU#y9nwa=}<+R93QNAGJ14c6y#EQCgPiJ@!^1$C?27wnM3pI zQ*OIXoG4fTDE@q7_IQirZNcE}%x`Zcnq9M#w?l$hcXT3qyC z%(637*7wm$0NK8?9uITABz@{!C{eo%_Crz`GTxZJQ>RVfHb`fU2^6JCnJIeNMTS~+oc|?{cD6M?$g?+ZubY5#7 zvIE>-YBg53OI_4v7Z>M`x0o{aaHuh=qnK!Y>b>UGprx$UcAzo!)@kWe@XfdsB??pz zZ9Ll^C;C{SMfbMp;*`AA7xpQ%ha06g?*)V|QJlyNfgl&3jF$M*FR`b8Us*)>YxZiQ zBS=zpYN4?HkMsR1D&~9MdK?a@n|vTd^XPN3SSbUn_c2G>P*{oSGP)C;vFSUpzCFR? z0z`>H#MD@uWu3>HC&b3qqyoBd^J(a62fb3es~hM1g^k-hOrbbr9~kza*XH~H%CXsc zp0Ti>IjA&I!Z06iv0^39@zkju*o@N}`b#?H)Ef2cv(c!p^j&64T#jYU~`Qw}6f#CW_J%XQe@ujdnmd?R4};eK08g~$XQ z={;*yZ0is#i8w3Hj?CFT^c%u?wnzI}UU0B15JEncC%2D^;nQo z@Qv9mURgp=&9u1H1!pnlw{uhkufx6R$=Ll5e`shFLQj_+KgBFVSh*h!UdF6nTcsQ@ zR7(qh@+Ec4Tpn7ecOQA8qWth46wP8Aw>`EiUKDzbP^&oX$IPmqXlS;|3#SE;Gvh~o zRLOb(rAf^tQf=0${2peh>bheF*L-8&-rI9&gj%^DqIY^F4zRAi7^5hEaDD$&_VgiO zSnadB5ck|L`ynW!wuxnD#S9vz384p^SegJ%YoJzo>#)NCdewOH04-Z@{dxa=Ef*T~ zYkcQ0gQC4?_wL2=kLL59>nabY*-=(2Io31Ub49G|yw@_(47ossbO7gqwGh(anw=JdGXKtcv6tC~V?pZ#&fQ$PY zO3m~_eQURRe1r!QlHM2Cwj_m#X#W95wR?pU2RUwG>IxO1>)_Nn1&d9utap7aP*`z_ z#)`7G)7dd+YQ3ad=(ZJ3luWX0*fac1 zxg)*yjI73x`7TpxiaOb#Y|XFvPDP_4a`w3MN_&GoWOvPHvczMp#vu*oN@f3vw?A&B z?Eih}@RmO(KovsQoV87U>(Ngz5^HL=1cxviDuT5fopfJ zL3W+T(Unqlr&_e{(>%{TydoY@z^m>t2vGc6Y z6h3-82vpmd$G6u}e%moREP?-S_0GZ+mI!L?!GY<+QEauvSQLahn5{ zb^5TEsU4U#p-kSZqVe*{>N<@WSDp=m*>#kQihm`W$C|VrVLUD#!soov`;K8%t$!-H z+I6~0C6Jz+XXB3Fznk~o@?JVz4AO3_Kh!Fok`*RrFB*-c+OWiv8o%_slT!{(yu{=1 zRSF^o!j9wKP-47F(jN1S6k*xKpgDRZc@9VVFu9Cnjd^QK3(id>n`iOP`BlyAK-$8d z`^eD>kV3M&4Q6U##LYbSlWV0E_buh4#)T}`4aZMkOOIzB2%$zRz7eGv>k?CI_PUfL9g^Q*`2!JDp>3UX#X3{nDQoxp zprpR0iIytN{1fAQ6SV3d3j=z&3Q0qVK zM-{sC-MM<{H__qd-D>V)YnzF&x~GyDHr;Am-UBvS=(jHk@0T6Qs&8`2beMc|m8=uW zfC=X_s#&h4?0d~5+HhV$YEF52lK3ZW75Z|W$U&tg6SMiE;J6OVbam68qPZv@uBR&& zMp@sim)4%MEljEiu*f69QcFJlpHq#W=jG+{qJv(=Kd2|(RCwGnBiotK7#(}<%~Ys;9< zj^pVF`!3Bc`!TJC+c;Vu<&VkXqtCuT&6k*!#S!7o&PI%$fTx& ze9nm9V@+XUAXT7QZMNPo9r*`? z`|4|q?TcKP*H0;h!o-+X9zDi-i)EFXGHTkvPRfsvE4pt#Mi=j3Zbdy*H6Vhi%)R8~ zh_VPNdz$d4G&AxE(NIbBF;)>D4>dlm zv%0Pel#O;_DA+1@u;fKWXhv#yQw>S@r+IAxdEDA=rWF(q-+{R4#<){Jv^7tcBj`@l zEoc{KfAKY%O+GB690g8#j5#MgTwegTp9tG}MjmMGi%?=klf^ch{rKmN`!mTqZkt^y zP{Zz*sO}SJc2+t|iHln?yO4l%`)2Kv9AyHM^*!`+)aLgBxJ0{6+zG_%i6&QvDON_y z6m-*)Xy#V`#?c#b$f6*tg`trb=-7)1gUVCJlN&n)h7FQ!UXkF51NLO695H{?aaO&% zwrB$O0HxI|qB`ZkxTOIMWVl?fxHQCL$i3|Y_hj_S8&9b9OiEMt{M4HgQzXUD~__f-w1CVlP7%5RC zjOf+Q^GcKtw=tD(@Oe(Y3Nm<7oj7D5<1E!Us*a-F4B-?4Hoh9n;3RVVfUz6<1bKly z6+7$pUt3>Nqw6vb|JRrQgCFTWivO>zx1Z+yudTC$Q0*td`5qwQ|KbOnABVN%6@;v* z+zjLY$KH&Sq>|yeQpsZs3QLz~+nHcnRwa@`s}rH#+5(wtpKBLH9a_{caS>=)qN+V<-?@k@9Xi&XSP|^J+L#gD7;(+2K4vP*tpVPM^>}J0d19O)^ zXh7a=#rJ@W|HVzOjHH`k6H55e`|$J`JO01b%X=3yYhqP6-btq+T@v9tt6e;yn8^nj z+k)>IjB|y*{9&Ixx@$K$b5+7S{ZoA3Ea@`J&FBlNim}G3hZP`0+Gyk3){u)=stfcE zRP^W_s#wueu8{Nqb(+5w^(!a^c(EdD6FL1vuy4Fs^?*5vityDMJLB)}|7TxoYut4;_Wwa|KUZxZX`_B1u+vt$zjgk|cjDX#Ko z&Ih=N-MZ^8-q%69qOJAVa7!>xZP+`m%|#|mygM6`Sz%-W3K$NA&*{|K>jLP>K0twwDDwPg#EH{fCYbzq zT1N`GE80e;m}-%yylL4cb3aS%w56XX{YLsIx4Bz0ckW?EiyrXSc3fn@B20Poc> z3wT2UkJDQqz*VR_0U9A%TOhU0n<2HVq+=X;lp8_7>=0l#(S3kZwI-V&)Fd9@kepiD z0OQ@oAtCMCAb@lS-~a!YuDuZKB+Do`5EeviJ$*ol6udkmQOd~uw3 zqf(*nF_#g*1ph2&agM?Ox@-SJI`y8|;v+B5i0hpzmfG)YW`_v+=41|-Q>(7KgCkfD zE6>lV8wh$~p6F_#y+9>`I;gu!NsFVQ0e%Z{4pdzF$;0UH&XHUzza49u<=uNAX=r$= zDHwVzz~kv#@=YLPKwi-=@~&p=9M96z3V$-x_&HsSpf?{rT9%)iAq8RrDJgvmN5&k+ z@1s>@-dM&4h*RBVQZjlq1K?iWHQW(;e~++tS7r_#-V%VhpGXA9r-yyTlJ^U%Ev9DM#t4b}_F-X&DIhQhRvDPtAaU5x*oIQcyVT#WNYh z*g{H@yZCd-j`=bj-Nt)Er}H4C=*Iy$Jnc&zVL$gJYm0HNv6v}WAugrTN^wjo`(v&G6AS;s#r-8Z=K=8;R$(z z%ONoZc!EVCJ`@&mH5A7E>GJrmp9=A2F=R~{CR+yrzX+n)0lekLh=#vMD7^AdAW6OY zlSBg*e+~gB7E86OiW_Sg-9GbtdlI|oj7{{0Z>j&X*R8gZE*_tWSn>48V+jwS+f8@vQBlUD!pD(m2GCN17JhbyU89$<(hx#V9=p$FRTV6y#|c0^tl+?PlDMkS6E4WZ`DR~G*|`s~;UXbk{D z`4>Ilv;@V^fl#Nr)Kh=DpHnq<_|3TBs#pc@nZd+%Qv0T`UG9Hu zSEG&+2^|uU)tQE_VD=QgouIi|OPExgAAM_bmqG6} zj?>fJ4&eoLfx!-I0Hr`SB!~i=8`-|*{=#B5Jz)TX+QHy7JgpQDdb*1PBpRWq_Jp-J zfVDE(Q2co7t&lo?9By@_x+5X3jeWJX8YPW6#t8WQ;Eh`-4B)a*m^7xtudCPmxYk3l zQ9TW`!$O@FBF-P+Uy)*p(-1+e;z0}0+if5_-fr+-ul(@PI0A}QSX+3}-crTRJV$w~ zY8w!EXvTy_xTwVNo=BF6zoqTwRY@iuIsJYiuoq(&3+rUL?vK7w0=J>1co;UT>ee{P z!?3p~Up=*m)dQ>0y@1Ok;E;~GXHq1azOaW|p51bB!}n&4fv6)(II!|Km8Q=)5?5ow z00917GwHa^vlPkD2KSy6VTa~zsNkiimJy8grDN;IOY1xY@29}61xd}lP%i8RNq$nD z2mLl0emnN5?DLB4;d|&N#e-geS4v)M?Bk1T2bzL#8n88|7M?ZG%0+K1+m<=YD!q`h zqn&-b8D#!>X&*3y9ayrEA@rxfYcUacC!n4G`n4^;+lOD9Q*F+saW z!vT6)q6I_mR0SzYw0!+}#m)h7g35&A_8PvqrPNpSFF6&#d6uBBD5ORJ=PIqgoOx$P zv&(#M)safC)^2sU)qtyPE+Z$tUCJ`iLufJ9WQ{z1`E`AqOnUwYlh280k{RA&N z#=QlFfb3oe2OD64Ad`@~8QGy#Xe)TNq;C2sXjr=-tN;rCCBq(q7X>7kPQ1%vqnfVr zLuME=0YYp4>U98>IXTWImLLjqf#XfOtMiU)g$n=;^mAq-gO4xQXDHTD99~@Rvk-;w zZb4D(1-qkOLJTUQRw63o?R7r#kkecX?)9>> zuxf2vh878S9~b^iMyt5%G`83O0RkZ>H~&=5hwIixVN6u%X0hb$3_>r3kh(qxi|e2# zHCc$pn(8}p@{&Y3{=|B*m%fz)MdZfp*wqW;&AocxN|7%&y}o;)YDEe&dP#nG0$39# zD->GNqzg;Y^W)U~fW}QUovxND-M)rW&shY2 z#^?`uWj~@AqUg+|jB=RhIJ*b{fOO$JWRIuMiB3S^3l8b!)ONpl0wXDy2v z$)`)hpOCZ;bk|H(AdxvToJy952`NPw0mG6kY)}l zp$vtELBgsIg}dxTb3l#xY@bm#B?<(QM#b)$cB65DA=RASR%D^0R1%G`Epx4?s6>;D zK7yzwANK2c2WxKeVDwBjVAXchQQ;w4eAQ*ZWp7Zx6SAs)yhcTT^hnGio!LD<%%BAaqV&^e8k&$SGZZu znxRVW9bDNbbAf^*SqfwFpI7Onj=VAZr5(FK-ARP7ANEbM<^#C`q;74O2KN*^t3IA1 zh`M)Gf%*PzKmIpSh{1LyDiMhGqAy3Z=lYTNJ2N%lbJx7C;~5s?EAiSWhMK>lNlKoF zPRW~*B-s)w#j2S(s)acRyWtt05v2fHGC|y-M?4S-u0J7c0~TBv9d)8Idr?h^6)e4# z@m`@g(a$>jB|g~zNqK=FMhYXsSo2um8x5?vO8<87TS;u2MN!T1N`^DOr7E~x&HYh9 zCAnpi_o>K{0YA-KCNz8=>u&e>Q{$NT0qb#%K}91YI~(?6YjC#op2__RS& zTYo75eF4irdAZtNCS2&ONla(00wLZFqO}*K2dsk?nr)p68z?Ip%|c|@bCxN^;5zb{ z|3B988TMFvI^=6IzA(5iX_3|*cStT5Hi?c<^X3&}9`CR7(2zbN&PI391dewp+|jUs z^^I7c=ylinaO9MGH>>*Y*cKGP2;4eYZS5!Gl2oFsj2h*d%Bbmd+yi zX@JmqVfKRw7EYK_FTXqX4KQgaK1qC-w=*dbb)a%W3STzpH%al3lKUfBWH@BE$pQhf`^$AS3`*&n>rNh)PS8F+ln&Jq+}Hz;X4Wm+g?!D zRCbLHuoI_d#&L#+GAUL6OXvEZJDEc~zi3gT3oFt8yLUa4L83i0oP%(f1JKxr1T*s9 zMs5#)>SjsioEYMgr%AdJJ;FVVNZ`2}$MMjg=pg)6ATbw}TYb~Epn}<6+}`oI%^=tmmo1l^4fPgOYEA0_aNN`MKpd5T$0Fxm`b?mRvY%kag^5LCVoX4XEk91H zzP6i_Fbo58;`l9oK(c`xbLg{J#Y#ck8zhnb@d=d}_mK$N${p(O16o62FT+W+Y$!jc z7}=3RqCw><9xI6Jf0+)mqEn3eC}1In`XcVgzlpl@XqM5CnDyyPqG<~XFMx{?t_Rqj zi@1TDBTv(-A1ZwOQ4pt`d0UK)xVnM`P~J@%9Qp!!I2##N;%+1mq$bSgGPg({MUz-J zDEM}E_A>J;ZU_Bi#2*4U^FL<= zL{$sJpRQAi_|-*C3Ij%rU!Q9{9Nl)kqI?1M#&L$X;|F}9N2VuW+1A*LaecYVvGa&(KX#0&T0;L)!N;PvL0mB zMszkMqO#mm>T&fm!>rd6mT#7=V;w3f_tRIe&mQ5Lk&z%OnCb9qd)8N9=TUB4J!o;$ zyT!hu86SoC(w`bMl`T|A5fHVzvFcZ{0@GnQ2-AxH(nJ%`*Rfdn@;z(Wv9bf*<(tnj z?w010XZWN)NXhgVLQ4)N9&G^Z z(?XXO6vf(C_%}$?`~k{0CMWV_817M`#p+250p20H{AxE0xQF`tkw$ATV`~ozL{xk<0~Ok0!dYq?+>is#1~Yu$nFkU zcuHAw%v5eh`t_2GW-B>c0QvI?@M(Y`CR6;}KH*9p`qKS$W(rr3EM2Ac(u&cZ!tZ59 zg((X_H|o^D!HD<~#zJCr7zxiSDTs=)>b!N7FIWMhszMij==H{DETW>dKRaw{Dwk*` ze2yxER#6Kt_!^08T`5ki^YE=ofg28~34K~PhnLqUR{8c_BvCz}8C-u5N;C~6A}IW8 zxB3!mEGnj?pEez!N7(V>@Rwh>@lSO7$>M$GmxpgV!*dI86K@Op%>=%u72@s!zQ*V> zU^X!Xntav!KYe^k)ByM0P5C_*^-7xghRgQOz?QqzJqZ!`nR;hvhU10}KO)f#&%|09 z5T{6Z|4YhsYD>WR_wBPbe<60+Nj|}}YUwZZ+FzF#_2S^MrHyJp$5Rqb`Qk#gfZ8Lw#RjRdpa=M;uS=}u zEZ@hj)fSX!R=fRcHuk)OKzCIz!OTqMyT{!`yE%u(-QSjd6OW~zP~teIqg(1Iu|3B( zS*7{8m(pP(v68dZw3aWf!)FD~8ABJR?k+DF3(-nY-SEzZk=Un_)f2j9!JBuk>r}}N zsr6g0+`fTC)?;uIM;PCvR0!5cH8;c?@=d?`<#^TwiVdCCFM%&DV}B@O7Y*ffndP~e zYcamN5Q^l_;e@e$m7i9eV{N1hePf|v8zKSrrR*19n?GXW`?4jIkm9-(AF6q z*jJOreu9Sk$#jh%f4noaXh7pRN{+&me7nQmzt;%FkP@tGB(rf^LJDYd0EOiVFxJJX7mcm2SF>vbO3 zOpiA{5hU#7f_)mw9Y`aojv}%2S3Xp?%>Lxg(B>+~X1`wy?!^nB^@y6AS08r7>=VqV&Ct?`>>9f~v~ync4XZv6d$dKQbiS1fbA* z&?F2(fm(KBLDfv}-3+aoqPcY6L0#kN{vH9}M8EG@iDbf5;a!3iS-;#y2i`EFJktLZ z6#EAdP%B2#d{0LD)%U~>)#{s**#z>OxBMZ~jfmD9a;LukOO*UjDeI#eN`bcQ_Gnk= zCnwgOu+K$7oo7m}69eqsOIGZIU2{>fIt6)WG@{Kk@5`+KIe(6Ng}I;ug>sbSn~J>d zc-j$Oy*dvhR_u?&ozW|xR5aZu-*jne{;@vG$$;Du%c)y&l5CxAb(Ca{ZAoR;&dRzl z)^yC;_28L&I4#aL>#D2_E&-2L?QnC*=!e6$)L^d#7g6D5_G{C|s#Ce`ui=Ejwmoh( ztv4IN1)+Mhd3O4ZF5m8oi8bwApxilWLS@7ms=nC|(`M8kA>5(3l51cbRm0I71bV81 zo6XGH$P+rE>E`}}t^JO8sWq|_lpq`Xx;f&(`?Sa(5fN*xR$*GZ+I`X3F67&j9N*4g zr^YL$UsHJxFS6ETT70=Q)5fpF z*Kw)S4VyKmT|k|Ocdr}9t}-t9EIc$}w745ztBD@zojaC|yC;+Cba2F|t%WfL5WzD}tyl z9=lVQw}IOQqe48>2RGxa2bSY2HKm3EFLfcwilzC5k92eLSli^v27k?xX=J z8u+k=7P@vg58-|ks986ZOjgz`l0FWste*8@j7Z10cCu~KMAPINePgxBKVjTnI>)U8 z*8`wW;^h}5R;b*|BrVy6v;=}7@)rJjiXBFj5KOf%gqOzxt)=we@XPbf4;^;RTopmuH@J*wLYlSc=)vL<1%tAxo=8z|AcZ&vq1mnQ38 z@c37=?pfzvN<1y7nq2dww7Ecq>30n#O_?rt#=KjzDzqsxP3`YK zxmj!7+hr-f1bWS1)=@Um6dk|v%TF=t<&WQyl)I*rJy4mG1MI5wzP%wU+;?hB9~wZO z{?sJNN*JseWIvg;)=uCD`s+i@ zP&NajriFc{I+dz8(C*aTTllqy6aZK`sFifRO{Dcb*+?(=*!NAooOt+aPeOoh4 zsz@(P@A0aH}jsY=)%c0M0ZUZ%f%TdDeHT!8MV-VVp=V{ z^jsqpJ3B3;HhUM!Vs2C7vZb2#eDP;S7)nay5vqe_XWIAt5JkSf3^k5D{jmf6>;_fl zQ@>TFhsHq|y$7Q?s}${kWt6NeGz-Z#x+mmsCYURwjXE1rg?30X(>G3c0CyDVtRb2- zPhQ)pJn@rRytQJcs^Iq1R|L3crTo3UQbOgmqoKU5b@8q>JJf7(=bDVi;VKiKOvem@ zGZ6-Ecg4?Nh(dQC+e#_Z88=r-zt&|vsT5w6HfL7WZrZ3v+5KKsKE_3faUpmMD$}}- zQt^{Hz&9D>#gQZc%TNGE$!QDxM?@UA1(R+d`C;ze^=i5Oe9HBIPuprc$R2a_yCt(nA;Xy7=lapehF z)R-{MHO!qYT^l%Au*ug|i==_5~>kP;7hVd`x=+;=W7~=eFK(SP# zogBh)wi|Ndw}QCBN7efQ1?m;)ZD!y^^pp-BDZo8e;1=spn{iVCCc;x1AMs47wIy&o#+cF zlw4xaBT*h|Td}P;cGKnTz-K`hJqLrXddea#z=0;Xbq+QT`Ut!8?Du!`gS1-#)E_`K zWcnsf;jQ4}6?YxyHM2kEcOcxvZ$ti|6hB^VTK00y$X5EN3?IPBHdBCy_siy&v!5ZQYK{M?)uVU zO5p9;o!WI2^%u0$!JQe4p0&`80tvY6b63EvBml2jtn?XlytvPPc|4(5sH@;Ivifu= zBaxSRcB7;LPUfMvQrfVZ&)~8IRd5BQuUL0SyQv*P)ukk7LJiyr7MT=KfYMnj7;a}1 zxJ{4~fFJ0s>P;vHW#SiGiBOZ%M*`reZ;GX9uCtR<0ooz*eB25RxELR_2|Y#9x?`83 zWUlR&$X9J|J3`O@*{p=Q^<2B7D zjbZJLJWR+5AU@_s3l%7}U0>1Al7M8lO00dudp&?C;eOu5Iy#g|aDyDCIv$-MK}-XG zPG~O;v6apz(Ng>%8&|$!5tq>*0|4Lm2 zhFf>ZuQ__ZJd~*8F2JeRfZI!ZxJUN2n_ul7PENjQ<5ds(>Owd$5^|={fEZwOX8wKB zHWHN08zS;HeM-LjFq8Xo0)Fu9(kZ%dh6d&_Tq}-;$((?A?^(Wtv-N}z2GKzc&6;O} zx;4|Qow_#ZqBAF@>tDYN@?glM z9;U+Ucv=Q`^Iil%S% ziAX!l(X~MnEs*frr$yoBR=dEp3YZ#ru|mjP7*Xj<`XSIkaDC-J0&kf(^+#Y9F~3ipb)O$MY*t}7An#G_c%E)P@4xOe;NSB_gW}Ah`QX9Ry_w%M z!~f`tkHkOwQZ9|?FCL#g5bsbtDx@SFWCI8(G$=XZ2&%QJ71%+ z=ZYxTSjU0yht$@phh(sS3lWKSq9SIFI5;@uhMw?m#6tUe78!56E;z$Z@e97^)^PpTJWRe25kZu|EZbu2u9AY4#@%V}RU@Za z!}VUvT-T_B_Y2v_?Xj!Dy9N<`@f?Y9{eqGPJ?#b)G&I;N*oVB|>G`>~sId+>k=1P8{g=6lA*za_*4y;xtYZ*aF{a4bkZzOvFGbX{^R}7& zCbElBj2{0mq9ZcHP;l!SE*w-zVvp?QNYguohe>aQc;7k^2JYAG5~8U=)dJg?hV5D@?sxQxnw(pnTbwZTnrO@aE3#Cf7TFb}(^i#%&$|B3H(R1d;SZBSucl*4 zlI(M5bGk$(wnNKh#>m$3S%`7#_qg18uv{fK!r($t~`?=B)^d1 zUN5<{WC!%K`v+xDM|K?NbKYd=06nb#C`F_z&mR6BT(MWDGz&Mc127vA`b}(CyM+r( z%hEsPlja?~47$YfQL4y&!j_bJv}N8W8~*11=vCuEdVZvRytb1(>w|uLc=y+O?{_(* z&R$Um4WCn0tueG%)rt@Hw+58IANiJbMNmdLdNH)m>7jcdfsnJ!j7D@n$Gx!+u4VFG z!*1R%kdbHmDCPAlg{z)LOI2^4h5N=sV{yZgPaa4MI6&=sQuS=FGe}P))C)~yk@S{p zYT9ez361Z>8(^LRgA7r#cb~r3$GEwsD4%^$6|`LTOyzidRSwxirIOsbqJ*8h0xC9; zTcn+}$r?*WYuB~k*VGKR>Ac~*%7gQ=kdy$A`Qa!-@FI`>m<%60O#TS#d-iMoLe%ml zP-QN&hS~Z9^qeT~ce8YIkdi*NZ%Jy+rF7^+QBBd{lwN3&{P1#78rjXvciX3x@CPqX zEr0*YAji0BfikJki22||(KCB&3LLi6VUR4{DYFl}c;x6exq=q8$_cjv!}f;fgR6$u z^v@%S&shFK_7mO*Z5aJ-uMpR}9G$a>g54D+F}A+4`DmA>PGeU)a7}Wb#>AOC_`Nc6 zYr^0}S(FtTX%U+P)H|e307vUkTDJe83+i_@S7?F#KkA{!OPG;5xa*v1wSu%;nJg$w zd@GHe4J-k#N-?(WB^W_1Id3q@t669$OLOQj#ftT4_SaZWq?@l@OVl{O)Npq*F7tM+8y2||aoT%i`Uaw+(K8k{y@V=W;g`Q9Dt3c5D);lhOQf77-v1;VST%LH3 zWN%hc3n629VRGoHS{|V->5SI0-J500+|a^`to-@+b7o4-A^=7J&)yE1tBBHTiu68L z-zBD5fE!Cl-b!>z2p*9U#whUBpIdwH4zrU#hk0WOt?SP#xR+PBccj1V*xl^GAF)Ai z#~vsnJ~Z#z7id7$fef3qyN1mbuH0%a;7Ur2pBa++FuclnD{duiYOM%m7V!r*HA_la=%O~ag|lT#J* zWw{nseatcuyx)b)Pf30vdF1A`E+_EjmE^g`k6)guG{3_@562CrSD`{@*YtzC;iBvE zXpi|Q=xLdIlG1qJn6sU}-45anm6gb;Vo`^_r^TwS(UZ@%3!@68HD?UYZ|TJuvgh&2RX1+%l4ZXvvp>-1(k63QW$uf zie>1KU9``2hj5bL%4>OL`uXqmcsm>OK6;Entn?HM1Sqe8Oh&7fHLSGC9;=a!tVWCL zWRn~6)M6#wGPa_yrv+}n%{$>9cNFP^Y>m#aVWDm3m!!ena)`A5W@?yxhmsGET^!oA zu>5u2N<8G~GJE=|YHt26-SL-^NRzZ6Px3&SbB66As>Cr*a{z_NB*Un=*4?FB2z|{D zj`V95eyf~Z`BS^c@!9rj1vd$U} zcz&j-Ag_yr-nEzF6Gao&dIa2L9X%DMFAKPD$m(Ls-^j9jpjCH^k z01QbZ)`)T^_RQ8u7_?F@9r!@2NDvPOb&AlB)Rv*%uS}t2E78)zJ8!T6yQ6?6-nwZ~ znYRONmApM-;2n;lKWM^-NF>ltfms1GMJ4>RK+B!u@vw;_C9o!wvhJx-dv=Y zXVolxY)veD94W%xVZ6=SJNh;FT6mZBxd#xRyC6NicjkQAIC{2{ z7onL74yD8PjKlC5>`&CHgp%z&E+4?PtSXNQ%V<-EYDi_~;`1mkxC#sUyEHudvS5P#bSLj%jZc zGabfYBmDF$0@mL4W(&M&I51CQ$f{y*e<1m6Ee2a+ht`QeUF(xQ&r(*B?eJh{JX{o+?j zOSH7~#q5LDwY1>g^uXaj%#GrM)+}7Vnc35v8%Kpv!zE3tA;rsAh3=m1wee;SSAvqx zBlXTaeuN~~ zoJR&jS_LCl+J(BkJwAkO5+MKq%y(}C^blQe8{TcGc09T$f5&S!L?y#}dR2Ahr1MpA z&9@EE;h9^KV4Nu*U=$v{?y9e;q|mZh{b?1>3URz#G`h~!9VJ^;wY0kTai}~|EDVwU zbEIkTt`!fr-trpvU79lEpYMyN8f6fN3m|;^6(smzvR2fy#7VE31 ze;MmjMzD|aKD5;_wU2&WQ(LksYp^)^xMuwAZMyZ(>d6IbH0!BxS6n`E!jQ8D@1?RH z=?hQKSk;3s=_t0D4jS>)=&LFt;d)&5`YCgS-1uj8t&H=?e&TgOE#6+7~g4G=sNTif3~G2|I9^@Xn`ma^A|0uE5FTSkz}VRCSmdk z57Ub)BhTllSr1};>EW|uhG*japdEkN=y4gEf$Y*2SF?5}U%0Kh&b7xz*^l(B^Z3pc zWm{&7)ai#sMbPzkmX{qPe9=**)E^GJaCqTtvliBDc9NoCP#9bhD402T4dNxj8U6$rX$C_$h8D^?)bTOrj?$&)@SMM+l&5DFbF2wQI6^XoXH3f(CY*HL&zO`OT zU&sr%8=BH{b0PD=te5t|`UNXRIHc-FOe8XJ_|{c#P5xnmxzO&6M>HO+xtA_hj1I=T zIp`#i|L{?y@j(BnQ>SxpWe-BS?mU1Wd-Wk6b58P=>ndV|SXlE&VhGk?!>}ih4WcRu zq>>ane4dB!-zBnki)9mT-fnsDtnJiEZP?wb=*Oo{7&9>|n7H_Z8B(vXfi@oB+Rx0B z>rS2caB$P#>Fq@O_DZf!+zrG!Ztnq^UU2uSAJa~Al3HWkJ_nr5aFN~<>t#)dMoNFc zw_!8X2dse)s}@IbXcbu~ZGJu`+%c{keEGz9lysr<&EW-n-0qT?fTgNr!c4+Dw3_9G zL%GTdM0`rHTf`XjoIASqXX~s&;Hp_j%%RW{IoM%tkNh@aI=RxgaX7EAT~i{--Ol^4 zbi?9-*jU<%IRPedp7{L^`Mb&{42|uOeDQ4Edcxh&2$$T#jz(nNNelQ=b$2L0d^rnQ zThf-JW+>4~WUJWVmvf|+s!^Qxuqee}k^h;>0PYoBk%QPT zcle0Di3EQCH1|@&nZ-=v{D!jHX8fVcodgqt-ximkpqcZY80Uqe$15}opT3#1{rO>+ z78+N~UBm#%>E%UiZ>LhQ)?k=iYv-J#n@--3m67*~lzNecvn|hmMgTXO%jN7mUzU@) z{IhL-Oj|49`jBJPf{U1djo+8Wl!_U0G=e2Yq&>ET7pbmG_fD9vdD4%GFIY#iJ*2Xo z4K8MmyL3~k4?40>Rmdn+a%|_uABQ53_eg9WDrKk$Yv50oT77WsosxM3Amp{<}~l!aPa6vM#E2tWCmkQM zZfO}D*BeMdT>DXB%6WIp-zE1nb{A(>mc&}~HL)=Fmb9-`vGDx1BXqBz5&fZ2y{-`{ z-J;O$78Z6eLpu~I+yRIbDXiH-9lXou(fJvW&dk99ap1t$2ySlwL>on2@)_-PN2$xt zL=9B(e$vE?YR;-Hy@tDt)z1B0CRL=o0PT2TlfXmDd{)7mP{|_RlzV>AjWw09dKb>P z4hqAypJ>pf9LLcibSdAcq*!1v49-28ru}bhq(=Yj>tsF#$${$3}|}hv_$OX{PoN z-Q}^!gBjt3^@|k;8{CvHW?MdRTe-OIVu)S3qquu9?^qq%;%>BaEP(*0*rv}rNB+`$ zQ!XxTp@kKQ$NBdkerb*sl8HBQpXLB=C?Es4=A)kGVsN zMTF#bM;IfkMSbr=ze>4?Z^FWisxr?Ea%vKwaIO!W`W?D#`dZo4(wLhse>G!Nq~uj-*JBD6@|5W z@*kTCY5%VkJ>_4mRDU?b6_s0!dzASi7a8r=Y=Q@7}+qKr}W3=)FfG~e<3iG?Q$ItMtW?hcn7gEl|&)Urd z2wQE&dui-t*FRwyY)<6Q@fq@zi=H3(S>mTOb9Lc36Gp*=8U7t{LC#`Huem z#T%oZ=|565&RUQMclHN+P2eY1Nr-OL{8Q9gMSlzYgar*l3_pmP;8Q3HV_8#*SRw`L zljMs`_o~^(8+0#mUTem8r{y%_%S^36;~&g)<^!rCS+G*h%`uC9=Kw96B1YrGei*AP zuAj4Sszh4gbL9f7m#RMEZD2juqgNk9+0@#NhT9Fg<@vabNGZ!-sy|E3du2E1l<)5s(5hx5fdhe_38XOx8Kj|Y?##@r zu5Vw6O%js{XjU4c>92^Xdn!x9wDHZWlVRZ@?u*RNvr3rMCtG7vs4dbF! zU^u_OCFJYlwTWoRO{iT>Q5|IWLfev#zs(@Xf5Q1^g6X=EUd4EBpc_`pB1b7;D>oL) zq*$GzWyMR2L&_Fr6~uTB)g=X}dSg{E^O`uiSYQ|eaYWZ>`uM>qw6*shD0v7lVb7Rf zr!qUxO*tahI!z5x14Ka`OKHGOhp3_ zwjOElJ@l?6kFSNU%j$UZK?g$5NxdkOGI-9&!?Eg+sO!Tmh1XK-#Z%ldLJsWZ-*h@> z>dfYe7Vtofvu9%hzfV>~=PskePa_vkh|8AWwdxv7$D4!;4VntFCSi$%$Rr5=#lSiH zL0MIlEq2v0dDzQRgfKa8haTxJ`AR8UdjBqQ3AW~YXko6>s@u-&Bc?RU06D{3_MgE{ zE&cJ}v>NI2Nb&O2yWN10+i#q`!Nkv00*7NkuH9%?aLIGDq1Ge-EAZ4W9}khsXQfxK zRpbQHb=x*{0zs&?4B}iKWh<(#dazCFuIO!9I8pnYm4R@c{(uoV?mc|*CE1*^JVyzz z9RODCn8NjsA1-FxK0E)k>TN9HBg?ccUwe}5)WB==S{=F6I9RV_0UPxQp}U(6+r?E* ze6UwN_OrAVmWTfNqlW30MU;1F6Oze2ZRQ1oc`S~=(XS?ZJJuW75X~*G@)VyO8fJ2n zH6bp-9dvB!aK*SXG$jVUrV~9VB(^p%vhEh8T4Qgsps!X^8el!7e!T&zJj0uDgc16! zg>zQ**JLVNAN;CjJb%hweGUx>yh)EijJjgIVY*ZRUfjndd=Z`|7~tOXXQi0h@Ep$U zbG6ewSU1kq{qwST8zHZq=~AJKB>LvzRzl2yRGVE3B?02hgVX*CoE4so36 z)m`jNm!m}=5oM-<>o=nxD%7GX@N53POsl|=9IGhXTKZ7ycQhS4GPldRHjog|x=fFV zvDzq!8julf&U{B8d?|75ca)1X0N+psCMrHb+wEPRY)ya->fL~ShuXB(o{VVwv1ZW+ zEo95{a$;W5zqy(Tkt=3>=Z#WM_d!pDvnrL&S$Tct)T1ir7h%u1`HEYbGe5~GC3POH zOF@o~6a^N{p^&xp^(sCEw8byWbJGE~AfNvqcj$HO&_aytH(eeQ<6>Kgk79JA2RohU zDN2@ZMR`I+E@lj?4I&6bkrZU_s<+F;27M+J)luo&%?VP__>XIZdzaMPi`O29$G`(> zG;QJ(6B>wzvNowG>}jIOc^SWHM1`;F_9xg-2Zkboo ztY?+6n4S>c1=^j!pVz&yCOAA5EW|8#Lwy_!U{s*@2N@Y#JnU~wRQ&8piw z7I=6Sn>eK#4Mg|;2(DCgqv9R*GUNPHJa1>#lU2#2IMH)Tf+Jx+5>~MwKba1Jf!@?ie?36~}elj1sp7^btTD{oU|ppgS&fp^JDixHYFuhk7DD~QRpS|0>Ss-YG&2G8M8;)P5Ts$`1)5I^`hi_z3 zAkqQ63;2g4Iehd)weN!6PiKfGNB_o3TLgaR(L+KAX6W15MJ|E1I6r1zNYqKOaCv@3 zn>ydM37J@P^0YE?G%7UBIV#Gk*3P7P`LC6Lc(0}-4EKZ`XoKgPnw4e%f%$aE^8U_d zP#TiMuUlBc`_^@7<((@D9AcNU=etdM%uUV()bgs+Fnvr&#(%}8pBn}Zgq1T$QI{4B z?u?iQrZIDY3o0iU>qx`XYG;FYy4)(5f5l+ZuluifOhQE{}oc`5O(r!Ro9On|!}9)U>ruYHM+S9gkNq7e2h zz_98p9x9pnVtp8p@J&k0wj1U?gupK^p8TdrjsK?j81YDte{j0`h#^Q2xJiO7se-fD zp=Wrq20E?B4Ft09VE-y-s0nY z?&3!0kd%#MAaC4;CZ}}+s||Mr`9>1n4jl-(ZCsRRaJ{g?;6`D6)D6I6VV?ucx^7Z) z)Z}+JK)nm`dsTv~Pa=~Pm@~~$FEo{S{^U4?u@eLxvNUj!?Lk1k7yKaDQ_PPm3j!de zlH1CkK|_B8C664ho_3G9`z!>-KJfrc-T#MG0f9^&1V)X$vAje|6y(_6b@j*QIosd4PCuOz zp)sZsXn#+MNP{Y*jq~sM;NsDO46Pdg*v0Xx%Ts^#kmLVY$KSv@5-eWdRiNq>rqxOg z_C18)Y7!3g-+hLAe$Pp3uL%IQyup8EdDc*FKmyG7>` z$ChM4m^;X{>bg^9x|DoZy=lLIdWZ9^qqA3bG_5?zrb!xFN@`ctPVGR~wmaW$6ad-{ z#;EllkDY(-6P2jIw7xQB7G2vtZojLr|FgeY~ z7WyQ5`BeSr^;!Ve3?-RM(%}+mukEp_y@4HTaYJ_RIJO5hZ^C(WkjcH@VX33R_a1BQ z0SX{t6G#!SFkg8PDR1hir`YqX{6&m*75&D+tIK2an(H#S6Hyj)ply(J>ab%`*k7LBFKC&~ZcZ!}e8UR|^!A?gAy8f6F z&wHL~VGYH30o^m$dm9dpQy~|EY}ak~v){mB_{TGjrk_oxz)<1{@_-G{O(X+)fXoDnWvR|cC-H{y!F2k45dFvSz{6tZY5^ld9 zf3|JiiB0a|XHUKy!nhfl%dEPbpM&<%RSj0!l;VUOQ(Y32UUu*S>Kgb(2K}xLu+1n< z*-BaPi`t=-KZzZJjGkCecHQIX(XF-;Fl0|7%&KKeWV>Icwsd6#DHgQ}<(UQz)3GZb~t1Pq|R)WZ-P=P@bUM`lV^I3G~7gMt1irn253`ehX5vS zZoPVwG_-$9-U7#UP(Dsq=7HypCF-uH&c}`=rvUiRw8O7<{9}qt*~pRnMv$}+_nT)iL^Q@PGf;ko zm>1A3s;Ozf)}-Dh2%V#e#jpmN{0Bm~&K&*VNc#sucx8PimyJyVImv8gtfk=dK=tnB z+a)j)eS6{sRSX&WqTpMdPm!E|hU33}>XnQ~>Pz{QVU|+#E{-iOKqKqrW>znwW+Re6 z&0D&e2=Fm5qjwre`SfB4_!lzInRp-oOAuza`16CDKNi&9D-O#2NGf9MbNbga zaQBqN917f})019nS9B9p@573s>Xm%%Eh6Ko)`^G#p^e+Es;+Fk9o^E~*bK#mB%1kP zNQv@(2$$nXF|vcTP+kxcS9DnkQ%tj#$Q$(=c|)G>c7F%l@Y^H*`|#p90rkJF57J#0 z1xwJ^f(NbNfCqmL-4sm2?Yw{U-TB7=_5lAT`YE}LEhjf983y(>0e3IrMq6gGuPy4Y z!9>*`tu*`o1t?AKB_Te$GSHfRX_2O?gAaxcRqL#N z=A)~}V|)JhNsOLbf-y7HapgDUPs-Q#x|DwzcwGPKn4}~j<@IU$(8r?ra{`Hgxc1}2 zrlsxOw6s0cGFZhtQe?wD+L+~@sLR@$8|15-`S7b&ueP)w(c?Py>d7|uX!1$&r_q&u zwy|q$89M_*WIM1w2He?~SV{J3FUG9sqAh=pF#t^7{Jym!s3E&OQoU*YTQ>{|M>wuk z=WwW4an?c3M(boa(j+AzJqJ+RZ2UcwH_=_8U?l{msReVC2nS|iJRXt!IX3yf$09%? z8Fp^Lb-)h+E$JVQ)_>EIIG&z}RJlig#;IC%JI)~F(!D%vl?1L(m&!6ECHM6p$FeA4qjM^4z zYLA5;343Lis)8IOq^r2hLp<^Z*5yZulsmhT_g=pm`52$u%bx|EJ$EkI>)F~_WO_?a z0Gh3UQxjWcC;4j%(aBs{eqUQVg-)MygZQ|FOeC23PT$=-z8x@$(&$^*q0dMAxsimO zZz_5<+h1_6pR~`o@6aB4`ko#Jclz^A4vk)&Sa#*PGEdNjT;_cwWoE9!l#y_vaxG54 zu1YOG?Hs$!D@(uHJca8diuQ50NFgjE*W3Fd5b_*tTo@GDtsY7|=Kokyf#!^Y;$bi&w zm#hgd=K5=l+)lPp=>EOc-?L!lSYA3q6${(l?e;jH@2`c-7N-+mb>*k|clTNk^Xt?Fljrk<<8hjMH3OCfn z?sf*xa8Ux43?Z!8-Mwv{vS#H{NQ#P(B~=({$sVbGV1C8q-S_+9o zeN!=g`mGQ35&ay(V*1|wV8)rq|JgEP!Y#xrF}i$Njq;&vQn@z`QsYu@{@TLx18*pu zuxNyx1mRxrLWRHn^TO3$tNnbFrD?>f;K#!*_*PfNiN}*J!^3|mBvNUq`arT^MFT|bF!W$y zW=rX-|EwHcfN(=Wm67+=(7u zhf7xfRLu@8ojYHev>SIEKvi~Or{D7qYlZ8tbbVu>R_VspL+m79pom+)6(OOyM({%5 zuiq9-P*OE0?eDecMi&eY*1bf&TZb>ivU99~asOg!bp?V$u}Z)JzLavJAlJn;)5z(t zOUwbrKrjVjd>knXrh86cLtQ_9*%10VKVo5;D&xUF=y4mgGBQ8c3~Aeq2-lUqg+%c; z!huf(ZlmTG7LBR=t)XZgZkfl|lDIQPvG=cYJl$=(5ZL(Xw8VAzcF!$YegV&bEQc8h zcw|L-nsYZ0b;RfKScTxUj{+JhFUW|wvrqPazf^UN@PmOGcKPmbVU~Pm7L`!$KL4^^ ztA7bvvg)mbhOU(44|no6^(AznzEop77%0H`*!rGd0Kr-Gbv^`46-^|^>4&Avtxkmm z%zZ95FSa17WDedc@WM@wQ|n~hbShZG5ErqHgM50}f?R@jKO*mmwVFyh?+nO3qWhJ-_s&^eXS;?6$>Sq-qr?6+Vojzq zDZd8G7G^DIBQba!>247g+R8_@&=c&+bKa3#!x!x;IPkHdql1tdrKltM3n_qkh?MDjzwhOT!Wo9XrwXMoT-lCa- zitrMZn(4q=Dtljyed2AN=2BUT^tU1c4|%rHnJUg6ce@Y`dg+*#?E*Zw`Kg;lG|25N z|Jktk^Q9MN?|?TH6nThsrX?1>m8~AB$cMOnnicw7apc)gBmnFDSN}2J7Fd8~xb)n( z^PQ%C>m6u6Pn>>&X@5E);G2c-jP+!7NTLLXTrmCGgYPoxT(j38zz^anYP(BW+khA8)rW?jD9<*Yjj2-R5M|ky#e`; z!7>en{$72!aYJ}U6|wSc>{*n2#EmiGjw5uM+%?w#>%NMPYEzRU=YEb75&tC*5^M~V zr*_s@-d%ACyf8ptshm~4^FZV2@WZMV2+>>qmrLIAL@%uKOdob|AAf3d$}@N8isQ^( z-$xs*sna5T_eWi~Qy9Ak7v;(yWd%6djf5gPh>51>b`_LkJuuKCUbFi!P6GzYX++%$ zsQ9!JJJ9kU3$b|`l0>mtHwa_(z6&=UZKx7tP;C6ALeuT`H~Zj|e6^6Vy|PncO@QU6 z!0FfRGS%+WzhlwLZDnzTN6ydHN5aNBT|bN=eswsTs#A5H+^Q=ay_?HL zCvr@Cs;T%7MvNShcQCgnI*0Je;D?Id=kjy?D;|5FIB5^c{9A~4ep?smg@le5Jnt@% zuz9ZfOu1;6=B$Y2LRsa%26HZe5-68RM1j%2dQQ_X&LDT8RA8{eCT?mX5kM9Q4c?NH zmlhvb<8yCZ8_KHo37Z?KAGF>n-d(gRRySyUmF(Fn{%;#yoKTy=WRx`&$)$}P&Mk1Ly5b3x>y5A4rG()}>7v9}H_%9g9OGs&KXkV>)3c?eG|5+r(J>wERpaU))} zH*;wR7#CUWU;|iK^=(dy>8JaT7MafiB4mP&XMP{|K*!8fL82q_OLdp~_=r9o6pVMD zJ3#p3|34Q^%D?=1z1dU6W9oAgi zwXcMYBSHN;drOTWH%BHXZ*oX$ZcXvxM7XV=;!94f$#fbEbOrv~gBkDoyt$UcCgr9n zeU?6Q+rFt_@!UT9K5QTX$dBffhUb|9h^+KWOP_`TU=t_~F4^ z*s9ANWJ?3l&vI9NF0(!K9xn7zZ^I)s<2GL2o(uQPpI8z!zSa-EBOGKLRLkN*cg@h* z=N4e0_i=0PQadA-ODL~=C+E-x)<;i^t}NuvNzP>`aV#u`Pv$mQD+*tu#tUV4xQEH* z3Nj8VyMfhLv>y+4N7J=`X@-!%6R)->%;j0xz%ir8hH@fR13T`Cx!auFp(~Tfzjvka z>2OzZUCxm!(c{P}+ueu-gant}tH1s=5WQ&QqjM?m219i9E>=6N?82CyiV>mODQq(o-Ci~3rJ>4bWUs_DwieireM` z&BjgrL;AgSYR~NPJ1!!lKmOXQL6&})gkv$_=g`mwjk3@5#AfdgtK!`aG!aK9wpr7kg=cZ47^t&1u~fA!c>v)|zi~A9QbA zIjs7HUr7hH>bhI_9fp}E|yI#lc0aaD;y`JL!!$ik$LeO|L=$RqCq z*vwC}Uv;@QUcbUGdJu4OJz$)j7f2y+q4(f{54d+vImBgL)SVv&xaip9m5{}6dhUN1 z=#KRe&D z^v-5@Rc20n^)z*MhCN%8Nr!AmZ6x;gg!_?BHa9BmK2qc{LxK_uYDWonwE%+Zb90Or zV!fY!`6rF=Edn%`$Dz-<{#fyOZv5mq$-~(iL&`jSJ+`;X!dRvaM7KMN)j(&}wtR>- z+L!C<3wiO>>W*cwQTEy31NbxlL!DsNA9O@(h8J-N1=eNf@lfvme?wpw%>fYH@g$M3 zm+n4Y&wMM|Qs=P;ktZ-T-s!OOf2XEw!) zHuMY?mS_X;xrRC@u@zJ$hEOae;8FeM0v%72d}g@$Tv!@)-lSV*Z-f*1k~@eu9YfEo z5qvA4OpGu6!UF=P%-L*2r0iJ1Ykk(Eg2f=yP38LiRxZu|L^epk2p#FDGn>C9d`_C!Tzh?{=e>*4O+dOQbJLX>ET}ZW-w{f*no;r_@&PaIpPUESPM%oPa-3Ago(R!jVL4j&m?L*Y?C<9xkb`^Lacb>$iXUsWi+OTgeYOm^dC<*)EVVk1%=m z&85nUPcM(9zcW^W(?9%79N%sA6lGt3W<{Ihj7HItj@oRJsx{KlOiY5uxxE z(SW6V`=V{UggQpK_oPeNm|Of0*oCubB7ctak#-{QiF+W#;66<);EiZ;+EW%7@p|KI zC6kKx@UUKW?e=S_W!`RW{i(_c?^qu4#Pc=GGPn@TqSZTj5)I=f8J z*e}U%jhU!FDbd>+h?h%Z0nfFz`AE@-(3Lh2ji|7_w|rDqlon|e6k9+ks52FOtz6ib zl%$m5QLNUR`ApR_E6VH%N`X0Oux?m4QYGY>3;b@7mIm94Bm*z<`MmosVAG3t(XeJ~ zMM(wU`&Y7eA&hPl5|gomu{905;>qJkV9^7%<0@vGk(UVRyt#t3jQ zZ3nFaYpjqh1&PHq=IjMV>Q2o1uW=>cm3T2O#x@UNi`Bm*CmAylRo6){x7!5zhX;sp z!rNBcew6%03Dva@`uC#yt@O7=w#M-{j(KXebLVz6EnjJHU5Z2cbynn33N(|~vFpjy zx|zA8S1*8#2$whpfMjI$UQBpMFO7B?nkXs6B>iwRh#3de3)ca1f zx$?SrF5EU)_YujG`sD@coQH&l-p;oK<2evbaYgMZ>R9gN{U}PYdZc3WV0XAajeWMI z`M6n#aW()1ae|(V2~SIypl!DhvU08<*X8pNE4KQ2ogAfSDCLWfzElYE2JK-}(7vcpt^5AXf{`=zidfs;z%bzoF9-Z{0tu^ z&g_kYbX;PGhdR7Hyr8UX9WEN>*irRfrT&V)M%xH=6eK%&_MU1jgiJ@;kduYk%KFA)0T5$^CnprhBl*7`L!bYo$fbhCWvHOX43!}1zd8) zahsqRe&fWD_lmt50N~j`c?C{|xR?>D2sK_TProzvxUJv5t+rPFt1YnZ`lfd;{K0&f%sbXt zz6fnM!nWLgrl!Me!+2LyImSN3@4_zfOYTB@|5Z5ocr=SHJf-c|=F>utaU)8v4; z>_Na3(a`KYIM2>VeER~_=R<7@2AL~zcqS}$eIb6Bx{cEbSN%poQRix!Q|{Bs*|Ul* zrz^zzSBVvPggDgnn}()rQUqMGg`ID_hot(CO;9q=Aoopf-&0%TEG8l)_qwB3f83%O zHEk+}RJFgLcanHvr`T zWN+Cxgs)zn#t|wL%1!KDYHj{BGx`gcG51&Qg;ja8p3Ya#oR4q>?K`$+e~QiA)$x2M zA1HTzrwF{;9GG(={McP}3of)(2N9bgcT|*OsHmBV3g+VwPICmjkInA@j`A2Y1d{k* z?YMH#(;i!A@X_&}N|I{@!Hs%SF1^vnj>Z98*2#NKf*0eP2neR%U%ybi_SwmqtJ8R`_}Gp51OkX{%N2 z!`3jROvCJWSLAtnH;9uuMCtL7X>7*p*xkXXtUtPlZmWVLvpn`F?<8_#W#B!w{Ys5+!O4|$dwCIUj1%}%Otl0k0y^Q zSmu1l3u|yw{2=@Di)X!(=D{XaqCCg>C#TQvoKO?PhwUodOL!mVX=2Y5MW6te+ z4DD$l+zqZ^Eot&83n3h82%v5Jk6XiRhqyU{WIX}fXVX4r=NrdNy@{&=Zm%|&)LU0C z9w0fIaBe5-dCxz&VmswVvb6kUp#W)m-fp7)b-cpD`!u*S=8A?m;7)E%la+GQA$c(T z8)ItWIzc==Fi=J63!Fv2R({%;(T@#jpqAjzu{z!roX-;WU_rL+I@FfJGR&Q=) zs)ZIM`sXGXCvDq4S@4-|={z9^7X|s5s>CdMSN;wEE&Y*OqWj7EzYmhsVJ(9h|oPe_AA3cE% z)C2MF?bpgM)=JF(55hXtYLlol_x%X<4*OoWxR0NahTg=!?V=eeT8AS(K{eMNlE2gr zUWQhaJB<&JWY}*Zr9rE9LXTB(q>4^hzm;9|C^`UOZ~zYv<29is*GxZ|1(BnsA#Rjk zCw;jnor)*vfDe>k>jD`*sTA&utrZuj^spV>j(<_KWWu$FWI>rWyMf)C4U~cg=xC-6`CZtFvz_c`m>YWpwUBO`*XRHO z+&Z{buGpAVtFw6KTfKdG7*%SDd9z4|RxCOyJ zbsAiZu1WcOYV7!f{cKU+><+Lrr5-5(T{Qw)q%vjGFX4^BqxE|b(gNXNKCIb;2zkZ6 z(1rWS8}MCbR0I(jxVMLLA$!}#%zcy37w>VLq7<)94FO;@`^UaFm;SnVW%EnsKbv_M z0h5aR2rl0NH{<{akl`IEHd~v0>x)pR;-ZW(4)#-1;1Zq*27@?D_WrdG?~J$@37+mK zXJT&_zu$aX7?f>ZAa=0}1ji$Jp4v#rk!0@Tq#ua6`%W2i5`8;mL@Ao|P(kbJsnQwX z7lOb>0E6J>2;l(_07D*X9E<6%hZ^L<&?{K&OVkb7`+uKqOW|E(Tk~e=3^)P+mzWBz zRpu`-|IUSF9H2t?Cr7?8zk(vQ9+3t_E zgSkuf(;E@pQ3#-2)yElSHCRKJrZ{O)YKv@@Ibu*5E=9YyYdXQX|o*<+B9R$TsbCTWxl!)mSMMKAyjV; zek6E+u_64Aa7bI|#Qa#T(#A216~i5$)NX=by!(T(0Z==Jact4R6^np;WJ*P7y$9H_i(1F@dE?Y!;Q>zwyfKxb%@M~GLl3a!N9RAkhy zLx=ob(u=@GV67vo-M$F=HF8tfabaG^ zF}ALO3z9$EK(zSXp~MF}Q8IZjZNCvMT?aXSOD!qMwoLjnR>ZyUI7VJr1_lTQbOc_(enY4{ zTc}$9$rFuQPUCxk_3hCi)jII~R+F#Bc091ut79HEUN|}Nmnar`pJA6C`=gymFwC`Y zT2qlD6orHVt3a!AvQf&*gLSn2=oMK83jka0yTx7G(p`(>VgWZQQQwSeO{c(PadpQn z!5{;gz=?|Q`+gx7D4>fvPECegxnV_8zmLVtn!}gB+|sZ5&ak_`HD<(^pM5iHsL?jn zvxkaQ7nuDe!g6zr^g)4qf2n;n zVe>slq+3#vTV@_QJuB#+q6GcUFs@D|v<$G2y5Tu2A58 z8Q`P9<>7&(XK!u`F(QX33TkXf3pi4#V){(>IJQNqHmmG82A&6ZIyD`jfbp*B+(Dbg zvY6MvD_#Wc+n*c6y0tm@9u`JipLHE&PZ;|cJu2+6T)S~B?a-??qJcTPg@csXyv)Fl zeIXtvDw!&SP6Z+~5h~!wvd4<=LtALt{FvZieiUjIA9V@8p0Z2WE^BMBbyn=-gGbbE znbQ+!!~EEZr7F1^AEr*DeB60u#?OgaPoN-;)6-mNJbmn14)3HzIlkD%q?|EimvK2v zOsT9LuuG*Z{Qut9JuCrS?)qcZTiSF=7P+P)p6jgb{r!c^ zV8wiXnM(}M!eT$dTguID2w99G-zl$M0+^6HNP&Jhe^D5ns* z_Vm+Gv^mkfTovG{4hk&t$usHF`Ao@z$NR=*`5|QO(_9b4mauNtqYRI z>Y3PlEfymbTelG^YO!QhmnquD zuPa5@rdQ3p^0Cf|gYL^awTIO9%FNCDSvSxTS6)`sgy4_dwq;j8!s>HjPm)bJ(X31u zFy&o{mg8$yuwi@eG(EM4R=ypI-WQC10RCHk-p{Q0I{7`fhT+r>PPirtLEDk z7DmqTes9}zXQf%*%^(Bf>N83M1ai!mhy0;-w>6vlrH0ANrzU4U_A(b9RNqqDxnL6-0D3j1SQsiTglzw%+jM5gl5wNsyGivQpTgi>K z&>`FP^qI>;(^s&jqQ(eRo@ap*b`ce}lG$I~H@g;7Z51)17lyX!fYgF7O0S5Okz>w$ z1ZgY2)wk4lhDC2qVfdxZwLsWiI&L=jV~yDzE^=eFHe8-Yl5qtV_XS%^hv5t=)gA$>mIs^~99dKq?pC!Llg5K+ssxv4tG}E{ z-E>#@Zm@bVqmChLygKBLyj-F|cE}sM(^iQYa-mY=ZNS)H1(0g}SAoycwWz}vrejMs zY8KLe*sR~MI*QGX;zRa@`A<}ktbIhnZWyYkGF^P@=-mcy?6Gs;9)`2@c2hS487qrH zi8@mSuFth&itp(okv@U?HN!DJMSK|#`T3={#@MCjNHbnH9G3IR6*HQx6rW`U14_*1>WN4E^A@ur0dw*!7sm^&>`ujnI z`&3o(+4E!E&^Yql{Fu6u#_@C8np@9;#m9;Lj4{RA^V{EzP=)FjUh5Xul;*A4H`VNQ zE6}2TsI2@8vb=K)5H&j(Y0GrKw&;4B%YbeT@FhNd20rv~Hlv+8JW09Eg=7e_Nuv$-}J`{4`7eV^~t zP7I=>P^r6x&y%n%nCplfDYiJ$ZC>!Z10qH$%)3S-bas=kSD`$m_vQ& zI)+2nQ-x`VevB*cN^@5V&JX=`x!D(-GL;7E`yXILepfvO*!*CsSJ_;4-yFz~a>tXN z%kPT2=E$0AnAI7U8uxU!uBFZy5pfG&i!?6m+9RJjPA!B+y|4NF=gP)NxLhvNXvM59 zebQS-?W58M?8Dv&F^G|A<;%*il`+*eggfxg(%S>IORdss^OB%cvF8}@Dp-YrVD7F$B)t&*a$ z6GK8_OxYPTBgDIeN|7v+lzm^uZY)KzXEzwKuQRrpVYc5Lz2EQ8=kxtOe!std|Fz8P z-gD1A_uO;O@;otyWncO{QvLoG$fgSvaMEwPAAB6R9O#EHcE3P>XOI`*zs9Zy@M0;; z>dGy7x@j6-k7<=;jvU5NFj%Nr(M_nL(r zWjp-Pf-7*Llu21S8XfRS&Mrus6N_i`vreVQa1Is#aiP1h8dfz+OAi|()p|?#@)c}0 z3P%_Va`e3N>PhI2A0(SS<%*RV^Jg8G&8r%GRIFf?HWXjKnxX9?>Sz|)%iAeHx=LfW z9uAN=DoXvuN(8NG;Fjd<4l@g;rX>q2p-V)d9A zLV+<$KDgjK->hx6?SBWL?{DAp{?Q^pR(YxKhoZl5wOWBaEGD+Y+=tEcNh(HwAid62 zchbL#rQ!N+?6L`2u@aoE7p$|jUbdG_>v0mWYwKb9PxX0vu6&OXc+&vjXsEDvmx_nh zWYlkkyG>wq#Y}7zX{c@b2E0AgyR(fP(6|YW)+?j-Wma#RH6N=s_k#4>AT1p=i&O09 zG&v{qIJ)it^fHN2ptL!$%7^=H{VsR(vP(zy+h79I+QSy}vuT=~ zU-@ipb!zGXZ_mcEjPO4w(4#xfh7mBkHER8@f-gcpMYH0t?w2zW;f$YjaYD<*d(*q}&aBV%s?~OT#D61XC&5)W?B!X*fy|=|;ELA#gMAc_dT{3y zJq#I&>NpLW(igCa5eo*7QRp+0m!f;yr>*Sb1qN<;mq={vG`a;16g4wfYNpkq|15*O z6bq`}%F#xw73FR7x6W?5R?CvBf4F)!!Tw2{5GqfOrNsc2u4la3p^` z4givaK@P_9I}^pd4u5?%eR%T`fYW`1di{a-7_IDyxX@`}&ZKT0iBq(Ak4yDtAz+tF z&b|J|+%Qr>Uo%hgy5H(}CE-J+6oWx{d0bZyJlmet?#NH=Y^8M8ie$>TTKPilCUo=Q zu-am$A0Kd~WCejSbwvRD^_>77dCIeT3pm5y8?7IQnCa=RG*D`RijTEog!07=Sk2Pn z%g4(edJ`Zv0nQuqu-u3|E9T=87l*IHE+V~Q%6Un(j6c>L-7TBo9-Z0Ms_E%z0X$6T zNYg+mb{pYUB4=k;eg*%yX6OXwScN(L51+>*(Ysop!5V~XqpQdWl{LSvf6m_0;d{Ye z;O9tj-q8aF1GF3CXM)*nRIBM#(eeP*AMaS(rl7k1!H{k)7R~+rJ z&8Ta0VpX+cxz%U%<&3Ce`2y1Z}*J*_CYV9bF}Fj z4~NpV4=OO4Q90Cj$c8V<+Fz;Uj2ZtqmPK-7&yGMSAYVCeJWw*5DBYiC)>k9NIG_XD z>hT2h%i}W$Nd55csP)H*=3U?Cb^MjLgXHW$O)acE)-CzwI2!`{qUD(Y`fyLz$9i8WuPzr#9UV!roU-ypYb%w^RikAObD&Oz}0b zqdv|4ejTSDI(<_D8?7aP$gU@d=)V`2>R=p;AD+lMf!eN7B&98>WPo1U7;E;A%B)$2 z1(CSi6`P_N^X}Z$T^A;0;DtA^`)o06FQ!TA>xM4SIMds>uB_cD**iWk(KmX(h zZ}UtI+EN0sS(F)zQ~7Hd^jz9ZqKiF!QfIMm8v38#r(&@}H%6GnMoBaOjnwQ0p5~t zN>UFcK+o$~;3r-qA-*HxCX>0f4I|FV(1tIbGThn6`Wmm+}lL{d!2 zyh!mdm?+)O#@+i7sT4eVUv!MeXh4Jqu49VIW4g*70=mEX1b5v&n4qTJ9@Dg$Qde5eA&?Sz{J;+V_?gj~_cY^SB|7Bf1~`;pgX zr<%#|J<{YRXfaiG4tGuUPXVSO!C+37rfIF8G+?etHCZOZJUEC2?UCD(y(E!GF{5!u zjciptC9-hu1ZU_MjiQ`P>+&zmXX(I18XjnK!X|dfb$uaxwe9&;*`rRW0XRt~bFLE? z*HnrM0_?H>?O-sEMZv-&3`Qs1EYC#uXY}bIMBBeQ!PWo&<+mm!7KZl;IR) zFF?<>c>RoKWUm>tns5<2XKpf2`Hs>OGO2bHVF`wbtF`p)r;1t<)H018h=>|U>90Go z!|Vkkkf5haw5E?&^tDE7&9>)j%%-98wdJvlU>t+;+L{pAVOe(P{Sk`70a__9Z^Q<| z#Yu3$>9PlAtsHk_(yUd5_vU(N*07J<{q@*KW=XgeZO7C8J*L%-MK!s@4?-AA+R8(U z70i^m)a;drF|Y1rRL)qlt>;SnBE-MJaiTRIlZPDqu?MN9A3Oo#8(TrVUK2%tN`CVD zs{@iC2Nd`v5Mz?}h*gMv07v!^I45#@G1m>hDog(|CT$O-;x}LHSFE|9<@^f*d14M+ z0y@GrR0!%X_bBOtLy(~e(_&03sv3FXB_C5-PN8a9)7m?LR5qY$gTnkO!695QBd5yp z6swo+w3G;&PT=)oTg_%wt@1_@7m(9gm6s5Mm@?CZqn5I~V$F_%s2Ckv7 zzp7N$X|)TVPs8B#dm+r*fl*5roVWSnq>@b3-9GH6nGr%#ZoLm#G`f!x!JPvtA!7C> zs%5`219Ul#04rPo#r4=haR)-==;&1a%Gh94jBB%Ei}S*@c71y3<%x0fOaj}-g5di6 z&Z=p+Lq zq!YMU(_Q2({!B0!|Drf%%TI|?UwL=C!z>Nc<7|P61L@OtnhMqeHV*=W`OZR;$wFw$ zdq1=tb=Q_G1R6;gm;FsT)|=M!FS;2F(z>RGVn^o6=xo~}a{X6lQs5X#2}c;83K^6t zbZ(1h#E#xZl$m;T;*Npf^%!>}cX4{NkC8T~x$eifT@HkU&&^Myz}}~m+Y1d6IBS{v zHP2vR9yNm?MIU*8?Nu3oG7OU01NK?LoKj6(m|AaGbYPkjTTg<<=(5<=J<5@@_7bF40=I2Q_MPM}p$gvV0pFN8;`ascyAB(OY63A4oEn9f)xG zMwryhqtwh_1&;e~`7a<3owLG;GTyTqJ@|{|*Vfq8179Ja9{ZSmKAqd^x@6kiFGn~U zxeV?ymhlpdM{;9LK?Td>sCnrVpDKL`=kjpGU?WN2`TeATEuB!f@zSjpB{{O8cIY#q zLevFkl2M-LX~N7@r@u(>uk;h-2I5mnr$Z-ulhw%pKlimQa=wF(%bMjRccJpTHpmI| z>&9L9h&RaO4;Q@#Xhr(O*76^WK(YPJkw9$&F5*37uEdC*U?Xu zqc`&!v4^E6cfEmk2Oskr(%h=s44xX>Y#THNs;Od=HYGJM*E(8+_n?)3-gm!w3Q0L& zC%^orXfbgf8^EV0gmn?7Fi!ZG?4#7$cWj`2!WKJh_4PXQGP`^iuL79k5WF}n^z|Ll zBZtA7Yfp>OwyUjcZDNQtOMNz4(Qe=yI`g!a3mcz>ccEC<@Lbf;h)16RTxPqn#XLRJ z)?vR-E@y0{fR_>rPc24a?))V~fo2nYAIyBH*%;eAdWhykJ{tN~FP3llXX`WM4_^I* zO-+6rZr%?a*t#(1n4gPgOyt0FH_vI^S7daCe?mcRN2xQ%y!;Vs)|?Lb}K8m%y8wIj55;g*OR)zVZ~E{JOh!tfO&|N);zuC z*t7Vivp)a2TwsIJhlY#KHIF0OI>Tz0xv^?>-!p`SBcD%R#g_7dZC;LVmeo6l3YJX!LWmE&s7f`-WM5+ks0Co4!xu?O@op7OUt zn*4;lb~OaKSz+RK4|=)&YWn&lmGFWSt4$#NsiFoCT=O6A6bCps`)Fso#?@y3xGfN* zW~9v@zJKFPOG`E4uKpKZ3nH$#R`;D#<*ke0iy9NW&8yvzb9x` zw(}?oXnAd8Vk-bd7f|Hr6Kd?kJ6)`7lN(n;5}wX|fG}k$pXh!SZn4eT-R~MhY26cz#bWC*l6x7*f0g=UC1F z2(s_3hxHxTIG8nIP;FT0=zVSUAb0yi{eW%_|f1okASMg%6Q!(i^l^0f1VCabBVR8o^iDr>^z%}M5mkZ=$t6~ z23~Jh#tKx8$aP{VYo7_zMmLhpL7>zSU}(#Y$0=%0HnCEXn8rZZ+xIto)7ZjijhdvojK|Fc zZh=O&tzr?vMItu7-H%maxE~8;5F8Flv~E&OsT37vq{;bU^g*>m#>6RowrYd5Ell^t z+5|6;Q5NHTCI4ky63ev@5+W3?jOS$sm5uoiVBsA)(*8fQjViWvdQ9u2E2qcia?nr^ zzZLFw9*XEYLe-wMcI69yl`<+CXXHI>(FZVXkVDlu%=NV8trO%kuw3L>@M&kl#W0%AnepG&>%q zq^+xS;C5-vXri<~)oL{FaUMlu1^X@wZtsSmjn_0dm+I``8k|oPatEEUvZscNZ>?4M zv=(vT@7EI!ynMO+Tl^AOT>QcfxM*iur~HduD`SN#E6T6al{EOMBN5U*w3u%sK7ht1 z28XrpOGx9u-}*7kOsgmK9ypq#c>8n;G}UJ@Rv{u5Ilk*$zS1^|sr13Bx;%B+)*Cd_ z`}K@3l}pLLGvvGluCh?}l2#haYtp=|#v-tx?c1!o)dRTY4>l=#kn#UU(cNeEV(ZcFqaZN44c&$=!jphrZzpP4Bw4* z?74y6ts;apKijadt8@i7Q)-Qwa}e0oq{k$TH{hyBCB}SQaVfXDp$6eumNL~gs0pqL z#Iu1$jOd;_qDmKYQXTFzm4n0ha1ggZF;vh_dyBXgZ7()?78BVm!-_^jg7G3UkBzc} zI%z{qbKCeomG3No?tWLIZG^MnFym3a%kRmm+JyuG<0B^1x1K#F+Ikx5mklj`j8+i) zMn@2knyAOOaXNn$u550mKO$DGSzWcT`Dk_p=T_w?O?}vU1lC>8T{hC+XAoN=Dkw6D z`6BIyYQ|y4k1M&m!mXAal$xMh={lp`qVltmkk`xe)2s3U$!BRSxtxO&amUzJYz`8q z!C5h9EC_XbW1rhCIl|t8guFYWeDT5?uZ6YEI)^BwM0|AHkU!QH zAYpVtog044&+nC+B{d5o`jS_}lOP>{dgE)$7t!%6_UUx+ z0J!ygImjivl$U7efnm_iPcVsz7SapH`#?%Ac`HqEzJ7N~$mb?jTT`+j@nq;*?q!wP zUKim*V@9<{mS4}ik_@rPz7%PkXD_Ly$Y_;B&R+0MY_5DngfH{{y$h9>2$8ThD8LOY zeQHbbP1V+wR_WOz;q$Nu3hgzwnWO#^y|&n?lb<*Glg#vNg=V`qhZ!ikmrH{7O-XyQ znU%1~*wOF;goC5$OAVIfkL#Du$m2~Rer!?@Z1kYWyL>b0+AM3VDz@X?@C!WAzv|&xjlkv z);R4mMyQc?>rJ!TYn}UN(w;NX0N`c5?tFz4*}pRMY&&P3R^k{MoVPT6lZ4 zw7c^cw4&Wsw(eO!vWgF|3%`nfaup$eg=_gHaX5tNyTb{1d*91~%1gPS7)SDuAu41L ze{r!>OV*0fay0cB%&)Po2|BNX&Bx6BTEEs;x+lNyrugarcj-OzsvlwlXFJ(<8?n5( zuX&LPoOPpS>`e5awU7Vg<%q+k?2t+ZIamf<&`H@Wm1v-2Ax+O+u$|j3)=wp;&3;Z= z&%T5Hk&;UE?J&g3!KFr@NG}2%-)GKp9G31I1|b_wy1;!@c7GDms$>bmJg&AR`L+Dn zatp?Kb6TmrTAER{qO=Augr_TkW6(f7*)e$+e=_T80R}FH=V^o)JK=RE2h!#)7tI{_ zP5VH;LyCN+l6ZE!C#HE3{(!{SvHK6Y-FmYvXI-N*P#K(9`Y2wwz^QSJO9^?W1Rxft zZqCY!50-P;i@(@i5&_Cbl~S@<*&O4dSG6giE}$%ngAoH#K-WS3F|{;{1KH|`f1&M3 z?o2i4XKGiH)b`e0FTdff#Q*1ZYg3VD2k8P$;sl-NK2@t9A%x7Ye6!a~G~-}tQbtCm?AVM^x$!SL$lDp5{JEaY^_01z;AT4F zf^~CChmcbjRMssY9&y?=_~T-gCTa46at1iNXASEKKgo1srwhTI0^b;UTC1VkFNS0e zmz4ODMR!Ag&X5Hld6-#%Vq|Deshw@4S1Z13wNL}V-qpc- zF>@cw9J3x7wL{A$XzL4&WxGMoW%H8dg?vP=&*5jHH5rq11y5X&gJ@Gmf_JQzyJ@Q+ zTEI%Qma*C0JF6|8t7ZSFak-rr+IpB-%@C1Z>$n>&-nb*JAfUk)R@Wyt4vItHL`)dJ zksEjR1u|l!mKzy6Lj6eGGgsxwI0^zMx537RL`zo>h&!j*46=-pS#;d(CsoWSPqR?O z=;TKfBBpTVG7)}d!eCi`?Ev#+CVMfKs zI7!CqWSI5PWOu|9Yg&hIe^}3K60Y0-jTR%fNrz{Vch-Ci&Ie&u4l5;58-Cp-#dWiC z%o@IeZRHqme{<=m2|G+2?lxpvH*ismedFsvEb`cP@Pe(_4ZYdKBtZpoH90a|y0$T6 zWw9RKuHkq)g`gf;I_?{o%NQ>7PO-WWYVEslsv-r3-PKlV5Z7yDOxzwY#pqP&^xZBT zz{LurHd+W+6BD3i0Nq*hf>DDg^5tz8dAnEpeGzXPxsy3~w=CmYf59bBcIA72iGEm*Flfw{D)OOI7Q~yX598#lPwHa6dhRZ{<1&GW37#v9Zh#(fh6dK7 z9{zVnscKnpxWCbL)Dfyz3tdl=wEA_*BCN~RKdp1}%|Ih{9g%V9`uNs$+b@sW6N`Hw z9K}5gC-_;TX5yJBIGIDq+!W6jcx3OZaQ1G$Z^92v zZ(FnL!T0|8dhO(oy`|b2C32+uM?dym&3E2sF#P!T8gm`W>ef)^LoSP+%IkJhw^DQVWX;(021 zxF@^2vig$hOE;{7&dU*u;)<|2wMlLS?`>^+*;?o%rN;a1q5GQ^((Zgg=867Si&pqr z%SN?j0v8L=pKzO%&}@}f?Ra_kdIIiBfV{K z<0<3)QyuMl>fT#RZ|6U-H1sCyMb~WOI@LGx<1$xr-)`vYampOI6ADZ=VdS61ZSKg;sW(P1D9iM|2Vvs$t%`%m9O zskzsurH*;@r;L_8qA7;HYh+w>3oCR~T31dOu5=~BTiY*1%KI<7;+jVK40O)VBVv;R zT&SXbU#MNNZ&`6%u6lyqmGK){L4?6XwsURou-lzeHd*lSQxwVe-T5K>NX^hPgNVE# z@#chS4XS#3Y3>r@a`UXkYiQW!NNMS~s8i~m#R-w}&RA1(vbWCfJaSDs`{Q}=lBO}j zroy<(c-!p$iqzhKw8)y01&xWCAGZAc57on}F}wD-X_^Q~k8d};0?si!XYcn=wz4Ve z<^10{y0M}haaLS`Gg^yp_z1Yfky;J*u+W7u;31tga@-1)3dT=|-1{UWOS4(o4jva3 zOLR=H&4j*$tgl8J1)vLVQSS=ncY}aF7dCHCFkVJ5=yWDWEu%g+SS2F`Y_K4LD2|FV zkA$y%48~LJ?R=Q)X?{}vPdBd&h=qX|(0uEq$Q&w-Yk!unxdJ2M0sY0n3S1bj2p5ib zHTdxdIEcaHWy8Yd8*<~F_%e+Os3*tGVip4*Jjqz8v5#CBJ0whN!beY4+iM0~swZ66 zN%45vtgTUu-#Y-HR_n&6o>k~Qqq^v_Ry)91PiW%{G5}=~PSyvB8hHGxd*pF5b_tWY znQ+GGEwJuG;xr$gyCET<8@i&RgVtE0T6~0!gV?Wea;qALO36y_dW>GPG(?>!>Caey zqasbsz@&QpK4|GWoKg=D5+jtVJV9187a3~kKAOmOyn-Ssl)aL49P9<+QAZrM9etmu zdEvXGQ~)B-?s_nA(XzR?EvLsG&mPiKo0AX}BF?PD>bULDx-TF} zd~bHpH8t5w(Pp$?6I1!jiQ1{qMdlrE!jd3zb~Y4iz=ge(Sx*oc*!55D{GudVoGn)% ziL7>P;9|MyM{b*Y%!F$(o)Mr@2V{WzaAKcSg?NtDC7Gpx6ckU_@UH>QzAH!r0IuS`$^i-T#~#Hhf%- z&^}&$D!I9#TJ3$_8BhQ!Ogrq!dQlxpW-AYs8;1{P1?doL1X}up+-|uupd9C#O2wsb zY10~Ov*AK7U>{9D@Hc^Mom@e9sN}jdGlH5w(0Nq+suE}?_Z_q~$!GtkKBS{s*zcoh zol?b8-X37`RrwZoy-FcHL+d0~)2+$JWk-n1nPy~djZMzJnqa&icI(U%ln=&DcYJ~f ztA(~2u}Vl-Z|A+Vv(@a69Zl=h=&DbLt4^4aYki1)HC0(F0KR8Ljd06G2_jOaKC3PB z)y9IjDmr5#NR~XZON9@aZ^`vf2~Luv%;QYcy7Xo_yNN%%O+35_hFNeftOi*p2S2Vh zhAL@9h&E@9Z^bXqHaFiJnLrxYn1jk{U}T+TWm=sr-ZlOc+>A`X7*oKQS{jZstvxF; z`hy<9TD0hifu@HNDD|+1=o z=Kog3wD1LSn{m;mjz+_sZ4VOP5TMu1vYni%J+WG?#x~RU4jyhndfo-BP4gvvniJHQcMeZDKEG&CkB|RPp5tWwo03ff|?ay zIB+!a{=-KldT8CW89U0;W-Z=3A!bqf#`|ZAl%d9!_$)ZPvL(Q&{(I&}K<9x2u?QD` z(~7E5saQz~J>)hW0)F*Tmk77>{3Xan|I5?k_ltQ$l64_e&m}CrG0Mdy-lN`b;P{ZIjC{B-*L&SB`fY&C!UMMNtCi|zFTWN}`ahA6mu?nejRbrK$2b*h zcqvD9hTh&=zuh2A8R?WV?6^J3$EFv8Z*C&rq&5p_H->*~PO}w}U6*CQ6!lu&OhUXl zD&&_%k*|Dg{OR9SbeDJUC_S%r-xyznGs2@K>>6i|isx2H^a*Ds@#z$BKd^s{Bj5J? zr7o(ijF&}H{IAn4ZG7*&^Q4V4C@1y)-gdrUgHJ9=7|eVtbd1u7VG;NC;Lc^auz)@> z%Xna1w2%_|$SWD}=KT+9TE91v93}lmN2OLLz-M7xJ)S!#NBOG6f##RWWwyf2Z$^LJ zbGf!I%gXUQsmaoHlwShTJoit3suX40y`B8XFfh6VF0mhd0582Pt|K8p;tmpNU$wWF zIQL;aYjpDcS@WGYB%f(`9o>XIT*s3(+2nWdu|?xa6LxGZxX=28j=w!(LQc+O4M^9{ z+>-HM9Hjh* zUYQ)Ww4}|J7l1Oi^f?0|?GJ&#Bgba4m(lT@5b5)R5beVr#NpF%`tzA4mLj+!d1c%d z#Likw*qP7e?D}fhlpDvyRq)d6m+okOu-?NecpH_~NXiOAi)9Cqqm@3S@KU;vSwTu5 zz15>HEmR^-i}-NuX(?+vb`v7mJ~}tutyg-;879M-oWrXgIMiZn4XSuD(&fghP#*#* z%?Y73-OdD*x&~be%mzwdb)#e`Uy$^>M{lo-b^uz)@xYdx=@|0ouw z-Nhm^_lh-$_DG(Ud3@Zo?zGzRa}8ery#NTj%kmkxUpEaR>t10C%xt+X<~${&1LFL% zflvU%_@n5*zke^IRPYWIk*sSj#!QP#>E{i;?HxW2D3Z6NURqm-T^Mu7ub5>@*1Aor zk>T^`n%{)-AB+2EfTv0rFaT<-yqOoCj#UI2pH)yqj(1PV@9<1n@=)mCbj$m*=jHHHB7K?Xx5lH@ zOhqVJD=f_JN1c-Yj5EZy`Z9yVY-jk=A0Ptxd-&A|k5bb*o#D5E^J*<`<*S$z4_@!A zI>WjNG+kru$oRL4VYzW%TF>^>IyUh0YD&4B~)pkjN607T74p-Nu$(7OB=wuiFeMl4;! z#-{sv|KH;%e-R~Rf~`BU`AdvLT3mAf=@3&g3u^rF6lgZFFrcKu!M~(eiw6FYCOdMM z*qXKugZj!sCI=itHns)yo`1$6ic)Q}gG8HL#?tkSBJByrch`3Yy0lyj${9Bo;|{am zKun;)Zag`|iM+xeJll-Y(Kh1&w*=Ub?M^1wZ_Z~tU>lT?<#Y#*yM5XIz7alPtd1w* zJL|el@CWz+JL`HUw0nrn&#=`)xc#H~AZtyH=LST7i?iME?q`x7a!-BR7`E0xkS{II zQvO~G_#NAZ5z#<_`sHenm5@Xh3jF^^#=7s{B)VwWJ%~dMb_cL}9NfnFSN}a-skpoq zmZG3}-HqCy1_czemBs^<+?`W)JNxOUL)#s2bn8tw`j-PBTXe&y#<4OI)_1V89?H&mj0(FXE-NrC(MR%SXN)F`^_&@u3T zACq@TodbKvzYqL9NJHyf4mf{UpL9E$|2`v^ZgVsbF*k>VDat%9ND2~?9 zDqUht4WS5j_@{`^7a>$nYUj3shpNNmcFmCEsVKokI>xQIpj2)Ud}2b>cHw55iz@^$ z28W-@+0vpq{0lYJovXgZLt~AK@Rzx;Lk0f!anRX=HbtyCZk{2Ip82qgP3vKlG>0AQ zx{bVaTq!7Br7{PHlaa8sxI?twJ}U^w{utinE5AfvFokm?35Nij7T95ZOqnwRT~l0UPrJ%fjJ@VKBrqfD?PWFJhwJCK$gf zV6d~Uf94ibeE#vpqpan80+nIZm3_<`E@)^yAxr?2_8SnZj9fa^F>QNkA9{{bo@Lnz z8zsAZzo0+;_?niKv8Tq1t%D`c0fkQF2WM!fRva9j^)tXjBTbC9BHjGfCZSbJ%(HzS zT=b?&FO0JWCB2B^WPgkF<0r3tDFUCJ+(KNU#Ei(MC1VsQ^l2r4o)9}uew6apsVIe+ zXqN9&xhe!-j^EONs1JBOe!grE))w<^^aEiRu#9h>p{Sr(pa*?CJV?zY=2T{$t{eEl zwx2W+f0rAe2fn`#3{(l@Hfh$A%)UGX|0e1TA!6>Tz&^H1E%k(R7%uE0>&2=7{>*yf za{_pQWi6Uk8xVw@$J~9^#)O@xL`Hji&8&)uA7cx;5sYV2g#NXn0T!*4tL;# zqQK)5f-h87Q+Z=G=z*(F+(d-*fU|z-H~>OG3H~#PV-pv)Myw7gau^)7otfKMtVV?3 zyQK&y5BxMkl=S{YJsB0|s zb=#H**ZHTMT@;W|r_6~Z`_B609XD2o ze(Jx!`46W#{;$Qqw<1zw&^zz}o&mzNV8D-^XYaQ}sd}ZIa|xg)Xb%5F)Xuy7Jvd!l ztR0@NCqyGT|C?F=*RtsYC@$86Z)O8vU4T8>LA;32&{ARx`!qggV z;k^>B>8|PVz+mn@!CM$7%@V1Kk2uX1Rr(;dG6^h~I|URk@pQIAu1w(UE4I29MuhsGWm zD%xJDje;+~I~{WnMfPp^{#t1SgC`OS@ZFBBypoHRi}~VwUt+7bdiOMoBC(9v1X-=9 z$NVu#u-6!YW#Oo*O^b%DP5=dq58!qlHhUYjHwJ7v-m3JS6-TCcspDr8q6qR8WhCIjv zypn__O~Q4NnuT{-I#+$94GgtPiG|)5Vn0#e=hT=%9y8uXr9u|-s#Fj8PfT5Q9CRu| zp1@q7fGw5bwz?_P#L)pGueS-aPZ2RgnOc1GI{f9XIJ z@Um{?-&$f$YC9~5{5^4%qPa@m#TUed-I}=1^GB5yWB8rZL8|1|VpHg=j*uUv}RH6Lxtg_ZfNu8&%y+aG~a z9b;)Av135RDAQ92ikXeZ(O&O+^KUMTmyJG=Yt``*Kn?^}-QC~tj@?aj$j7>t)c0Wd zp!qQaLqty~RBh}Dd_}vFAS-`p^@n-Xvg}fR#b~8#zP=e^PS++nMWIc<%m%f73)+m? zraeDcKH(eku+eP7qS)R<9X+!=QCd=OHC59sCl&HXNA+eXm*ZssU-igz*?R@ z$;!F$YoXjPsckDyd~S33%&!Ppx1Q}mN781sDt~j&{NV0B)HXse3c0p_a$*IJuUg*P zm-mFC0oPhsqn!-E+AoASvP_iUH_j#C>CN)vK&O_;JPhrcdM= z63;IXVH>lg!cSHjPD|R>!!W%r^j{`#E>+BOp@+14=eNyPCEUWW{w4;U zdRXp`7~1S-U1;Dkx#XP!J4YGS2&=Fkq1Tj`G$z?FKKmjTrk@0^_-}>h)f38?g}=7| z*Qy<&mmjE?c7J6JgB!4k$$hEy$Ix0|{stl^TYIBkKl;=XHfLR+K?4)6mlXYIa|_*S z5}P+i4VW!;)S(XfQK4D{Svb0om$2chH|#~f1?d=7q}3`=;5`X)^NSOK*09dS=ppTr zUp0hy%&eVX)WI5zw;%FA1zwp{U&QnKc5l?UE+NLfqILiH&%{`LIW}eQc1J0xgyD0g zMho+qA;ze;7qm+A4A^LWy_X}G7nvei4B$oPyX;gZe4aL9RzZ1g#J^FUrHwxl8k9@k z^VF@oAj>$&;(YI7sls|Fb+Z`#DOzWg?okBg-gP^7q1-(qsbnUop zybZ_ry79U=R~%~YFpV*(W8!kf?o1FAKIB}mim}FJ?}x0uz~JJl=OdTj`9f-+e4I7i z+}b@M0k1GBBhBmSKsCP8Lzk@xWlL@6T!)loaXwRj9X&BR5Su?@I(H^pec-Wt&*pG9 z!ShKGRlq@7-ax4yHWOk*;7Xf0^CVeYsTSpz#&Y>}ouX(JbkCM?>|!e=+ATmMIa+l< z{#sS%N3xnFkJk3{Xd@n{R&Bhk>64n)VI!M{uFNIRZ*T?%5sB|iQnODWR$ayIV}s>v zdKLh^@dsJFNn3ri9+pa1vU!Q?Q{TZoVOg$h?=_I`FQi#ha4HmfIL!3l^}eR^2cRq$ zVbwC0-W?hh_GYHDI8UN={idR;4ln_Cn6Ha&aW9_vq~unmMbm^+SwI>8HJ?Q+X!&zu zV|2*ECVto9ew(XAzG7`kk~DWHFxIOHeTlLhk*J3O>r?olV`C0cmX<2b zv?yBb?|!6-ue=AVhmoPWI;XZP3#KArIds-~gm&!QCepOzl{xX)6N8NwHrw2Fap{Wg zZuykaTOj%*>I5NbstK}zN40|Y!-eC!Z?K73m8mvi#oRlaD3$fmkETrMAQ8^o$Vs<| z=()ITy;AA=WA>fE@|C($l0lrQNReabDb7cx_XuvUM2Bn9^as({Ipm3|{>B3|)zk3e zMY_{7Re}#A-f#k z_(B$PGj*;n4~Q{u`;ygLl6#Da)LginicEo69j0dKoP~GC5EK`Vt{SZ+6)73cSNGc> zOixh!b-&Ce_!?$+Qr(UZz`x;Z;YXqqv>4sdh>|XPgU@K5x6QVr63$(s#xY0e7Js0T zTyL$npJ4y;)}1M2;~;nIU1f@Z!ySuXGBlMN8JFla>P}i^XBctm;r>Eh#YaE&llhyQ zw*o1nGKERN3%#2Uyk8pR`H;SDhXNbRg2Hrm`P)hyW2g&?U28VtgGiuI$JlPa5YqKB~9y^=ZMsKB?`mhp84=p&B@iexGxLHrx2$IJ{6AXiFelbNKHNW3R;}su9ibN~uytK<0s~NZ;jwcP2WJV*Uzy?f za2LFDTJldZ=IM_%hb3cC93b0ZX`Fm!wFgT)HQu1Eeo+k>Olip2(*N`V!gjK3nEaPI zDeU=(^WB81(Au(e#>LH_O_cBw`?ZlA3gSvC{skUhYngeF;GWMWNuRssS!TT!_WWRE z63No5s+z8-Ik_>iERy7P7w6*&daqRC-J6x?*1sn=R%YkP_mYOF&p@eZXRIbctjfu_ zV&>>IiLsu^ybIJ_6AZGjZSGe0P9$2IelMhwTwjzy zN$MvHgqO7qME|ucHoRdOxr|~ju@2NJ*a?8N)e?OTB{)fcg*4Qz_6#WV=x8E&aT{)I z9}n0k3K%GA$!>1<*4S|1(VxfOUC2CBd%ovRCR2*MPJQyT#@QiIBfTQhc7T$ru53a5 zW+0pB;F?j%*k1J5m2S(CBAgf6{768lv2%#+EUkJqHo=p8DC%exUif+#o_zT01L-m} z;z3CFl7Gp{xkTfKJ#HrtBGHJK!jHo-j|BEM`b_xdvQL=g`SXlj&~nGX&hH|Bl39B| zeFRN)zdR2fmP61Bo1+&la;LA=*Li8_yjVfK-yS~?T9BzA$m9gSD(AT(Y?#Zi!#=2*JIo>Jw|nx1ce+b@vD>2ukkn!^wKP=-zUHnnt6XA>j= zO?RXTJ|!@3Amn$~D!IO7>N{r$3PL)zbIPNg=Biv%bxR4K>j`RD%L>DkyGM=n)nrEI z3a~Atcg|D9#+XPo{K%&IfNj7dJOtBIi8hs{)P;Ilqei`<(fgy)=eFD{CZk4{Wi_KR z6MIbZ{WIhwzfL}LHQN}0SM=8;!hmU*MQy{_tLJx>SyAuWB!|>U7}z9BpDPrK{bC1D zBl)F$TiP_y`*d#*__k3>-P=sW{VHv3+i+;gPC6;tc{F?o&u`tc2a}d}qvovl75>1+ZN!9;gRZwx#*(ElaOa6{lcZ?KR1a}j?I}yI zpRJl<$65_hi-SJ<8zX7-&BON<{Tm@KC3Rmr*!WKWNY+iRb`Xfxuv9kjg49S1m~@_U zE89MYmiq2ZI52)tYsD-j`oK`<3twz@SK;Owg-&X{yyV%w##f~cYgpFX_8ID|x20Z{ z{Jl2EqH#6jP4O$=lO`=nuSt}V&dx63Y!#UJbC}tcC${)NCA;U`!1Y2K#Vj>C{9-Hg zEa3y{rTOYar>(T;u5qI52OZb=I@D?J8xFKq+y}_uzF2Rb)+?bp(E@#1Mlbf)IyrVa zR6eVX*^R|hno2C`^G31}wzXP;R;ziw#~01=MtrEDk5e0wMYv}{XO^VTY&vPs=sLI@#H7sHpMo$J;pg zi8H1){WF=b19TmzYCc%y-L>IgAFBtRGRzPbG}VTm_mG1h2AMz$hiQU8yuy#%P7^+& z8jzz7<4yUj`k)fLE;?>3Sxg~-E9){FKik`U%dG>!I4$u>*LAI$Gq&ASniwhUxFjfL zdgdL7(g|xcdic_Ok6N7fdtB?E`L0AN8KtuUo|)&y6OZupl?^d!?yvqTywNkGYVBSH zU7GFo>}=1y4uQ8EAAa+6;W$NQHYe;Jz@-H~@5zwvL=$wY+}#ipP)>-@l;jlC5uYCB5J7PZY#omQi?+S%D5;CiM`H^2bBOR z0Ij|%W#lIcly}!rztxrXT&P7L>9wYSVJhI>7F>Ms)-)ilH=9(ZlIBXK!p9tV>b|0jO@FC5GYM#ps5YhWNTSXLH z7IChM>ZqU8Q0Q=M0A*cgAeR5_?-g{F4M-1{S9e4}H7PE^pvJ7$~qtULU| z&SH=TZgw(mFG&Od zjWCA)AhH0G8sd_kwFEATCaa(Z_+=C9AGvl_ zDO}Rp*o^B8^;GQfd$&rOK3=q}`RKZqNV&vX@jxPi6yr)x0|58u8ipejZ*r~V1P40ZSho}D@{UJx!^QZTDjz&Ye%HeK5nIjG`ex|zsBBAwo@BdTRwMQj+ z#^GmaEbvlE7cY%=bY{calBOFSotZ)@ z=@dLBV4<*bnJuI83qO;iHZ`&-N>aM_{V@L6+5X}H-+TML&&T)jJiqsO{m+l3oGOo< ztuKz6p+rB9tw(!vwYP^QUeC*N-QodI4l!^#3x+QdQ7P43w}vI69$GVMzo>Y5mrp2a zFXube@YWPx5T0eTPWBi%2$VhN@1i&F!UY{;IkT2B+t2Kt~I4PJYo9E#~JMN<& zy4=LQ8&QeYE4PRph4xQhW8fJ(ctdADyEerlawfb_?%Aeqer$u1i1ErtB(FR*caT=| zY}PYPAPzFk$PKk3aF_w$cL0HjtiP~qN0yCqLE2(W-pgz&X%dJ;MHGxm7&Xxy-sTQc zAbE&GHB>V-$XdF3u)F0-Q2fz2Yo;hE{eo9tQZ&Z-6S!V&h6Jk*s1^A<=7Eo^V>UU~ z!*lP`sql`?pe{g;&kxM)!LEHHG(t-!A*RTBMA;yRk3azjXZFBNfrS0~R3c9+W#~1c zOMxK)xNx2ha$)yEJF?iEF)Y5c~J3(;RpZl=*L|25v{ddDj zwIBD{r$;ThK1HgL*1d|Ga_FqGR!A}2+!t7KBW=hpnJ+5#?+-x}_#Wg>zAI>SKaOVF zd-}YhR>)GG%*b)N6o$8)Qn4SMsej2xi9DKv4P_;RO{b+Q?^NLNcS?B0g>T4N39L76 zE`?kuK7*?YE@#~NhBl5$B!@3`XB>7_CcKP${aQ*ffPZN$akC3=J%1r|C5HV7)N(O? zm5s`K_pNtjegvU?gP*W;7Z7qAEtxA-uY z_<8S%3+Wj8+v*<164SLV<7^_OVB@6LrH+2zzmcNr*36 zf3`$EQFSNMDoSQu4^#PY7@X$zUi#xjYqpX~nV^E*P7}K!SBtkv^;0QmbrZ37PoRr; zHG#Fpe33*=sc}2|O-U>3kvyb9l2*|_eboog@Po)`3$s?3TsT7mV;fkzf>v*u)u+4S zGKBe5wsKY17BE72~GL5F<#wn^C66 zoq_SML9ged42k{62@5Py1hYO5>T*DhmhH2I23BK^AL0de6vi*M6oHzB;r}iaw~*cg z&nyApV}|s8iMM5rp!^V(fQv#9G-k;OVik&U(``fT&d7|diewJwX&|uNth#(LAaT-I znfGZkQtrwTq>qV}(IoYf`AZHGa)(v@(}lw7Dx2NT0*9Tl07Fa99pt?3SjKg7AyYju z5be8-w+7nl0ulWoNUYk>#7Uj&2@-mQ|5r{FNp&$^M+Vd}>|R&~Sfi%WQ*o_aSY2(i z)0rROdu;EBCvx87oUKo&Yz5ExqxSl*6P)61lYcw278vUSrQUEWZ8Shp5j?s|SbgkCF7nSETQUDBhLDkyDXSOy lfq((&n^0*BUy+ob=7{( literal 0 HcmV?d00001 diff --git a/doc/reference/c++/mctools/loop.rst b/doc/reference/c++/mctools/loop.rst new file mode 100644 index 00000000..d31f0b0c --- /dev/null +++ b/doc/reference/c++/mctools/loop.rst @@ -0,0 +1,75 @@ +.. _montecarloloop: + +The Monte Carlo loop +-------------------- + +Introduction +************ + +The ``mc_generic`` class is an implementation of the Monte Carlo loop. Its +goal is to propose and then accept or reject changes to a configuration +according to this loop: + +.. image:: loop.png + :width: 700 + :align: center + +As shown in the figure, after a first initialization, the loop starts by +proposing an update. In the following, we generically refer to this proposal as +a proposed **move**. The move proposes a modification of the state of the +system, which we call the **configuration** of the system. After having +computed the transition probabilities between this proposed configuration and +the old one, as well as their probability density, we compute an acceptance +probability for the move. Based on this probability, the move is either +**accepted** or **rejected**. If it is rejected, nothing happens and we remain +in the same configuration. If it is accepted, the configuration is updated. + +This procedure is the heart of the Monte Carlo algorithm and is repeated +at every Monte Carlo **step** (meaning one loop). Measurements are not +made at every step, to allow for some decorrelation between measured +configurations. Thus, measurements are made every :math:`L` steps. We +say that these :math:`L` steps form a **cycle** and :math:`L` is the +length of a cycle. + +At the very beginning of the simulation, one usually allows for :math:`W` +**warmup** (thermalization) cycles. This means that there will be no measurements +during these first :math:`W` cycles. After that, we define :math:`N`, the +number of cycles that will be done until the end of the simulation. + +At the end of the simulation, the code will have done: + + * :math:`N` measurements + * :math:`N + W` cycles + * :math:`(N + W) \times L` steps + + +C++ variable names +****************** + +In the C++ examples, these variables will be called: + + * ``N_Cycles`` :math:`= N` + * ``Length_Cycle`` :math:`= L` + * ``N_Warmup_Cycle`` :math:`= W` + +You will also have to use these names if you will construct an ``mc_generic`` +instance from a dictonary (see full reference below). + +Monte Carlo loop and connection with moves and measures +******************************************************* + +We will cover this in more details, but let us already mention here that the +``mc_generic`` class only implements the Monte Carlo loop. It doesn't need (and +in fact doesn't) know anything about what the configuration is or what the +moves and measurements really do. All it does, is to use external classes which +take care of making the moves. It just expects back a Metropolis ratio so that +it can decide wether the move should be accepted or rejected. Once this choice +is made, it tells the external class which again does we is needed if the move +is accepted or rejected. The same is true for measurements which are external +classes called by the loop. This will become clearer with an example in the +following section. + +.. note:: + + Above, we described the Metropolis algorithm. A different accept/reject + scheme could be used but the mechanism remains the same. diff --git a/doc/reference/c++/mctools/overview.rst b/doc/reference/c++/mctools/overview.rst new file mode 100644 index 00000000..669d7edb --- /dev/null +++ b/doc/reference/c++/mctools/overview.rst @@ -0,0 +1,355 @@ +.. highlight:: c + +An overview of the Monte Carlo class +------------------------------------ + +In order to have a first overview of the main features of the ``mc_generic`` +class, let's start with a concrete Monte Carlo code. We will consider maybe the +simplest problem ever: a single spin in a magnetic field :math:`h` at a +temperature :math:`1/\beta`. The Hamiltonian is simply: + +.. math:: + + \mathcal{H} = - h (n_\uparrow - n_\downarrow). + +You want to compute the magnetization of this single spin. From statistical +mechanics it is clearly just + +.. math:: + + m = \frac{\exp(\beta h) - \exp(-\beta h)}{\exp(\beta h) + \exp(-\beta h)} + + +The C++ code for this problem +***************************** + +Let's see how we can get this result from a Monte Carlo simulation. Here is +a code that would do the job. Note that we put everything in one file here, +but obviously you would usually want to cut this into pieces for clarity:: + + #include + #include + #include + + // the configuration: a spin, the inverse temperature, the external field + struct configuration { + + int spin; double beta, h; + configuration(double beta_, double h_) : spin(-1), beta(beta_), h(h_) {} + + }; + + + // a move: flip the spin + struct flip { + + configuration & config; + + flip(configuration & config_) : config(config_) {} + + double attempt() { return std::exp(-2*config.spin*config.h*config.beta); } + double accept() { config.spin *= -1; return 1.0; } + void reject() {} + + }; + + // a measurement: the magnetization + struct compute_m { + + configuration & config; + double Z, M; + + compute_m(configuration & config_) : config(config_), Z(0), M(0) {} + + void accumulate(double sign) { Z += sign; M += sign * config.spin; } + + void collect_results(boost::mpi::communicator const &c) { + + double sum_Z, sum_M; + boost::mpi::reduce(c, Z, sum_Z, std::plus(), 0); + boost::mpi::reduce(c, M, sum_M, std::plus(), 0); + + if (c.rank() == 0) { + std::cout << "Magnetization: " << sum_M / sum_Z << std::endl << std::endl; + } + + } + + }; + + int main(int argc, char* argv[]) { + + // initialize mpi + boost::mpi::environment env(argc, argv); + boost::mpi::communicator world; + + // greeting + if (world.rank() == 0) std::cout << "Isolated spin" << std::endl; + + // prepare the MC parameters + int N_Cycles = 5000000; + int Length_Cycle = 10; + int N_Warmup_Cycles = 10000; + std::string Random_Name = ""; + int Random_Seed = 374982 + world.rank() * 273894; + int Verbosity = (world.rank() == 0 ? 2 : 0); + + // construct a Monte Carlo loop + triqs::mc_tools::mc_generic SpinMC(N_Cycles, Length_Cycle, N_Warmup_Cycles, + Random_Name, Random_Seed, Verbosity); + + // parameters of the model + double beta = 0.3; + double field = 0.5; + + // construct configuration + configuration config(beta, field); + + // add moves and measures + SpinMC.add_move(flip(config), "flip move"); + SpinMC.add_measure(compute_m(config), "magnetization measure"); + + // Run and collect results + SpinMC.start(1.0, triqs::utility::clock_callback(600)); + SpinMC.collect_results(world); + + return 0; + + } + +Let's go through the different parts of this code. First we look +at ``main()``. + + +Initializing the MPI +******************** + +As you will see, the Monte Carlo class is completely MPI ready. The first two +lines of the ``main()`` just initialize the MPI environment and declare a +communicator. The default communicator is ``WORLD`` which means that all the +nodes will be involved in the calculation:: + + boost::mpi::environment env(argc, argv); + boost::mpi::communicator world; + + +Constructing the Monte Carlo simulation +*************************************** + +The lines that follow, define the parameters of the Monte +Carlo simulation and construct a Monte Carlo object +called ``SpinMC``:: + + int N_Cycles = 5000000; + int Length_Cycle = 10; + int N_Warmup_Cycles = 10000; + std::string Random_Name = ""; + int Random_Seed = 374982 + world.rank() * 273894; + int Verbosity = (world.rank() == 0 ? 2 : 0); + + triqs::mc_tools::mc_generic SpinMC(N_Cycles, Length_Cycle, N_Warmup_Cycles, + Random_Name, Random_Seed, Verbosity); + +The ``SpinMC`` is an instance of the ``mc_generic`` class. First of all, note +that you need to include the header ```` in +order to access the ``mc_generic`` class. The ``mc_generic`` class is a +template on the type of the Monte Carlo sign. Usually this will be either a +``double`` or a ``complex``. + +The first three parameters determine the length of the Monte Carlo cycles, the +number of measurements and the warmup length. The definition of these variables +has been detailed earlier in :ref:`montecarloloop`. + +The next two define the random number generator by giving its name in +``Random_Name`` (an empty string means the default generator, i.e. the Mersenne +Twister) and the random seed in ``Random_See``. As you see the seed is +different for all node with the use of ``world.rank()``. + +Finally, the last parameter sets the verbosity level. 0 means no output, 1 will +output the progress level for the current node and 2 additionally shows some +statistics about the simulation when you call ``collect_results``. As you see, +we have put ``Verbosity`` to 2 only for the master node and 0 for all the other +ones. This way the information will be printed only by the master. + +Moves and measures +****************** + +At this stage the basic structure of the Monte Carlo is in ``SpinMC``. But we +now need to tell it what moves must be tried and what measures must be made. +This is done with:: + + SpinMC.add_move(flip(config), "flip move"); + SpinMC.add_measure(compute_m(config), "magnetization measure"); + +The method ``add_move`` expects a move and a name, while +``add_measure`` expects a measure and a name. The name can be +anything, but different measures must have different names. In this example, +the move is an instance of the ``flip`` class and the measure an instance of +the ``compute_m`` class. These classes have been defined in the beginning of +the code and they have no direct connection with the ``mc_generic`` class (e.g. +they don't have inheritance links with ``mc_generic``). Actually you are +almost completely free to design these classes as you want, **as long as they +satisfy the correct concept**. + +The move concept +**************** + +Let's go back to the beginning of the code and have a look at the ``flip`` +class which proposed a flip of the spin. The class is very short. It has a +constructor which might define some class variables. But more importantly, it +has three member functions that any move **must** have: ``attempt``, ``accept`` and +``reject``:: + + struct flip { + + configuration & config; + + flip(configuration & config_) : config(config_) {} + + double attempt() { return std::exp(-2*config.spin*config.h*config.beta); } + double accept() { config.spin *= -1; return 1.0; } + void reject() {} + + }; + +The ``attempt`` method is called by the Monte Carlo loop in order to try a new +move. The Monte Carlo class doesn't care about what this trial is. All that +matters for the loop is the Metropolis ratio describing the transition to a new +proposed configuration. It is precisely this ratio that the ``attempt`` method is +expected to return: + +.. math:: + + T = \frac{P_{y,x} \rho(y)}{P_{x,y}\rho(x)} + +In our example this ratio is + +.. math:: + + T = \frac{e^{\beta h -\sigma }}{e^{\beta h \sigma}} = e^{ - 2 \beta h \sigma } + +With this ratio, the Monte Carlo loop decides wether this proposed move should +be rejected, or accepted. If the move is accepted, the Monte Carlo calls the +``accept`` method of the move, otherwise it calls the ``reject`` method. The +``accept`` method should always return 1.0 unless you want to correct the sign +only when moves are accepted for performance reasons (this rather special case +is described in the :ref:`full reference `). Note that the +return type of ``attempt`` and ``accept`` has to be the same as the template of the +Monte Carlo class. In our example, nothing has to be done if the move is +rejected. If it is accepted, the spin should be flipped. + +The measure concept +******************* + +Just in the same way, the measures are expected to satisfy a concept. +Let's look at ``compute_m``:: + + struct compute_m { + + configuration & config; + double Z, M; + + compute_m(configuration & config_) : config(config_), Z(0), M(0) {} + + void accumulate(double sign) { Z += sign; M += sign * config.spin; } + + void collect_results(boost::mpi::communicator const &c) { + + double sum_Z, sum_M; + boost::mpi::reduce(c, Z, sum_Z, std::plus(), 0); + boost::mpi::reduce(c, M, sum_M, std::plus(), 0); + + if (c.rank() == 0) { + std::cout << "Magnetization: " << sum_M / sum_Z << std::endl << std::endl; + } + + } + + }; + + +Here only two methods are expected, ``accumulate`` and ``collect_results``. +The method ``accumulate`` is called every ``Length_Cycle`` Monte Carlo loops. +It takes one argument which is the current sign in the Monte Carlo simulation. +Here, we sum the sign in ``Z`` (the partition function) and the magnetization +in ``M``. The other method ``collect_results`` is usually called just once at +the very end of the simulation, see below. It is meant to do the final +operations that are needed to have your result. Here it just needs to divide +``M`` by ``Z`` and prints the result on the screen. Note that, it takes the MPI +communicator as an argument, meaning that you can easily do MPI operations +here. This makes sense because the accumulation will have taken place +independently on all nodes and this is the good moment to gather the +information from all the nodes. This is why you see reduce operations on the +master node here. + + +Starting the Monte Carlo simulation +*********************************** + +Well, at this stage we're ready to launch our simulation. The moves +and measures have been specified, so all you need to do now is start +the simulation with:: + + SpinMC.start(1.0, triqs::utility::clock_callback(600)); + +The ``start`` method takes two arguments. The first is the sign +of the very first *configuration* of the simulation. Because the +``accept`` method only returns a ratio, this initial sign is used +to determine the sign of all generated configurations. + +The second argument is used to decide if the simulation must be stopped for +some reason before it reaches the full number of cycles ``N_cycles``. For +example, you might be running your code on a cluster that only allows for 1 +hour simulations. In that case, you would want your simulation to stop, say +after 55 minutes, even if it didn't manage to do the ``N_cycles`` cycles. + +In practice, the second argument is a ``boost::function`` which is +called at the end of every cycle. If it returns 0 the simulation goes on, if it +returns 1 the simulation stops. In this example, we used a function +``clock_callback(600)`` which starts returning 1 after 600 seconds. It is +defined in the header :file:``. This way the +simulation will last at most 10 minutes. + +Note that the simulation would end cleanly. The rest of the code can +safely gather results from the statistics that has been accumulated, even +if there have been less than ``N_cycles`` cycles. + + +End of the simulation - gathering results +***************************************** + +When the simulation is over, it is time to gather the results. This is done by +calling:: + + SpinMC.collect_results(world); + +In practice this method goes through all the measurements that have been added +to the simulation and calls their ``collect_results`` member. As described +above, this does the final computations needed to get the result you are +interested in. It usually also saves or prints these results. + + +Writing your own Monte Carlo simulation +*************************************** + +I hope that this simple example gave you an idea about how to use the +``mc_generic`` class. In the next chapter we will address some more advanced +issues, but you should already be able to implement a Monte Carlo simulation of +your own. Maybe the only point that we haven't addressed and which is useful, +is how to generate random numbers. Actually, as soon as you have generated an +instance of a ``mc_generic`` class, like ``SpinMC`` above, you automatically +have an acces to a random number generator with:: + + triqs::mc_tools::random_generator RNG = SpinMC.RandomGenerator; + +``RNG`` is an instance of a ``random_generator``. If you want to +generate a ``double`` number on the interval :math:`[0,1[`, you just have to +call ``RNG()``. By providing an argument to ``RNG`` you can generate integer +and real numbers on different intervals. This is described in detail in the +section :ref:`Random number generator `. + +That's it! Why don't you try to write your own Monte Carlo describing an +:ref:`Ising chain in a field `! You will find the solution +in :ref:`this section `. + + diff --git a/doc/reference/c++/mctools/random.rst b/doc/reference/c++/mctools/random.rst new file mode 100644 index 00000000..638bdd18 --- /dev/null +++ b/doc/reference/c++/mctools/random.rst @@ -0,0 +1,96 @@ +.. highlight:: c + +.. _random: + +Random number generator +----------------------- + +Generic use +*********** + +TRIQS comes with a set of random number generators implemented in the class +``random_generator``. Here's an example illustrating the +use of the generator:: + + #include + #include + + int main() { + + // Construct a random number generator + triqs::mc_tools::random_generator RNG("mt19937", 23432); + + // Generate double numbers in [0,1[ + for (size_t i = 0; i < 100; i++) std::cout << RNG() << " "; + std::cout << std::endl << std::endl; + + // Generate double numbers in [0,5[ + for (size_t i = 0; i < 100; i++) std::cout << RNG(5.0) << " "; + std::cout << std::endl << std::endl; + + // Generate int numbers in [0,5[ + for (size_t i = 0; i < 100; i++) std::cout << RNG(5) << " "; + std::cout << std::endl << std::endl; + + return 0; + + } + +After having included the header +:file:`` one constructs a +random generator with:: + + triqs::mc_tools::random_generator RNG("mt19937", 23432); + +The first argument is a string which allows you to select the generator. Here +mt19937 stands for a version of a Mersenne Twister. The second argument is +the random seed. + +Now that you have an instance of a generator ``RNG``, you can generate +either ``double`` numbers or ``int`` numbers. If ``RNG()`` is just called +with parenthesis, it produces numbers uniformly distributed on the +interval :math:`[0,1[`. If there is a ``double`` argument ``D``, then +numbers are produced uniformly on :math:`[0,D]`. Finally, if there is +a ``int`` argument ``I``, integer numbers are generated on :math:`[0,I[`. + + +Getting a list of random number generators +****************************************** + +In order to have a list of all the strings describing the available random +generators, you can call the static method ``random_generator_names``. For +example:: + + #include + #include + + int main() { + + std::cout << "A list of all random generators" << std::endl << std::endl; + std::cout << triqs::mc_tools::random_generator::random_generator_names() << std::endl; + + return 0; + + } + + +Accessing the random number generator from the Monte Carlo class +**************************************************************** + +When you construct an instance of a Monte Carlo class ``mc_generic``, this +instance automatically has an access to a random number generator. +Imagine you constructed an instance:: + + triqs::mc_tools::mc_generic SpinMC(N_Cycles, Length_Cycle, N_Warmup_Cycles, + Random_Name, Random_Seed, Verbosity); + +Now, you can use ``SpinMC`` to have a random number generator:: + + triqs::mc_tools::random_generator RNG = SpinMC.RandomGenerator; + +Typically, this generator will be passed as a argument to your +implementation of a move:: + + SpinMC.add_move(mymove(config, SpinMC.RandomGenerator, ...), "my move") + + diff --git a/doc/reference/c++/mctools/reference.rst b/doc/reference/c++/mctools/reference.rst new file mode 100644 index 00000000..9f3b1d85 --- /dev/null +++ b/doc/reference/c++/mctools/reference.rst @@ -0,0 +1,82 @@ +.. _montecarloref: + + +Full reference +-------------- + +Introduction & Motivations +************************** + +* **Purpose** : + + The purpose of this little class is too facilitate the writing and maintenance + of Metropolis MonteCarlo algorithms, with several **advantages** : + + * Easy to add new moves and measures. + * For complex MC algorithms, with 6 or 7 different moves, it helps to clearly separate the code for each move. + * Parallelism is automatic. + * The random generator is a simple parameter, it can be chosen dynamically. + +* **Principle** + + The `mc_generic` class is a generic version of the algorithms, with `moves` and `measures`. + The user : + + - writes move classes, modelling the Move concept. + - writes measure classes, modelling the Measure concepts. + - register them in a mc_generic object MC + - call `MC.start(...)` ... and that is (almost) it ! + + + +The Move concept +**************** + + ========================== ============================================================================================= + Elements Comment + ========================== ============================================================================================= + * mc_sign_type attempt() - First part of the Move. + - Returns the probability to accept the move. If : + - the move is :math:`x\rightarrow x'`, proposed with proba :math:`T_{x\rightarrow x'}` + - the probability of the :math:`x` config is denoted :math:`p_x` + - then attempt should return the Metropolis ratio: + + .. math:: + \frac{p_{x'} T_{x'\rightarrow x}}{p_x T_{x\rightarrow x'}} + + with the sign. (The sign will be separated from the absolute value and kept by the MonteCarlo class). + In other words: attempt() = move_sign * move_rate with abs(move_sign) = 1 + * mc_sign_type accept() - Called iif the Move is accepted. + - Returns a number r such that :math:`|r| =1` + - There is a possibility to update the sign + here as well, so that the final sign is: move_sign * accept() + - CAREFUL that we need the ratio new_sign / old_sign here just like + we needed a ratio in attempt() + * void reject() - Called iif the Move is rejected (for cleaning). + ========================== ============================================================================================= + + +The Measure concept +******************* + + + ========================================================================== ============================================================ + Elements Comment + ========================================================================== ============================================================ + * void accumulate(std::complex sign) - Accumulation with the sign + * void collect_results ( boost::mpi::communicator const & c) - Collects the results over the communicator, and finalize + the calculation (compute average, error). + ========================================================================== ============================================================ + +Doxygen documentation +********************* + +The :doxy:`full C++ documentation` is available here. + +.. : + Breathe Documentation + ********************* + .. doxygenclass:: triqs::mc_tools::mc_generic + :project: doxy + :members: + diff --git a/doc/reference/c++/parameters/CMakeLists.txt b/doc/reference/c++/parameters/CMakeLists.txt new file mode 100644 index 00000000..127842d6 --- /dev/null +++ b/doc/reference/c++/parameters/CMakeLists.txt @@ -0,0 +1,3 @@ +# Doxygen sources +set_property(GLOBAL APPEND PROPERTY DOXYGEN_SOURCES ${TRIQS_SOURCE_DIR}/triqs/parameters/parameters.hpp ${TRIQS_SOURCE_DIR}/triqs/parameters/defaults.hpp) + diff --git a/doc/reference/c++/parameters/parameters.rst b/doc/reference/c++/parameters/parameters.rst new file mode 100644 index 00000000..a63d6d44 --- /dev/null +++ b/doc/reference/c++/parameters/parameters.rst @@ -0,0 +1,191 @@ +parameters +=============== + +Introduction +-------------- + +The purpose of the class parameters is to handle program input parameters. +It provides a convenient way to pass several parameters of different types to a program. + +Parameters can be stored in a parameters object and accessed in a manner which is reminiscent of a Python dict: + +.. code-block:: c + + parameters P; + P["x"] = 3.14; + y = P["x"]; + +In Python the syntax is similar: + +.. code-block:: python + + import parameters as params + + P = params.Parameters() + P['x'] = 3.14 + y = P['x'] + +The class implements the following features: + +* storage of parameters of any type, including arrays +* C-like cast operations, such as integral type to double conversion as well as lexical cast to arithmetic types +* Python interface +* type checking +* hdf5 I/O operations +* write contents to std::ostream +* the class is boost-serializable + +parameter_defaults +----------------------------- + +When parameters are used within a program, a number of them are usually optional, in +the sense that they need not be provided by the user. This either means that the program +can run without them, or meaningful default values can be provided. + +Other parameters, on the other hand, may be required to be provided by the user. +These typically are parameters for which one cannot provide meaningful default values. + +These cases can be handled in a consistent manner using the parameter_defaults class. + +An object of this class allows to specify the name, type and documentation for all +required and optional parameters. Default values are provided for optional parameters: + +.. code-block:: c + + parameter_defaults pdef; + pdef.required + ( "Beta", double(), "Inverse temperature") + ; + + pdef.optional + ( "N_time", int(100), "Number of time points") + ( "N_freq", int(200), "Number of frequencies") + ; + +The default_parameters object serves two main purposes: Firstly, the input parameters can +be checked for completeness and correctness, i.e. they can be checked if all required parameters +are provided and have correct type. + +Secondly, the optional parameters provided through the input parameters can be checked whether they +have correct type. Those which are not provided can be added to the input parameter set with +their respective default values. +Both steps are performed through the update method of the parameter class: + +.. code-block:: c + + parameters P; + P["Beta"] = 3.14; + P.update(pdef); + +Given that the parameter_defaults are complete, the resulting parameter object contains all +parameters that the program will eventually access. + +Finally, the information stored in the defaults can be used to generate the help of the program, +by printing a list of its parameters: + +.. code-block:: c + + std::cout<` and +the :doxy:`parameter_defaults documentation` are available here. + +Parameter example +------------- + +.. compileblock:: c + + #include + using triqs::utility::parameters; + #include + + int main() { + + parameters P; + + P["a"] = long(1); + P["d"] = 2.7; + P["a_string"] = std::string("-14.3"); + P["char_string"] = "-14.3"; + + triqs::arrays::array A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2; + P["A"] = A; + std::cout << "A:"<< P["A"] << std::endl; + + long a = P["a"]; + double x = P["a"]; // cast to double from long + double y = P["a_string"]; // lexical cast to double from string + std::cout< + #include + using namespace triqs::utility; + + int main() { + + parameters P; + P["Beta"] = 3.14; + + parameter_defaults pdef; + pdef.required + ( "Beta", double(), "Inverse temperature") + ; + pdef.optional + ( "Alpha", int(1000), "An integer") + ( "Gamma", double(0.9), "A double") + ; + + std::cout< + + ... + if (!condition) TRIQS_RUNTIME_ERROR <<" The value of a = "< + + try { + ... + if (!condition) TRIQS_RUNTIME_ERROR <<" The value of a = "< v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = '@TRIQS_SOURCE_DIR@/Doc/misc/python-powered-w-200x80.png' + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +#html_static_path = ['@TRIQS_SOURCE_DIR@/doc/user_manual/.static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +html_additional_pages = { 'index':'index.html' } + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, the reST sources are included in the HTML build as _sources/. +#html_copy_source = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'TRIQSdoc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +latex_documents = [ + ('contents', 'TRIQS.tex', ur'TRIQS Documentation', + ur'2011, The TRIQS collaboration', 'manual'), + ] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True diff --git a/doc/reference/python/contents.rst b/doc/reference/python/contents.rst new file mode 100644 index 00000000..57289b29 --- /dev/null +++ b/doc/reference/python/contents.rst @@ -0,0 +1,23 @@ + +.. role:: red + +.. index:: contents + +.. _contents: + +Reference: Python libraries +================================ + +.. toctree:: + :maxdepth: 2 + + introduction/introduction + install/install + green/green + lattice/lattice + data_analysis/contents + solvers/solvers + wien2k/wien2k + faq/faq + collaboration/collaboration + legal/legal diff --git a/doc/reference/python/data_analysis/contents.rst b/doc/reference/python/data_analysis/contents.rst new file mode 100644 index 00000000..78b7935a --- /dev/null +++ b/doc/reference/python/data_analysis/contents.rst @@ -0,0 +1,26 @@ + +.. index:: analysis + +.. _data_analysis: + + +Data analysis +################################### + + +Python is a very powerful tool to manage data, plot them, fit them. +Since all TRIQS basic objects are pythonic, and have the correct interface to be plotted e.g., +scripting the data analysis and the production of figures is easy, with the help +of the standard scientific python libraries +`numpy `_, +`scipy `_ and +`matplotlib `_. + +.. toctree:: + :maxdepth: 2 + + hdf5/contents + plotting/plotting + fit/fit + provenance + diff --git a/doc/reference/python/data_analysis/fit/demo1.py b/doc/reference/python/data_analysis/fit/demo1.py new file mode 100644 index 00000000..3eebcb9b --- /dev/null +++ b/doc/reference/python/data_analysis/fit/demo1.py @@ -0,0 +1,47 @@ +from pytriqs.plot.mpl_interface import oplot +from pytriqs.fit.fit import Fit, linear, quadratic +from pytriqs.gf.local import * +from pytriqs.gf.local.descriptors import iOmega_n +g = GfImFreq(indices = [1], beta = 300, n_points = 1000, name = "g") +g <<= inverse( iOmega_n + 0.5 ) + +print " van plot" +oplot (g, '-o', x_window = (0,3) ) + +print "plot done" +g<<= inverse( iOmega_n + 0.5 ) + +print "ok ----------------------" + + +from pytriqs.archive import HDFArchive +R = HDFArchive('myfile.h5', 'r') + +for n, calculation in R.items() : + #g = calculation['g'] + g <<= inverse( iOmega_n + 0.5 ) + + print "pokokook" + + X,Y = g.x_data_view (x_window = (0,0.2), flatten_y = True ) + + #fitl = Fit ( X,Y.imag, linear ) + g <<= inverse( iOmega_n + 0.5 ) + + print " van plot" + oplot (g, '-o', x_window = (0,3) ) + g <<= inverse( iOmega_n + 0.5 ) + + print g + g <<= inverse( iOmega_n + 0.5 ) + break + ginv = inverse( g ) + print ginv + sigma = iOmega_n - g + #oplot (ginv, '-o', x_window = (0,3) ) + + #break + oplot (sigma, '-o', x_window = (0,3) ) + #oplot (fitl , '-x', x_window = (0,0.5) ) + + #print n, fitl.param[0] diff --git a/doc/reference/python/data_analysis/fit/demo1_prepare.py b/doc/reference/python/data_analysis/fit/demo1_prepare.py new file mode 100644 index 00000000..925a551e --- /dev/null +++ b/doc/reference/python/data_analysis/fit/demo1_prepare.py @@ -0,0 +1,14 @@ +import numpy as np +from pytriqs.plot.mpl_interface import oplot +from pytriqs.gf.local import * +from pytriqs.gf.local.descriptors import iOmega_n +g = GfImFreq(indices = [1], beta = 300, n_points = 1000, name = "g") + +from pytriqs.archive import HDFArchive +R = HDFArchive('myfile.h5', 'w') + +for n, Z0 in enumerate( np.arange (1,0, -0.1) ) : + g <<= inverse( iOmega_n + 0.5 - iOmega_n * ( 1 - 1/Z0) ) # / (1 + 4*iOmega_n*iOmega_n) ) + g.name = "Z = %s"%Z0 + R[ str(n) ] = { 'Z0' : Z0, 'g' : g} + diff --git a/doc/reference/python/data_analysis/fit/fit.png b/doc/reference/python/data_analysis/fit/fit.png new file mode 100644 index 0000000000000000000000000000000000000000..f90629d4975886ab1750651db4979984668f5f81 GIT binary patch literal 66792 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

n?qk&eMZ1A`pNo^J?jd}yYC;WH< z`9- zX(ey)O1llOVRti~PTnLF4LQs|iaxDeWp3v2WtZ(8Ob@UGM2*O?sM0Mb?{+KA737O@0 zXSPG64?wgn5n20Nz8p(f>xb&}*jo;vnFAeXyJb_$P49ZXfK`#DW|J%~R;Xr!b-9?C zK}+gv%TXD;=0*MX*fY@iOeH3n^z!~V5FW~GAxtUYn`2})b+23N&rzWuK*Srd&HZI$ z{L2xJ6F7l}Z~w$0_D*?dwlE zqs-tGW%8BY7Z7%;mPFk{m6!}eE46?V1yHPXf>U7X0IZT4NwcO2` zza^Ek3aE5FWw_YL6OUd)`vc} zpbPRoLictXtdTeslz0Cf$6p67TU;2F9@bxSBZ~0SuSuFt*9aIw{w0GwN|WQ`d;8A? zPpmB2F}iHYK^1FZ%OKef_rZY}nSxp$O6ee6(Px98^YWF2(t87tiAP@!0zt{EsUb(o z^rjtpL|2zI!`)UgXA!@eKaN4Gfy~y%VU*47*Z5B2z}=q_wIzb`zK`_Gs~Jk(FmVPN zz2M*6ZN_X8i83%$dJ}vEDY-oXA?S@IJHVfk_bBMp#w7v5U;1AASfit(ttaIb|A=uW zeAVO%w}r%fSW3lr#9fp9*1{DA68lFvPi0{0Q-$X zxa1kk?VU!&dJO+WKAV(JMAptA3m@WM(*F*M*<68CgrevR6dCb-dj|Z57tHR510nEi z#gTU8TFf~nvzg6z$hs}G`1kc}LoA0#dT&drA2yuru@_a>XO;2g-3FGA)uYyCi_u-T zGosWz|IY0ErWZa&WM`9E9=-O$ z6>DTopZe0JrH#7^n+bOA=TmHWhEsS6FfC6Me!M(p1>ZnYK{)*0_Z%`0@^;Q`NzY z!DXcvk^Ehz9H^5O3-LR6z;BqL7j3A-Th173Th$}B#(_hEX|+;wD?OWHl9h57xrk$z z`C1nan#H!OPVG*oJsgg9zffGJj_zbAdUdx%?&7rm?;Xqv9Fz!>Qi+@y3zS&RAF=iI z*lR{(f!Ymg?A(tNjPCY`{gm#(F7El##yit&tb85D024N!RNi(zj0$-mfCcRo6re=G zGEu&^WI<;w9OEauAgU{~?G2w9?YJ5dLkwCfvJ5`&(>^;>)97^66rt(UnH-58!BZ+G z1DiK71kYr6PxK-57PvGyMh`7mhychLy$FmquL8~LZY}0QWRBl=p0%a^!Ii*wkfk7f z1^py=_OX*LgQp$duXYFly{9duoiLWOQ0KKUFAK|p(PUwy z@=LkOM3sB~22cBI#(An)lRF1(`PP3}B42$zU0>r)78+W(`@ZYU%F4`zbAR|V4p$Ay z8PN);`F?s}a+b7bh>C{=!>&I-!XB%n%;- z7Hcp$DqFVDkRetUs)Tjl;`i{W2U7wOB=fq?>4Y)9C(Au2>6iwuQx=;kLq2kDc@j!5 z;O!Vy1)+80?ypWeR$H9HQ7UwL_}aW{!*xkOsSiHqCjtHYTY( zy2T&R6L0F3lu+elX6Er{99oYDlNH8q*Za91dxhQTWSZ3a!pW|G#_Jv(E zp!!Ubw6@!zYV#R)i%^%{qd#VAceA-WM{Ni&f& z_v5w<6e5W%r(`ca1uqPDY*%8F5BKcm#SV1?&{`>D-!9`D^Wv!;T^<=Um7_MiM$at_W*vYzerJNaH-nwA9sa?A%kT@+6-m55H!3@n*Vc)6Dtaz@d{^%Q zYumfz?CgR|B5FdP()<6J3joa62MA4{s+ndiA2f2r!U{gq)Wc+e0jdGPj&&crLL#N+if%&7LBKZ?skkgUvWX7A^hqaNge%d*Cwlb;rYsDWvZk@%_c1_2z z7LsQ^EuL`ekcC4rCus718IeLz8=X_-_vD<@b7|g9q~r$NKc5%dWjz0AI_cZl{UjyA zP+x^NrgdfN5zyC*&a|=7{_q^S$X)p4m`(G*`?Nc`ymCYO)jW|Qsd25m8~;?%tMoA( z{RF3?hv&!7m56Tm(9|$;PW{==96VuZ`(!v80m@n#l^V#$rku`J7gdaWvqg7b2tn9u zx^CR}FqVYM&0ehQ>bIPbPb#H%KPpUD+jUb6ZBA5CRu(4^Ml3>-SJ=C%I-trZC_g%< zI_m+-#({d74RiLO*dzin0F+lu2G#biSEuSf*EwJkb&uxs`uFvAr&x7Iuy*H2;E|x` zO2a=Va3#F^M(IaYuS^L71RHJE!Y%eMEw^SdMMGNztYC-SoAKPS?h{AvMFj9~4#q+S z=7X+EIGs?+J6Cn7uA#%iWWQgagjcM6uv!v3+fB!=i5n!3uWKc!g=XQ1u6KRu zSYz3C3Aw9%AQ`Djms%LPKaeD3 zf<`VRh&cFKwwSLko7+rDPAmBw0**S3zA?^MaItHOMvH4`d{f1Z^H?8SarEy1<*%04 z*0gu)LD^?E%c10stM7{CRgC@6k-z~IU0o^p$+7%iUo$h=bk2}B6hfqzy>p%iGhb#i zZnowW^}P5}rsgA?YTsAnez^CDJ$YB#uuG!JL*?`U_8T{vf_sbae$R;>QXpGyv3F$& zWXU^dwx6TtMR$v1cNF{Hjxa5(_9UPmt8t4gmp@J&W7WVoJiwJ9og6ZMgW+>0yAe6O z`1*T&SDAKKE%Tl__xld?`tST@>IRG3;MByP*9GOZFJVs~5(OI~g$DV{9cdyRL&C1u zfZ0mdX9Wk8dGbr9umcQY5T_HOF+`A^CfFhzkid4J`X4CLS++5++)R&l<^QPpUdew5=kCrJquS=(Y<) zo^Wpm6x+SJKwWa|_Jns3kfGO!b+yknDyLJn8e*AAlmv-qT(q{M^?C;hP2J-%)_Asr zym&Or=B_faTpG~$XtUP7iK-oQ^vkPRm-mo_PNl}KzSkyJDW2PHU%*z`zwOU2eBmBQ z!g%9Fa>IW}u5C~gdt+|NA;c8v=;D%G<1Z5Oc@SxjE3JwBNvIntDpR?QLCK>9$lp;2 z)VlC1L;r|O(>L#^DK=!;-_QF21Av7i4pHC4Z19Zv!hB_)J*93bjpRZ_wOe}r!58K! z!Wj<&Y5AMWP?F0X@m7UxuV%RUP!{ti2F~>Eokf*%0xV<~lQR=1UXWwAg)D$KKiC*a za?tseWQ$Jfce2Q6GU~?^_-Qk@zNn_BE^hQE;}ITizUhUG#%0zn7R4u7P zPb%-%Qy*{sHzDw~tf`Wq9@rUO&+}s`*rQ$TVQ&3qXIj}8FEk)8Bf>pdn4{KLRut~x zSV~@+DJV9*wNO=c+7<#30r+COEatvy_X}}KewERo^$)qye%OFT`(|yu24&c^C%k7~ zE!aC@g`8<6^L_aqwDLRrKE3zrE9=mXn4fat=)CwCB8L_w6Y)sCf7W;AQ@A&0*c{ol zP8_;2qOD#W%%VxG|A30WCVCpnx^G@Iu8U8xQLh>`(->!77{64!cYkr^ZO5nXmtVhf zRYd8PBWz~AI_9MFLqfvdOd%i0^25W8q@U&-aiA>iRPnryw(SvJ8*uwDS>OC|**kn* zOf8=zE)(jUwLVVGm-3d#pl7t$D>;~1cZz}T>-<#G3mmj-Ld>U14ED1#_o{VdSf6nQ zg?5OjtE+9GCim*Sy-8YaVvcsaS8b744nOOolC!B+$$3Rl@m^Ko zE$n=`9vc%OkWAgmFY>;P3!uc*zI)&>-JX#|OOx!e0NFJ+SGijYh32LeGQ1@qK=6TA zQa85=c{P{-?5OkP2C$<@P^eKrx}<3_BhrLs?6}gMwBhfeZVLhIm>hmE`%?&QZ2&ub zROVF1jo)j(6RCY`Dh8~x!~Ol7+)v_`x+E_nBKA4b&e%BP<#`-_4b|I&1;zIv-?k`= z65M=Xj*rJ&$XBunWoQ(}=lJ>cI7~}5CJ}*c9*GUCVN4#o1(AUP{l(pp%A-v$PTD&} zqr*1&4?Klwf*j9JtZd{kL={^!i^tJLiwX<7Z*~3^NC>Ij_!899+x_9iXnuq$YL%YJ z=lADX73Ikq{%4L@g&{g+$pMdE2YGfVQ^ICv_MlL>DuJZnu%+-TJV`0Lnf^nzW!LUt zv0pl9?}EGTMDDS1(Y@Wz5P&WQV=Me@ipNNbz(z$Cta79zjCXF70jZz(65={P8+Pw^ z<(_xo*F8`H`lp14;Dc04OkBLvl)YQplHSvk_<(vMDGdtyw7p$$5FH z#XUyokKJ}(o-C_~h?FbKEnO9JH7D84$bk5q6{yZUJly~-DvdlsMa_HvenE>skjavB zS-_(pszo68&KvEy_iY0^TGIscon;VnEf$Sk6DN>#~gHC=l!z`%XAUIn}|56K?*ZS$(3N~RjlGWH*? zgJRQ8YZ;^U%FHdrEzf$1wCUa3=JCtv}tL%HmSj&mn9;HK95NzmQgDA z=UvQ`U06fY)g7%XapqlA)e_qfI#j(I_cbu^p_axdd>r4Ahi9q9ovzc=MA1)}K0d6C zj_xr5K@~k~%;vjy_nbV|%72-AdwDs-C(B&HClJX%lapgZnsS^CZy4yQ1FDglH4?pK zIyU$@vP^$vrRTdHMH9p6`(yp%%R;M83t@R{0x|GzT zL&dWe#zq^HjtnUFx>sEjRoCiYjiI)?7()}Nw&3o_-8PDK9J;l$iER8E*AlfE>`!c(T#G zWzn)#jF|Y`Dkxs6CG1$K*Wj?AvWJJrE|Ni#Ow|UrSnnRNrBTx^J8Fw<_?Fxi%WM7& zL72HSRaLOK^&M--@5_MSQYgrpNWFT3n_s}eN)u!?KK8_|$*Ea?NJ+kg=y~y)L^=!6 zNM1fWHE%K)Ca{6XGixCXiW*4TSe?=#c+7_90?je&GgCwTSmNN8V?y=OCsD?Ys;N-| z?PpU9^!2b5O!M^AQS-FOaCVyQRpjqcBwz^clk=;f&-`rSjL6Nk6_3#?MXVI_e5j~i zY`k}ctBs9)zl{8AdDgcdX!iaf$D=2*aN#fuhC{`!%Qv7eK(1 zFdsQ~hZZ&BWV^>ht;0w_Y9{RhSu%jOgbJU&GYA#bm4EY=L^C$w*`~Hw@pMCU)kZen z`6J2^>!}@&4&iU(2Rt2Gw;U7_GFg+5rlCH40x2ONi#FrO1j5qL3`-+P>P7b!Q;`dh zmg)HU^}z^1b4kh6Oytm7vM5b497^t0Q4LgZCUD=H0Ay2ISeF7lFfU!TAD7YuvvNNU zKOHn>0!@L&?m0(}+_sG?D1^{3k2nqoy-xrbU&U02&KTH$hI^5g1esfkx48HAt!1hc zAUgYnk`EfIn`z>uVKXvzj;sG8{2mZi0EEZJL6yPk>c3p@i9HRF8JqwULbd1K1D=z++or~$(5Rzlm0s#gtAB=5il&Q zZZX$;b@_ZVD$v!#qw&O$SV-?*0|i6_cJ|nGeg6g6hQ{*o9~U!<$Imdw#{NxU&aL)b zzu(X*ZN9T+ZQXlD#X{ui1J6(D2KSFw8+QSdfKB(}fc~(Li%4%9<}e5dD(xS=dGn1z zrRX1*;Glz{Ah^VQ8&&nYYpBjhP zHU3cnv0Z#4KqbS2l-m5nK@)M#C#gpaLUQ}y=v?1D#hHU&R5k9ezA=Xa1;PQu;~8F0 z*pTV`rvxCMs7wM7p-Uo$|Aw5M75`-%;q`bw*FxRj5A?nGH)7O4Gmc*AppvkEIEIGc ze8jj_C*&sqGMi)IbgbSUoQ~bY(fZ3>3ed96F&%=Q6%L2NFaQ1GIGA(m2epp4BqXCB z;Zsv}zJg<5sQn|3=<^#;dy)B~AaipvT~u^j z?R&TLg^XYvh~Ih*{;U+6hDk0ksU=pR%p+W(#RM9}ErS$oy$V2cT#55%1q6qTtr$4w zj}|4$bP(bwf~-xw2B3GK_G)cEFK%AZz1Fr{xAX7Z{b~erH(6#v@c1zb*y6QH4_){6 z0&1UQ=S6_|etsV;>MP(ZQuxo@qk;?!IKi?14(Q)+HV~|Y5E;E0h>s#HefPkOYjK9b0WjinQN}2v8s{t=`j0L!f$1}#J2GJ`L&JX!(J-iJfK{~PHsf+k>&;EccCP*j(cMWBGpt zzI=fY_+xp{b246BY%T|71-s}HgfZt^w8l)7F)J>iibBVppub%J9Wn%ntqPbn4)Ckn zC2S7pA|81IKybuECLa713h{`e2N|@t4@D`Y+cuJ^k;u1gLZ6eM{yz}v8)%sKlUGo{ z0==J}p5i@t&<%iL20#Ei?PBbfgVZSGe&;`9@~l<97w$Wa%Q(W9dlEbC7Y=G_YP_4J zHJ~QH8`LQCR*o7c#~sX9WdIaSqEIQr=2{qb>g3RIyK5+g^9-QSr|ob2B^$y> z)h9cKl0*WY*mrY0X?91Z(Ey&aQbail!-Prbd!c$Ad$ zL)y33#z4|aba%DIAY0n7^pO=PTplGX1%nAv`X1h|u^a|%K7?fj-ZD3sO?{Y)M?mnY zq@vwh<79g*fAD^T(B&Q+fYii;g6x_Z3W!<;w2%3Et<`sr@gySZ`cMrBsL?P`;|ff>HG|F?8`)FYi7+texx zGtMk-#aQCSL|iVqLe7F5CABHSZ2RQ6e=U4Tt zu&aQ1gSEx6e28|?@#WE!5kGWQA$zb>Xf!J`V(w7?u)r!;L`Z$`W*mS>5G=@fvknrQ zAse7v*MVYD!&xFCqZSYdBpbiQV|Nn3%OD#_RrEl{UVodK+T2@&het0B{}RgvBb323|p03m)QgvYippFZV>omMJaJ$m%0&UIZaii}S!Cnx7~f4|C$7jK6NMD#DWN5H-Eic8Z^-)|EW zd@5(J%W`tW29sE|ZET9gB_zN%zua4Vg_Yg6CK9e=$$iNATqH3GnN;-k(}RM74!@}@ zTlYqi2zSIk_)(>-?JeQ3<+d}!2Vf8sK~Zy3UZ?C}9P(m-75ZucF6_GS>*s|3TMPikU}wqpY-bOQtIue3szSx6*C2O zS5{VVG;bCT8bp}gfnx-IuNAYfV4POsw>L30WeZ@gnxSjamS57J%2qQC7S@>e`5CM$ zV^*8RTwcPiE)PcZnq5E2$;lng`RslyD3AgGRHN(Tg#v=|2-)Upsd$bX{jQp6Xld*G zuDrgp2_^=30tB? z3IJE%)dTYt77@WoLPEl=aj~~9=MNyLOqd2a2nYzcweFckeyphANwgqonBE@ut6na> z*v9=)H8lbLHCf8_{CP4%7HkZV%!LC13=P(?o6sYP3_ZI5x`#(&$joVo02Mbdgh_XC z$cg|UYlEIqrEwsOVQUeqM{Zb8MJ3kM)Ko)VeSA^3+N`4dumH8mc@jjW1lr(|4wrC< zY3{~`4X|?cX9_VrJ(98;duU2-ZgsuUPj)M+%=&CV$PHNXSg<3E zFOs+{XSD~iK(<@viCnvNt*x!)Mgb?enPzbD-R9@!~BfFN!KCu~dAzR-O*l?eRhcz7> z$^p&{|E#imI<%wB8n%E#{wd2K2PcOALlI2)~xHee*keqzBtWG$xc`VC^y|;gbMk`R#-J79$ zyluvz0U*0DG)$MB%=^z5a+>#%Tpz9)_D8k##!yx?H}e}bIxS}U^hf!hYTM?bViNua z;24ZdOo!zpX0^6cEOd__znW=uCeLhxomB&HwN--_-;4U=o!OGeNUU8b=3)mz=81_3 ze!t5`KyrRIe@XaOY}X0^%O>j3@DfP$d0=4wjO<5M)~(o8M!LEw=f~UNcui^sirciW z4w*YY$>9LD7yscyb8g2uJAnA|h|^<7f4ss-L|sj7X|@Ka!gzzD(ZOa#hxe2qMU1SR z9EY;t{+l1oZY5{un-z+BdZ}KAU!@hjyu7H|-=n?jxJu!7D;^jg=E~2{Uj@jBtK-Td zT#Ji~0HCpPLiltS;FlE?74_TAx6kS%T38OJT7dmdK~*)b$?KqiJ$MTRkf0Vg{@Li9 zTg5b(S6G<#=a0()99N{)yOv7e3&8OPqX?o5!@xsOFfqwF11Mj^+D5(>mLr+=z)k?O zv$sRbGYj%PviNS55gu<_u1k2z#XM;^I=`cex8+aq&8dBVTjN=lRuZDB!-u7EiCp0rrpr z|C?*z1$5^X6r=(e*@mCe4$UzZSXnlAz*f{*AYL^BfuJzTN{VTawBAJl*8lHvv6W$#e8PQf$ zjA}n!!hBSM3^}C7qJluOG&D8WzkO8KYxS%eu>#wMxo)C9i{C8RT0c3WKmwG7uTRbF z=USU)ZMDnw3ym23ql9Xf%fIwOiGG_3*ZzTgzn2DV_U?o6Kn>;%^`?g_4Y3Vlr53|jL3mJ_- zH0IY-Rn5uE%X6vWCUyz9W$Ubwotstvnn)N=rm zCz^l;ak_WgFHjMkG-WB)Cr?yhu+~ifYp;pP$lcDNmH=_;l^ zA82tu*)iCjYkLVW*5V%{rp5RC5M3h-0!c$SgJjU99&|1qo`&W-W8c3QJ>qeALPz%k zF_(Zi(;$X%0t6zkPl^W?q2JAwM}A)36DFpi7VcN0RAq*3dWby=_;bMC6Ln%BLEM+^ wJ&_=Ym0D0I6*(G5`Po literal 0 HcmV?d00001 diff --git a/doc/reference/python/data_analysis/fit/fit.rst b/doc/reference/python/data_analysis/fit/fit.rst new file mode 100644 index 00000000..99097b90 --- /dev/null +++ b/doc/reference/python/data_analysis/fit/fit.rst @@ -0,0 +1,48 @@ + +.. module:: pytriqs.fit.fit + +Fitting data +==================== + +A simple example +^^^^^^^^^^^^^^^^^^^^^ + +Let us for example fit the Green function : + + +.. plot:: reference/python/data_analysis/fit/fit_test.py + :include-source: + :scale: 70 + +Note that `x_window` appears in the `x_data_view` method to clip the data on a given window +and in the plot function, to clip the plot itself. + +A more complex example +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To illustrate the use of python in a more complex situation, +let us demonstrate a simple data analysis. +This does not show any more TRIQS object, it is just a little exercise in python... + +Imagine that we have 10 Green function coming from a calculation in a hdf5 file. +For the need of the demonstration, we will create them "manually" here, but it is just to make life easier. + + + +Reference +^^^^^^^^^^^^^^^ + +The Fit class is very simple and is provided for convenience, but the reader +is encouraged to read it and adapt it (it is simply a call to scipy.leastsq). + +.. autoclass:: pytriqs.fit.Fit + :members: + + +Example of fitfunc:: + + linear = lambda X, a,b : a * X + b, r"$%f x + %f$" , (1,1) + quadratic = lambda X, a,b,c : (a * X + b)*Omega + c, r"$%f x^2 + %f x + %f$" , (0,1,1) + + + diff --git a/doc/reference/python/data_analysis/fit/fit_test.py b/doc/reference/python/data_analysis/fit/fit_test.py new file mode 100644 index 00000000..248c6fa8 --- /dev/null +++ b/doc/reference/python/data_analysis/fit/fit_test.py @@ -0,0 +1,26 @@ +from pytriqs.plot.mpl_interface import oplot +from pytriqs.gf.local import GfImFreq, Omega, inverse + +g = GfImFreq(indices = [0], beta = 300, n_points = 1000, name = "g") +g <<= inverse( Omega + 0.5 ) + +# the data we want to fit... +# The green function for omega \in [0,0.2] +X,Y = g.x_data_view (x_window = (0,0.2), flatten_y = True ) + +from pytriqs.fit import Fit, linear, quadratic + +fitl = Fit ( X,Y.imag, linear ) +fitq = Fit ( X,Y.imag, quadratic ) + +oplot (g, '-o', x_window = (0,5) ) +oplot (fitl , '-x', x_window = (0,0.5) ) +oplot (fitq , '-x', x_window = (0,1) ) + +# a bit more complex, we want to fit with a one fermion level .... +# Cf the definition of linear and quadratic in the lib +one_fermion_level = lambda X, a,b : 1/(a * X *1j + b), r"${1}/(%f x + %f)$" , (1,1) + +fit1 = Fit ( X,Y, one_fermion_level ) +oplot (fit1 , '-x', x_window = (0,3) ) + diff --git a/doc/reference/python/data_analysis/hdf5/CMakeLists.txt b/doc/reference/python/data_analysis/hdf5/CMakeLists.txt new file mode 100644 index 00000000..278c5f22 --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright Olivier Parcollet 2010 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# grab all the rst files here.... +EXECUTE_PROCESS(COMMAND find ${CMAKE_CURRENT_SOURCE_DIR} -name "*.rst" OUTPUT_VARIABLE res ) +string(REPLACE "\n" ";" res ${res}) # remove the newlines +SET(SOURCES ${SOURCES} ${res}) # adding to the previous sources +SET(SOURCES ${SOURCES} PARENT_SCOPE) # put it up + diff --git a/doc/reference/python/data_analysis/hdf5/contents.rst b/doc/reference/python/data_analysis/hdf5/contents.rst new file mode 100644 index 00000000..f2f56f11 --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/contents.rst @@ -0,0 +1,48 @@ + +.. _hdf5_base: +.. module:: pytriqs.archive + +HDF5 interface +################################### + + +In TRIQS, the main data storage format is `HDF5 `_ (Hierarchical Data Format v5). +The best picture of a hdf5 file is that of a **tree**, where : + +* **Leaves** of the tree are basic types : scalars (int, long, double, string) and rectangular arrays of these scalars (any dimension : 1,2,3,4...). +* Subtrees (branches) are called **groups** +* Groups and leaves have a name, so an element of the tree has naturally a **path** : + e.g. /group1/subgroup2/leave1 and so on. +* Any path (groups, leaves) can be optionally tagged with an **attribute**, in addition to their name, + typically a string (or any scalar) + + +`Any data with a tree structure with arrays or scalar leaves can be naturally stored in hdf5 files`. + +To be more precise, we call hereafter a data **hdf-compliant** `iif` it can be reversibly transformed into + +* a tree structure with scalar/arrays leaves. +* or a dictionary `keys -> values`, where `keys` are strings (field names) and `values` are scalars, arrays or any other hdf-compliant data. + +Due to the recursive nature of trees, the two definitions are equivalent. +An hdf-compliant data can be naturally saved in a subgroup of an HDF5 file by adding (cf example below) new leaves for all scalar and arrays +and new subgroup for other hdf-compliant data. + +Using HDF5 format has several advantages : + +* Most basic objects of TRIQS, like Green function, are hdf-compliant. +* TRIQS provides a **simple and intuitive interface HDFArchive** to manipulate them. +* HDF5 is **standard**, well maintained and widely used. +* HDF5 is **portable** from various machines (32-bits, 64-bits, various OS, etc...) +* HDF5 can be read and written in **many langages** (python, C/C++, F90, etc...), beyond TRIQS. One is not tied to a particular program. +* Simple operations to explore and manipulate the tree are provided by simple unix shell commands (e.g. h5ls, h5diff). +* It is a binary format, hence it is compact and has compression options. +* It is to a large extent **auto-documented** : the structure of the data speaks for itself. + +.. toctree:: + :maxdepth: 5 + + tutorial + ref + + diff --git a/doc/reference/python/data_analysis/hdf5/protocol1.rst b/doc/reference/python/data_analysis/hdf5/protocol1.rst new file mode 100644 index 00000000..56ca0f0e --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/protocol1.rst @@ -0,0 +1,90 @@ + +.. _HDF_Protocol1: + +Solution 1. The class provides the transformation into a dict of hdf-compliant objects +---------------------------------------------------------------------------------------------------- + +Principle +^^^^^^^^^^^^^^ + +The object which can be reduced to and reconstructed from a dictionary whose keys are strings, +and whose values are of one of the following types : + + - a scalar (int, float, complex ....) + - a numpy array of scalars + - an hdf-compliant object + - a list, a tuple or a dict of any of the types above. + +A class `cls` has to implement : + +.. py:method:: __reduce_to_dict__() + + Returns a dictionary of objects implementing :ref:`hdf-compliant ` + or basic objects as number, strings, and arrays of numbers (any type and shape). + + :rtype: a dictionary + +.. py:classmethod:: __factory_from_dict__(cls,D) : + + A **classmethod** which reconstructs a new object of type `cls` + from the dictionary returned by :func:`__reduce_to_dict__`. + + :param cls: the class + :param D: the dictionary returned by __reduce_to_dict__. + :rtype: a new object of type `cls` + +Example +^^^^^^^^^^^^^ + +A little example:: + + class Example: + + def __init__(self,d,t) : + self.d,self.t = d,t # some data + + def __reduce_to_dict__(self) : + return {'d' : self.d, 't': self.t} + + @classmethod + def __factory_from_dict__(cls,D) : + return cls(D['d'],D['t']) + + # registering my class + from pytriqs.archive.hdf_archive_schemes import register_class + register_class (myclass) + + # Testing it : + HDFArchive("myfile2.h5")['e'] = Example( [1,2,3], 56) + + +What happens in details ? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Let us consider an object `Ob` of class `Cls`, interacting with and :py:class:`~pytriqs.archive.hdf_archive.HDFArchive`/:py:class:`~pytriqs.archive.hdf_archive.HDFArchiveGroup` `H`. + +* **Writing** :: + + H[Name] = Ob + + * a subgroup `S` of path `Root_of_H/Name` is created. + * Ob.__reduce_to_dict__() is called and returns a dictionary `D` of scalar/numpy arrays/hdf-compliant objects. + * The objects in `D` are then stored `S` in a regular way (scalar/arrays) or using the same recursive procedure (other objects). + * `S` is tagged with the attribute `HDF5_data_scheme` of `Cls`. + + +* **Reading** :: + + res = H[Name] + + * The subgroup `S` of path `Root_of_H/Name` is explored. All objects are taken to build a dictionary `D` : name -> values. + This procedure is recursive : the hdf-compliant objects in the subgroup are rebuilt. + * An attribute `HDF5_data_scheme` is searched for `S`. + + * If it is found and it corresponds to a registered class `Cls` : + + * Cls.__factory_from_dict__(D) is called and returns a new object Obj of type Cls, which is returned as `res`. + + * Otherwise, a new :py:class:`~pytriqs.archive.hdf_archive.HDFArchiveGroup` is constructed with `S` as root, and returned as `res`. + + diff --git a/doc/reference/python/data_analysis/hdf5/protocol2.rst b/doc/reference/python/data_analysis/hdf5/protocol2.rst new file mode 100644 index 00000000..6b66114b --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/protocol2.rst @@ -0,0 +1,9 @@ +.. highlight:: python + +.. _HDF_Protocol2: + +Solution 2. The class does the I/O work by itself +----------------------------------------------------------------- + +not implemented yet + diff --git a/doc/reference/python/data_analysis/hdf5/ref.rst b/doc/reference/python/data_analysis/hdf5/ref.rst new file mode 100644 index 00000000..52652b13 --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/ref.rst @@ -0,0 +1,218 @@ + +Reference manual +############################## + +The :class:`HDFArchive` class offers a convenient interface between the python objects and the HDF5 files, +similar to a dictionary (or a shelve). + +The module contains two classes : + +* :class:`HDFArchiveGroup` : operates on a subtree of the HDF5 file +* :class:`HDFArchive` : an :class:`HDFArchiveGroup` at the root path, with a simple constructor. +* :class:`HDFArchiveInert` : + +Typically, one constructs an :class:`HDFArchive` explicitely, the :class:`HDFArchiveGroup` is created during operations, e.g.:: + + h = HDFArchive( "myfile.h5", 'r') + g = h['subgroup1'] # g is a HDFArchiveGroup. + +Apart from the root path and the constructor, the classes are the same (in fact :class:`HDFArchive` `is a` :class:`HDFArchiveGroup`). +Let us first document :class:`HDFArchive`. + +.. warning:: + + :class:`HDFArchive` and :class:`HDFArchiveGroup` do **NOT** handle parallelism. + Check however the :class:`HDFArchiveInert` below. + +HDFArchive +======================================= + +.. autoclass:: pytriqs.archive.HDFArchive + + + +HDFArchiveGroup +======================================= + +.. class:: HDFArchiveGroup + + There is no explicit constructor for the user of the class. + + The :class:`HDFArchiveGroup` support most of the operations supported by dictionaries. In the following, *H* is a :class:`HDFArchiveGroup`. + + .. describe:: len(H) + + Return the number of items in the :class:`HDFArchiveGroup` *H*. + + .. describe:: H[key] + + Return the item of *H* with key *key*, retrieved from the file. Raises a :exc:`KeyError` if *key* + is not in the :class:`HDFArchiveGroup`. + + .. method:: get_raw (key) + + Returns the subgroup key, **without any reconstruction**, ignoring the HDF5_data_scheme. + + .. describe:: H[key] = value + + Set ``H[key]`` to *value*. + + .. describe:: del H[key] + + Remove ``H[key]`` from *H*. Raises a :exc:`KeyError` if *key* is not in the + :class:`HDFArchiveGroup`. + + .. describe:: key in H + + Return ``True`` if *H* has a key *key*, else ``False``. + + .. describe:: key not in H + + Equivalent to ``not key in H``. + + .. describe:: iter(H) + + Return an iterator over the keys of the dictionary. This is a shortcut + for :meth:`iterkeys`. + + .. method:: items() + + Generator returning couples (key, values) in the group. + + .. warning:: + + Note that in all these iterators, the objects will only be retrieved from the file and loaded into memory + one by one. + + + .. method:: keys() + + Generator returning the keys of the group. + + .. method:: update(d) + + Add into the archive the content of any mapping *d* : keys->values, with + hfd-compliant values. + + .. method:: values() + + Generator returning the values in the group + + .. method:: create_group(K) + + Creates a new subgroup named `K` to the root path of the group. + Raises exception if the subgroup already exists. + + .. method:: is_group(K) + + Return True iif K is a subgroup. + + .. method:: is_data(K) + + Return True iif K is a leaf. + + .. method:: read_attr(AttributeName) + + Return the attribute `AttributeName` of the root path of the group. + If there is no attribute, return None. + + .. method:: root_path() + + Return the root path of the group + + .. method:: apply_on_leaves (f) + + For each named leaf (name,value) of the tree, it calls `f(name,value)`. + + f should return : + + - `None` : no action is taken + - an `empty tuple` () : the leaf is removed from the tree + - an hdf-compliant value : the leaf is replaced by the value + +HDFArchiveInert +======================================= + + +.. class:: HDFArchiveInert + + :class:`HDFArchive` and :class:`HDFArchiveGroup` do **NOT** handle parallelism. + In general, one wish to write/read only on master node, which is a good practice + cluster : reading from all nodes may lead to communication problems. + + To simplify the writing of code, the simple HDFArchiveInert class may be useful. + It is basically inert but does not fail. + + .. describe:: H[key] + + Return H and never raise exception so e.g. H['a']['b'] never raise exception... + + .. describe:: H[key] = value + + Does nothing + + Usage in a mpi code, e.g. :: + + R = HDFArchive("Results.h5",'w') if mpi.is_master_node() else HDFArchiveInert() + a= mpi.bcast(R['a']) # properly broadcast the R['a'] from the master to the nodes. + R['b'] = X # sets R['b'] in the file on the master only, does nothing on the nodes. + + +.. highlight:: python + +.. _HDF_Protocol: + +Hdf-compliant objects +======================================= + +By definition, hdf-compliant objects are those which can be stored/retrieved in an :class:`HDFArchive`. +In order to be hdf-compliant, a class must : + +* have a `HDF5_data_scheme` tag properly registered. +* implement one of the two protocols described below. + +.. _HDF_Protocol_data_scheme: + +HDF5 data scheme +----------------------- + +To each hdf-compliant object, we associate +a `data scheme` which describes how the data is stored in the hdf5 tree, +i.e. the tree structure with the name of the nodes and their contents. +This `data scheme` is added in the attribute `HDF5_data_scheme` +at the node corresponding to the object in the file. + +For a given class `Cls`, the `HDF5_data_scheme` is `Cls._hdf5_data_scheme_` if it exists or the name of the class `Cls.__name__`. +The `HDF5_data_scheme` of a class must be registered in order for :class:`HDFArchive` to properly reconstruct the object when rereading. +The class is registered using the module `hdf_archive_schemes` :: + + class myclass : + pass #.... + + from pytriqs.archive.hdf_archive_schemes import register_class + register_class (myclass) + +The function is + +.. py:function:: register_class (cls [, doc = None] ) + + :param cls: the class to be registered. + :param doc: a doc directory + + Register the class for :class:`HDFArchive` use. + + The name of `data scheme` will be `myclass._hdf5_data_scheme_` if it is defined, or the name of the class otherwise. + +.. _HDF_Protocol_details: + +How to become hdf-compliant ? +----------------------------------- + +There are two ways in which a class can become hdf-compliant: + +.. toctree:: + :maxdepth: 1 + + protocol1 + protocol2 + diff --git a/doc/reference/python/data_analysis/hdf5/tut_ex1.py b/doc/reference/python/data_analysis/hdf5/tut_ex1.py new file mode 100644 index 00000000..581d3792 --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/tut_ex1.py @@ -0,0 +1,11 @@ +from pytriqs.archive import * +import numpy +R = HDFArchive('myfile.h5', 'w') # Opens the file myfile.h5, in read/write mode +R['mu'] = 1.29 +R.create_group('S') +S= R['S'] +S['a'] = "a string" +S['b'] = numpy.array([1,2,3]) +del R,S # closing the files (optional : file is closed when the references to R and subgroup are deleted) + + diff --git a/doc/reference/python/data_analysis/hdf5/tut_ex1.rst b/doc/reference/python/data_analysis/hdf5/tut_ex1.rst new file mode 100644 index 00000000..766bfdb9 --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/tut_ex1.rst @@ -0,0 +1,65 @@ + +.. _hdf5_tut_ex1: + +Example 1 : A basic example +-------------------------------- + +The simplest way to interact with HDF5 files is to use the TRIQS HDFArchive class, which +represents the tree structure of the file in a way similar to a dictionary. + +Let us start with a very simple example :download:`[file] <./tut_ex1.py>`: + +.. literalinclude:: tut_ex1.py + +Run this and say :: + + MyComputer:~>h5ls -r myfile.h5 + / Group + /S Group + /S/a Dataset {SCALAR} + /S/b Dataset {3} + /mu Dataset {SCALAR} + +This show the tree structure of the file. We see that : + +* `mu` is stored at the root `/` +* `S` is a subgroup, containing `a` and `b`. +* For each leave, the type (scalar or array) is given. + +To dump the content of the file use e.g. (Cf HDF5 documentation for more informations) :: + + MyComputer:~>h5dump myfile.h5 + HDF5 "myfile.h5" { + GROUP "/" { + GROUP "S" { + DATASET "a" { + DATATYPE H5T_STRING { + STRSIZE H5T_VARIABLE; + STRPAD H5T_STR_NULLTERM; + CSET H5T_CSET_ASCII; + CTYPE H5T_C_S1; + } + DATASPACE SCALAR + DATA { + (0): "a string" + } + } + DATASET "b" { + DATATYPE H5T_STD_I32LE + DATASPACE SIMPLE { ( 3 ) / ( 3 ) } + DATA { + (0): 1, 2, 3 + } + } + } + DATASET "mu" { + DATATYPE H5T_IEEE_F64LE + DATASPACE SCALAR + DATA { + (0): 1.29 + } + } + } + } + + diff --git a/doc/reference/python/data_analysis/hdf5/tut_ex2.py b/doc/reference/python/data_analysis/hdf5/tut_ex2.py new file mode 100644 index 00000000..f08b47de --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/tut_ex2.py @@ -0,0 +1,16 @@ +from pytriqs.archive import HDFArchive +from pytriqs.gf.local import GfImFreq + +# Define a Green function +G = GfImFreq ( indices = [1], beta = 10, n_points = 1000) + +# Opens the file myfile.h5, in read/write mode +R = HDFArchive('myfile.h5', 'w') +# Store the object G under the name 'g1' and mu +R['g1'] = G +R['mu'] = 1.29 +del R # closing the files (optional : file is closed when the R reference is deleted) + + + + diff --git a/doc/reference/python/data_analysis/hdf5/tut_ex2.rst b/doc/reference/python/data_analysis/hdf5/tut_ex2.rst new file mode 100644 index 00000000..23298c1e --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/tut_ex2.rst @@ -0,0 +1,48 @@ + +.. _hdf5_tut_ex2: + + +Example 2 : A Green function +---------------------------------------------- + +What about more complex objects ? +The good news is that **hdf-compliant** objects can be stored easily as well. + +We can store a Green function in an hdf5 file :download:`[file] <./tut_ex2.py>`: + +.. literalinclude:: tut_ex2.py + +Of course, we can retrieve G as easily :download:`[file] <./tut_ex2b.py>`: + +.. literalinclude:: tut_ex2b.py + +The structure of the HDF file is this time :: + + MAC:~>h5ls -r myfile.h5 + / Group + /g1 Group + /g1/Data Dataset {2, 2, 1000} + /g1/Indices Dataset {2} + /g1/Mesh Group + /g1/Mesh/Beta Dataset {SCALAR} + /g1/Mesh/Statistic Dataset {SCALAR} + /g1/Mesh/TypeGF Dataset {SCALAR} + /g1/Mesh/array Dataset {1000} + /g1/Name Dataset {SCALAR} + /g1/Note Dataset {SCALAR} + /g1/Tail Group + /g1/Tail/Indices Dataset {2} + /g1/Tail/OrderMax Dataset {SCALAR} + /g1/Tail/OrderMaxMAX Dataset {SCALAR} + /g1/Tail/OrderMinMIN Dataset {SCALAR} + /g1/Tail/array Dataset {13, 2, 2} + /mu Dataset {SCALAR} + + +.. hint:: How does this work ? + + The Green function implements (as detailed in :ref:`HDF_Protocol`) + + * a method :func:`__reduce_to_dict__` that reduces to the Green function to a dictionary containing a mesh (Mesh), a tail (Tail), the data (Data), the indices (Indices) and so on. + * a classmethod :func:`__factory_from_dict__` that reconstructs the Green function from this dictionary. + diff --git a/doc/reference/python/data_analysis/hdf5/tut_ex2b.py b/doc/reference/python/data_analysis/hdf5/tut_ex2b.py new file mode 100644 index 00000000..18ce131d --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/tut_ex2b.py @@ -0,0 +1,9 @@ +from pytriqs.archive import HDFArchive +from pytriqs.gf.local import GfImFreq + +R = HDFArchive('myfile.h5', 'r') # Opens the file myfile.h5 in readonly mode +G = R['g1'] # Retrieve the object named g1 in the file as G + +# ... ok now I can work with G + + diff --git a/doc/reference/python/data_analysis/hdf5/tut_ex3.py b/doc/reference/python/data_analysis/hdf5/tut_ex3.py new file mode 100644 index 00000000..45229e32 --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/tut_ex3.py @@ -0,0 +1,12 @@ +from pytriqs.gf.local import GfReFreq +from pytriqs.gf.local.descriptors import SemiCircular +from pytriqs.archive import HDFArchive +import numpy + +R = HDFArchive('myfile.h5', 'w') +for D in range(1,10,2) : + g = GfReFreq(indices = [0], beta = 50, mesh_array = numpy.arange(-1.99,2.00,0.02) , name = "D=%s"%D) + g <<= SemiCircular(half_bandwidth = 0.1*D) + R[g.name]= g + + diff --git a/doc/reference/python/data_analysis/hdf5/tut_ex3.rst b/doc/reference/python/data_analysis/hdf5/tut_ex3.rst new file mode 100644 index 00000000..6c54db6e --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/tut_ex3.rst @@ -0,0 +1,42 @@ + +.. _hdf5_tut_ex3: + +Example 3 : Use the dictionary interface of the archive +-------------------------------------------------------------------- + +The archive is like a dictionary, persistent on disk. +`[for Python afficionados, it is similar to a shelve, but in a portable format]`. +Therefore, one can iterate on its elements. + +Let us imagine that you have stored 5 Green functions in an hdf5 file. +For example, we can create such a file as :download:`[file] <./tut_ex3.py>`: + +.. literalinclude:: tut_ex3.py + + +Imagine that we want to plot those functions :download:`[file] <./tut_ex3b.py>`: + +.. literalinclude:: tut_ex3b.py + :lines: 1-13 + +This produces the following plot (scaled semi-circular density of states). + +.. image:: tut_ex3b.png + :width: 750 + :align: center + +Various pythonic constructs can be used in combinaison with HDFArchive, e.g. +in order to plot only a few curves from a list :: + + keylist = ['D=1', 'D=3'] + + for g in ( R[x] for x in keylist) : # use an iterator + oplot( (- 1/pi * g).imag, "-o", name = 'g' ) + +or if we want to add the names :: + + for n,g in ( (x,R[x]) for x in keylist) : # use an iterator + oplot( (- 1/pi * g).imag, "-o", name = n ) + +The advantage of using an iterator is that the object is only retrieved from disk when needed. + diff --git a/doc/reference/python/data_analysis/hdf5/tut_ex3b.png b/doc/reference/python/data_analysis/hdf5/tut_ex3b.png new file mode 100644 index 0000000000000000000000000000000000000000..fae4ec71975641654c383fe4b2032d28abc6f1b5 GIT binary patch literal 62478 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 literal 0 HcmV?d00001 diff --git a/doc/reference/python/data_analysis/hdf5/tut_ex3b.py b/doc/reference/python/data_analysis/hdf5/tut_ex3b.py new file mode 100644 index 00000000..878e7def --- /dev/null +++ b/doc/reference/python/data_analysis/hdf5/tut_ex3b.py @@ -0,0 +1,15 @@ +from pytriqs.gf.local import GfReFreq +from pytriqs.archive import HDFArchive +from math import pi + +R = HDFArchive('myfile.h5', 'r') + +from pytriqs.plot.mpl_interface import oplot, plt +plt.xrange(-1,1) +plt.yrange(0,7) + +for name, g in R.items() : # iterate on the elements of R, like a dict ... + oplot( (- 1/pi * g).imag, "-o", name = name) + +p.savefig("./tut_ex3b.png") + diff --git a/doc/reference/python/data_analysis/hdf5/tut_hdf1.png b/doc/reference/python/data_analysis/hdf5/tut_hdf1.png new file mode 100644 index 0000000000000000000000000000000000000000..6d53bb63b64914eecdde7bbec61ceb537f33ef77 GIT binary patch literal 141624 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%0A>XD5KAYAk06%#w!G@HF#_U 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

8&!?<5F5rw;E9TgLP`OE1L~o>4LAqhrUOO< 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 X&?$TQLFHfqc@!xzdC{DQ22cMRg-qA- literal 0 HcmV?d00001 diff --git a/doc/reference/python/data_analysis/plotting/example.py b/doc/reference/python/data_analysis/plotting/example.py new file mode 100644 index 00000000..74462bad --- /dev/null +++ b/doc/reference/python/data_analysis/plotting/example.py @@ -0,0 +1,15 @@ +from pytriqs.gf.local import * +from pytriqs.gf.local.descriptors import Omega +g = GfImFreq(indices = [1], beta = 50, n_points = 1000, name = "g") +g <<= inverse( Omega + 0.5 ) + +# open 2 panels top (t) and bottom (b) +from pytriqs.plot.mpl_interface import subplots +f, (t,b) = subplots( 2,1) + +#plot ... +t.oplot(g.real, '-o', x_window = (0,10) ) +b.oplot(g.imag, '-x', x_window = (0,12) ) +b.oplot( lambda om : -om*0.8/(om*om + 4), name = "Bad Fit !") +b.text(5,-0.5, r'$g(i\omega_n) = \frac{1}{i \omega_n + 1/2} $', size = 20, color='r') + diff --git a/doc/reference/python/data_analysis/plotting/myobject.png b/doc/reference/python/data_analysis/plotting/myobject.png new file mode 100644 index 0000000000000000000000000000000000000000..b721cd10b538b510093ff03a218023dd45953f91 GIT binary patch literal 52082 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 literal 0 HcmV?d00001 diff --git a/doc/reference/python/data_analysis/plotting/myobject.py b/doc/reference/python/data_analysis/plotting/myobject.py new file mode 100644 index 00000000..3275f1c6 --- /dev/null +++ b/doc/reference/python/data_analysis/plotting/myobject.py @@ -0,0 +1,17 @@ +import numpy + +class myObject(object): + def _plot_(self, options): + PI = numpy.pi + xdata = numpy.arange(-PI,PI,0.1) + ydata1 = numpy.cos(xdata) + ydata2 = numpy.sin(xdata) + return( [ + {'type': "XY", 'xdata': xdata, 'ydata': ydata1, 'label': 'Cos'}, + {'type': "XY", 'xdata': xdata, 'ydata': ydata2, 'label': 'Sin'} + ] ) + +X = myObject() + +from pytriqs.plot.mpl_interface import oplot +oplot(X,'-o') diff --git a/doc/reference/python/data_analysis/plotting/myobject2.png b/doc/reference/python/data_analysis/plotting/myobject2.png new file mode 100644 index 0000000000000000000000000000000000000000..b0b4a8a76d5f459b6a7d3cec5f340a5027cc81c8 GIT binary patch literal 68117 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%0Dz zOqF>yPV|7o|HpODB#lL`uf`EsEgbl2C3;+;%?~#w+<&bDT#Qt*3k-Vrl2@t zrfW(J3Ru+y#fdd$!7UgoRLSHUp&p1UDk{=DOO};jS}-GJ+UW03+Toi`AdR=H0F_8^ z%OU@Ggm~sEEYOVVoNNFP6%@b9u;_!@3ON52Ki!+{*`7d9O27mF%0fKP%@@qg{C$0K zasgl{;P3H1JUuO2_g24gI7-K4*p&&mx~+N@@IucpuhlGdI-?|5I}~j7Jx;^AF;G)e zD>G{w2Hl)s66RJqQ^>J*c=*v1Zf<;ai2m0JJMi@>b{G~c<;zX4yi@GE+yC_i4OlLl z{$#fMyZI2Cj3ia2Y@p;~4h7I}4p!L==+`<>a<}|TEG>ejmfQ@=zTKOx+h~7}ZIko- z6Swn1Yk;Sk!Z?gq=QkH;y z6Ot7jBb1duA|Iw%KH6C<%wtydqjva*&h4=^z?9i}Q!gMa+^!Kd?iJ0=ihKEM|cY|b#SHAknX zwg5QnPFF{8w_R5i7C|Rhy^D`muMo$p#s=H=x@ ze)zE38AWW|;Pzg~ab|I6X8_z63VvHPd z5%)*xFIZPLiZs8;tEhAVv&K@Smk*wCPuOHs>#zh2F0hXgfV7Fn|NJl`C&MJ^zmxjU z*zN&iy9RRR(*OBEZE806C-?r4A?&LVXbk`_. +In fact, TRIQS introduces a simple :ref:`plot protocol `, which allows to plot +objects which have a graphical representation. + +A thin layer above matplotlib +================================= + +TRIQS defines a function *oplot*, similar to the standard matplotlib pyplot.plot function, +but that can plot TRIQS objects (in fact *any* object, see below). + +We can reproduce the first example of the Green function tutorial : + +.. plot:: reference/python/green/example.py + :include-source: + :scale: 70 + +The *oplot* function takes : + +* as arguments any object that implements the :ref:`plot protocol `, + for example Green function, Density of state : in fact any object where plotting is reasonable and has been defined ... + +* string formats following objects, as in regular matplotlib, like in the example above. + +* regular options of the matplotlib *pyplot.plot* function + +* options specific to the object to be plotted : here the `x_window` tells the Green function to plot itself in a reduced window of :math:`\omega_n`. + +Multiple panels figures +================================= + +`Only valid for matplotlib v>=1.0`. + +While one can use the regular matplotlib subfigure to make multi-panel figures, +subplots makes it a bit more pythonic : + +.. plot:: reference/python/data_analysis/plotting/example.py + :include-source: + :scale: 70 + +.. index:: plotting protocol + +.. _plot_protocol: + +Plot protocol [Advanced] +=========================== + +What do we need to implement to plot an object ? +Simply a little `_plot_` method that reduces the object to a set of curves. +This section describes the conventions on this function. + +As soon as an object defines this method, it can be plotted by the `oplot` function of `pytriqs.plot.mpl_interface`. +See example below. + +.. function:: _plot_( OptionsDict ) + + * OptionDict is a dictionnary of options. + + .. warning:: + * The method _plot_ must consume the options it uses (using e.g. the pop method of dict). + * Other options will be passed to matplotlib, so leaving spurious options here will lead to errors. + + :rtype: a list of dict representing one curve each. These dict must have the following fields: + + * *xdata* : A 1-dimensional numpy array describing the x-axis points + * *ydata* : A 1-dimensional numpy array describing the y-axis points + * *label* : Label of the curve for the legend of the graph + * *type* : a string : currently "XY" [ optional] + + and optionally : + + * *xlabel* : a label for the x axis. The last object plotted will overrule the previous ones. + * *ylabel* : a label for the y axis. The last object plotted will overrule the previous ones. + +Example +------- + +Here's a simple example to illustrate the protocol: + +.. plot:: reference/python/data_analysis/plotting/myobject.py + :include-source: + :scale: 70 + +Example with options +--------------------------- + +A little bit more complex, with options. +Note the use of the `pop method of dict `_, +which returns and removes the entry from the dict (with a default value). + +.. plot:: reference/python/data_analysis/plotting/myobject2.py + :include-source: + :scale: 70 + + diff --git a/doc/reference/python/data_analysis/provenance.rst b/doc/reference/python/data_analysis/provenance.rst new file mode 100644 index 00000000..7dfcdec7 --- /dev/null +++ b/doc/reference/python/data_analysis/provenance.rst @@ -0,0 +1,101 @@ +Reproducibility, provenance. +================================= + +Scientific numerical calculations are ... scientific calculations. + +Hence, like any other kind of calculations, according to the basic principles of science, +everyone should be able to reproduce them, reuse or modify them. +Therefore, the detailed instructions leading to results or figures +should be published along with them. +To achieve these goals, in practice we need to be able to do simply the following things : + +* Store along with the data the version of the code used to produced them (or even the code itself !), + and the configuration options of this code. + +* Keep with the figures all the instructions (i.e. the script) that have produced it. + +* We want to do that **easily, at no cost in human time**, hence + without adding a new layer of tools (which means new things to learn, which takes time, etc...). + Indeed this task is important but admittedly extremely boring for physicists... + +Fortunately, python helps solving these issues easily and efficiently. + +TRIQS adds very little to the standard python tools here. +So this page should be viewed more as a wiki page of examples. +TRIQS does not impose any framework on you, it just provides tools +and lets you organize your work as you wish. + + +TRIQS code version +---------------------- + +The tiny module `pytriqs.version` +contains various pieces of information configured automatically at compile time :: + + import pytriqs.version as V + + V.revision # The branch and the git_hash commit number or version number + V.git_hash # The commit number if under git, or "" + V.branch # the branch on which the code was compiled + + # publishing these informations may lead to a security issue.... + V.cmake_options() # returns the contents of the CMakeCache.txt file + V.machine_info # Hostname and login of the compilation + V.all_info # a print of most info (except Cache) + +.. warning:: + + While the informations of the configurations, the machine, and login may be useful for *you* to + reproduce the computation, publishing them is not recommended since it contains informations on your machine, your login. + For public data, just use V.revision. + +Saving the script in the data archive +------------------------------------------- + +It is actually very simple to save the script +(hence the parameters) along with the data, +simply by putting it in the HDFArchive, e.g. :: + + # ... computation ... + Results = HDFArchive("solution.h5",'w') + Results["G"] = S.G # save the results + + import sys, pytriqs.version as version + Results.create_group("log") + log = Results["log"] + log["code_version"] = version.revision + log["script"] = open(sys.argv[0]).read() # read myself ! + +The script that is currently being executed will be copied into the file `solution.h5`, under the subgroup `/log/script`. + +In a more complex situation, you may decompose your computation in several scripts, e.g. + +* A script common.py, with some common functions, classes... +* A little one, computation1.py for each computations. + +In such situation, one can simply use the `inspect` module of the python standard library e.g. :: + + import common + # set parameters + # run... + # save... + # Ok, I need to save common too ! + import inspect,sys, pytriqs.version as version + log = Results.create_group("log") + log["code_version"] = version.revision() + log["script"] = open(sys.argv[0]).read() + log["common"] = inspect.getsource(common) # This retrieves the source of the module in a string + + +From the data to the figures +------------------------------------------- + +[TO BE WRITTEN] + + + + + + + + diff --git a/doc/reference/python/green/block.rst b/doc/reference/python/green/block.rst new file mode 100644 index 00000000..e6435551 --- /dev/null +++ b/doc/reference/python/green/block.rst @@ -0,0 +1,221 @@ +.. index:: + single: Green's functions; block Green's function + module: gf_imfreq + module: gf_refreq + module: gf_imtime + module: gf_retime + module: gf_legendre + +.. _blockgreen: + +The blocks: matrix-valued Green's functions +=============================================== + +In this section, we present the matrix-valued Green's functions, +i.e. the blocks of the full local Green's function. +They are available in various flavours: + +.. toctree:: + :maxdepth: 1 + + block/GfImTime + block/GfImFreq + block/GfReTime + block/GfReFreq + block/GfLegendre + +They have many common properties, which we now present. + + +Operations +-------------------------------------------- + +Block Green's functions support various simple operations. + +.. note:: + All these operations compute the array of data, but also, if present in the object, the high frequency expansion tail automatically. + +* compound operators, `+=`, `-=`, `*=`, `\=`: the RHS can be a Green's function of the same type or an expression + +* arithmetic operations : `+`, `-`, `*`, `/`, e.g.:: + + g = g1 + 2*g2 + +* inversion, e.g.:: + + inv = inverse(g) + g2 = inverse(inverse(g) - sigma) # this is Dyson's equation + +Slicing +-------- + +Just like numpy arrays, the Green's function can be sliced, *when the indices are integers* (otherwise it is meaningless). +The syntax is the regular python/numpy syntax, so a simple example will be enough here:: + + >>> from pytriqs.gf.local import * + >>> g = GfImFreq(indices = [1,2,3], beta = 50, n_points = 1000, name = "imp") + >>> g[1:3:,1:3] + GfImFreq imp : Beta = 50.000; IndicesL = [1, 2], IndicesR = [1, 2] + + >>> g[1,1] + GfImFreq imp : Beta = 50.000; IndicesL = [1], IndicesR = [1] + + >>> g[2:3,2:3] + GfImFreq imp : Beta = 50.000; IndicesL = [2], IndicesR = [2] + + +Assignment: <<= or = operator +-------------------------------------------- + +Because python always uses references, one cannot simply use the = operator +to assign some expression into a Green's function. +Therefore, we introduced the <<= operator :: + + g <<= RHS + +This sets the data and tail of g with the RHS. + + * If RHS is Green's function, it must be of the same type and size must match + * If RHS is a formal expression, it must be of the same size + +To simplify the notation, in the case where one accesses the Green's function with a [ ] operation, +the = sign is possible and equivalent to the `<<=` operator. + +.. warning:: + Don't use the = operator without the brackets: it has its normal python meaning, i.e. + reaffecting the reference. + + Let us illustrate this issue on a simple example:: + + from pytriqs.gf.local import * + # Create the Matsubara-frequency Green's function + g = GfImFreq(indices = [1], beta = 50, n_points = 1000, name = "imp") + + g <<= inverse( Omega + 0.5 ) # correct + g[1,1] = inverse( Omega + 0.5 ) # correct (it uses __setitem__). + + + However, the following line is almost certainly NOT what you have in mind:: + + g = inverse( Omega + 0.5 ) + + * The reference g is reassigned to the object `inverse( Omega + 0.5 )`, which is not a block Green's function but a lazy expression. + * The block created earlier is destroyed immediately. + + +Lazy expressions +---------------- + +To initialize the Green's function, one can use lazy_expression, made of Green's functions, `descriptors` +assembled with basic operations. + +:ref:`descriptors` are abstract objects that do not contain data, but describe a simple function and +can be evaluated, can compute the high-frequency expansion, and so on. For example: + + * `Omega`: is the function :math:`f(\omega) = \omega`. + * `SemiCircular(D)`: is a Green's function corresponding to free fermions with a semi circular density of states of half-bandwith `D`. + * `Wilson`: is a Green's function corresponding to fermions with a flat density of states of half-bandwidth `D`. + +.. toctree:: + :maxdepth: 1 + + descriptors + +shelve / pickle +--------------- + +Green's functions are `pickable`, i.e. they support the standard python serialization techniques. + +* It can be used with the `shelve `_ and `pickle `_ module:: + + import shelve + s = shelve.open('myfile','w') + s['G'] = G # G is stored in the file. + +* It can be sent/broadcasted/reduced over mpi :: + + from pytriqs.utility import MPI + mpi.send (G, destination) + +.. warning:: + Shelve is not a portable format, it may change from python version to another (and it actually does). + For portability, we recommend using the HDF5 interface for storing data on disks. + + +Plot options +------------ + +There is one important option that you will find very useful when plotting Green's functions, which we +saw already in the previous section: + +* `RI` = 'R' or 'I' or 'S' + +It tells the plotter, what part of the Green's function you want to plot. 'R' for the real part, 'I' +for the imaginary part, and 'S' for the spectral function, :math:`-1/\pi{\rm Im}G`. Of course, +depending on the type of Green's function under consideration, one or more of these options do not make a lot of sense, e.g. +calculating the spectral function of an imaginary-time Green's function is not useful. + + +Direct access to data points and tails [not for the Legendre version] +----------------------------------------------------------------------------- + +Data points can be accessed via the properties ``data`` and ``tail`` respectively. +``data`` returns an array object and so does ``tail[i]``:: + + g.data + +.. warning:: + + Be careful when manipulating data directly to keep consistency between + the function and the tail. + Basic operations do this automatically, so use them as much as possible. + The little _ header is there to remind you that maybe you should consider another option. + + +.. _greentails: + +Direct access to the tails +-------------------------- + +All block Green's function come together with a **Tail** object that describes its +large-frequency behavior. In other words, for large :math:`|z|`, the Green's function +behaves like + +.. math:: + + g(z) \sim ... + M_{-1} z + M_0 + \frac{M_1}{z} + \frac{M_2}{z} + ... + +where :math:`M_i` are matrices with the same dimensions as :math:`g`. + +* Tails can be accessed with the ``tail`` property. Moreover, in order + to have access to :math:`M_i`, one uses the bracket. For example:: + + >>> g = GfImFreq(indices = ['eg1','eg2'], beta = 50, n_points = 1000, name = "egBlock") + >>> g <<= 2.0 + >>> print g.tail[0] + + TO BE UPDATED + + Here ``g.tail[0]`` is a diagonal matrix with 2 on the diagonal, corresponding to :math:`M_0`. + +* Some operations (sum over frequencies, Fourier) uses these tails to regulate the sum, + so it is necessary to always keep the consistency between the array of data and the tail expansion. + +* Fortunately, in all basic operations on the blocks, these tails are computed automatically. + For example, when adding two Green functions, the tails are added, and so on. + +* However, if you modify the ``data`` or the ``tail`` manually, you loose this guarantee. + So you have to set the tail properly yourself (or be sure that you will not need it later). + For example:: + + g = GfImFreq(indices = ['eg1','eg2'], beta = 50, n_points = 1000, name = "egBlock") + g <<= Function(lambda x: 3/x) + g.tail.zero() + g.tail[1] = numpy.array( [[3.0,0.0], [0.0,3.0]] ) + + The third line sets all the :math:`M_i` to zero, while the second puts :math:`M_1 = diag(3)`. With + the tails set correctly, this Green's function can be used safely. + +.. warning:: + The library will not be able detect, if tails are set wrong. Calculations may also be wrong in this case. + diff --git a/doc/reference/python/green/block/GfImFreq.rst b/doc/reference/python/green/block/GfImFreq.rst new file mode 100644 index 00000000..0a045d47 --- /dev/null +++ b/doc/reference/python/green/block/GfImFreq.rst @@ -0,0 +1,54 @@ +.. index:: + single: Green's functions; block Green's function + module: gf_imfreq + +.. _GfImFreq: + +Matsubara Green's function in imaginary frequencies (GfImFreq) +===================================================================================== + +This object stores a matrix valued Green function in imaginary frequencies +in the Matsubara formalism : + +.. math:: + G_{\alpha \beta} (i \omega_n) \equiv \int_0^\beta G_{\alpha \beta} ( \tau) e^{-i \omega_n \tau} + +where :math:`G(\tau)` is the :ref:`Matsubara Green function in imaginary time `. + + +Reference +--------------- + +.. autoclass:: pytriqs.gf.local.GfImFreq + :members: density, set_from_fourier, set_from_legendre + + +HDF5 data scheme +^^^^^^^^^^^^^^^^^^^^^^ + +The GfImFreq (TRIQS_HDF5_data_scheme= "GfImFreq") is decomposed in the following objects : + +========================= =========================== =========================================================================== +Name Type Meaning +========================= =========================== =========================================================================== +Mesh MeshGf The mesh +Tail TailGf The tail +Data 3d numpy of complex Data[i1,i2,n] is the element of the Green function where : + * i1, i2 are the indices + * n is the Matsubara index + + For real GF in time, we store only starting from n=0 and the + rest is deduced by symmetry +IndicesL,IndicesR string The Python repr of the indices, e.g. (1,2), or (1,) + repr(this_string) reproduces the indices +Name string Name of the Green function block +Note string Note +========================= =========================== =========================================================================== + + +Example +--------------- + +.. plot:: reference/python/green/block/green_imfreq.py + :include-source: + :scale: 70 diff --git a/doc/reference/python/green/block/GfImTime.rst b/doc/reference/python/green/block/GfImTime.rst new file mode 100644 index 00000000..e0e1efd2 --- /dev/null +++ b/doc/reference/python/green/block/GfImTime.rst @@ -0,0 +1,50 @@ +.. index:: + single: Green's functions; block Green's function + module: gf_imtime + +.. _GfImTime: + +Matsubara Green's function in imaginary time (GfImTime) +============================================================================== + +This object stores a matrix valued Green function in imaginary time +in the Matsubara formalism : + +.. math:: + + G_{\alpha \beta} (\tau) \equiv - \mathcal{T} \qquad \text{ for } 0 \leq \tau \leq \beta + + +Reference +--------------- + +.. autoclass:: pytriqs.gf.local.GfImTime + :members: set_from_inverse_fourier, set_from_legendre, transpose, conjugate + + +HDF5 data scheme +^^^^^^^^^^^^^^^^^^^^^^ + +The GfImTime (TRIQS_HDF5_data_scheme = "GfImTime") is decomposed in the following objects : + +========================= =========================== =========================================================================== +Name Type Meaning +========================= =========================== =========================================================================== +Mesh MeshGf The mesh +Tail TailGf The tail +Data 3d numpy of double Data[i1,i2,n] is the element of the Green function where : + * i1, i2 are the indices + * n is the index of the time slice, starting at tau =0 +IndicesL,IndicesR string The Python repr of the indices, e.g. (1,2), or (1,) + repr(this_string) reproduces the indices +Name string Name of the Green function block +Note string Note +========================= =========================== =========================================================================== + +Example +------- + +.. plot:: reference/python/green/block/green_imtime.py + :include-source: + :scale: 70 + diff --git a/doc/reference/python/green/block/GfLegendre.rst b/doc/reference/python/green/block/GfLegendre.rst new file mode 100644 index 00000000..398537ae --- /dev/null +++ b/doc/reference/python/green/block/GfLegendre.rst @@ -0,0 +1,55 @@ +.. index:: + single: Green's functions; block Green's function + module: gf_legendre + +.. _GfLegendre: + +Matsubara Green's function with Legendre polynomials (GfLegendre) +===================================================================================== + +This object stores a matrix-valued Matsubara Green's function in imaginary time using +Legendre polynomials. It is connected to the usual imaginary-time Matsubara Green's +function through: + +.. math:: + G_{l, \alpha \beta} = \sqrt{2l+1} \int_0^\beta d\tau P_l (x(\tau)) G_{\alpha \beta}(\tau), + + +where :math:`x(\tau) = 2\tau/\beta -1` and the :math:`P_l` are the Legendre +polynomials. :math:`G_{\alpha \beta}(\tau)` is the :ref:`Matsubara Green's +function in imaginary time `. + + +Reference +--------------- + +.. autoclass:: pytriqs.gf.local.GfLegendre + :members: density, enforce_discontinuity + + +HDF5 data scheme +^^^^^^^^^^^^^^^^^^ + +The GfLegendre (TRIQS_HDF5_data_scheme= "GfLegendre") is decomposed in the following objects : + +========================= =========================== =========================================================================== +Name Type Meaning +========================= =========================== =========================================================================== +Mesh MeshGf The mesh +Tail TailGf The tail +Data 3d numpy of complex Data[i1,i2,n] is the element of the Green function where : + * i1, i2 are the indices + * n is the Legendre coefficient index +IndicesL, IndicesR string The Python repr of the indices, e.g. (1,2), or (1,) + repr(this_string) reproduces the indices +Name string Name of the Green's function block +Note string Note +========================= =========================== =========================================================================== + +Example +--------------- + +.. plot:: reference/python/green/block/green_legendre.py + :include-source: + :scale: 70 + diff --git a/doc/reference/python/green/block/GfReFreq.rst b/doc/reference/python/green/block/GfReFreq.rst new file mode 100644 index 00000000..6795929f --- /dev/null +++ b/doc/reference/python/green/block/GfReFreq.rst @@ -0,0 +1,62 @@ +.. index:: + single: Green's functions; block Green's function + module: gf_refreq + +.. _GfReFreq: + +Retarded Green's function in real frequencies (GfReFreq) +===================================================================================== + +This object stores a matrix valued Green function in real frequencies : + +.. math:: + G_{\alpha \beta} (\omega) \equiv \int_{-\infty}^{\infty} G_{\alpha \beta} ( t ) e^{-i \omega t} + +where :math:`G(t)` is the :ref:`Green function in real time `. + + +Reference +--------------- + +.. autoclass:: pytriqs.gf.local.GfReFreq + :members: set_from_fourier, inverse_fourier, transpose, conjugate, set_from_pade + + + +HDF5 data scheme +^^^^^^^^^^^^^^^^^^^^^^ + +The GfReFreq (TRIQS_HDF5_data_scheme = "GfReFreq") is decomposed in the following objects : + +========================= =========================== =========================================================================== +Name Type Meaning +========================= =========================== =========================================================================== +Mesh MeshGf The mesh +Tail TailGf The tail +Data 3d numpy of complex Data[i1,i2,n] is the element of the Green function where : + * i1, i2 are the indices + * n is the frequency index +IndicesL,IndicesR string The Python repr of the indices, e.g. (1,2), or (1,) + repr(this_string) reproduces the indices +Name string Name of the Green function block +Note string Note +========================= =========================== =========================================================================== + + +Examples +--------------- + +.. plot:: reference/python/green/block/green_refreq.py + :include-source: + :scale: 70 + +Note that `g` is a **retarded** Green's function. + + +The next example demonstrates how a real frequency Green's function can be +reconstructed from an imaginary frequency counterpart using set_from_pade() +method. + +.. plot:: reference/python/green/block/green_pade.py + :include-source: + :scale: 70 diff --git a/doc/reference/python/green/block/GfReTime.rst b/doc/reference/python/green/block/GfReTime.rst new file mode 100644 index 00000000..471d3708 --- /dev/null +++ b/doc/reference/python/green/block/GfReTime.rst @@ -0,0 +1,49 @@ +.. index:: + single: Green's functions; block Green's function + module: gf_retime + +.. _GfReTime: + +Retarded Green's function in real time (GfReTime) +===================================================================================== + +This object stores a retarded matrix valued Green function in real time : + +.. math:: + G_{\alpha \beta} (t) \equiv - \theta(t) <\{c_{\alpha}(t) c^{\dagger}_{\beta} (0)\}> + + +Reference +--------------- + +.. autoclass:: pytriqs.gf.local.GfReTime + :members: set_from_inverse_fourier, fourier, transpose, conjugate + + +HDF5 data scheme +^^^^^^^^^^^^^^^^^^^^^^ + +The GfReTime (TRIQS_HDF5_data_scheme = "GfReTime") is decomposed in the following objects : + +========================= =========================== =========================================================================== +Name Type Meaning +========================= =========================== =========================================================================== +Mesh MeshGf The mesh +Tail TailGf The tail +Data 3d numpy of complex Data[i1,i2,n] is the element of the Green function where : + * i1, i2 are the indices + * n is the index of the time slice +IndicesL,IndicesR string The Python repr of the indices, e.g. (1,2), or (1,) + repr(this_string) reproduces the indices +Name string Name of the Green function block +Note string Note +========================= =========================== =========================================================================== + + +Example +--------------- + +.. plot:: reference/python/green/block/green_retime.py + :include-source: + :scale: 70 + diff --git a/doc/reference/python/green/block/green_imfreq.py b/doc/reference/python/green/block/green_imfreq.py new file mode 100644 index 00000000..c22c2cfb --- /dev/null +++ b/doc/reference/python/green/block/green_imfreq.py @@ -0,0 +1,11 @@ +from pytriqs.gf.local import GfImFreq, SemiCircular + +g = GfImFreq(indices = ['eg1','eg2'], beta = 50, n_points = 1000, name = "egBlock") + +g['eg1','eg1'] = SemiCircular(half_bandwidth = 1) +g['eg2','eg2'] = SemiCircular(half_bandwidth = 2) + +from pytriqs.plot.mpl_interface import oplot,plt +oplot(g, '-o', x_window = (0,10)) +plt.ylim(-2,1) + diff --git a/doc/reference/python/green/block/green_imtime.py b/doc/reference/python/green/block/green_imtime.py new file mode 100644 index 00000000..e1a5b3bc --- /dev/null +++ b/doc/reference/python/green/block/green_imtime.py @@ -0,0 +1,13 @@ +from pytriqs.gf.local import * +from pytriqs.plot.mpl_interface import oplot,plt + +# A Green's function on the Matsubara axis set to a semicircular +gw = GfImFreq(indices = [1], beta = 50) +gw <<= SemiCircular(half_bandwidth = 1) + +# Create an imaginary-time Green's function +gt = GfImTime(indices = [1], beta = 50) +gt <<= InverseFourier(gw) + +# Plot the Legendre Green's function +oplot(gt, '-') diff --git a/doc/reference/python/green/block/green_legendre.py b/doc/reference/python/green/block/green_legendre.py new file mode 100644 index 00000000..981334e2 --- /dev/null +++ b/doc/reference/python/green/block/green_legendre.py @@ -0,0 +1,14 @@ +from pytriqs.gf.local import * +from pytriqs.plot.mpl_interface import oplot,plt + +# A Green's function on the Matsubara axis set to a semicircular +gw = GfImFreq(indices = [1], beta = 50) +gw <<= SemiCircular(half_bandwidth = 1) + +# Create a Legendre Green's function with 40 coefficients +# and initialize it from gw +gl = GfLegendre(indices = [1], beta = 50, n_points = 40) +gl <<= MatsubaraToLegendre(gw) + +# Plot the Legendre Green's function +oplot(gl, '-o') diff --git a/doc/reference/python/green/block/green_pade.py b/doc/reference/python/green/block/green_pade.py new file mode 100644 index 00000000..8d15809a --- /dev/null +++ b/doc/reference/python/green/block/green_pade.py @@ -0,0 +1,44 @@ +import numpy +from math import pi +from cmath import sqrt, log +from pytriqs.gf.local import * +from pytriqs.gf.local.descriptors import Function + +beta = 100 # Inverse temperature +L = 101 # Number of Matsubara frequencies used in the Pade approximation +eta = 0.01 # Imaginary frequency shift + +## Test Green's functions ## + +# Two Lorentzians +def GLorentz(z): + return 0.7/(z-2.6+0.3*1j) + 0.3/(z+3.4+0.1*1j) + +# Semicircle +def GSC(z): + return 2.0*(z + sqrt(1-z**2)*(log(1-z) - log(-1+z))/pi) + +# A superposition of GLorentz(z) and GSC(z) with equal weights +def G(z): + return 0.5*GLorentz(z) + 0.5*GSC(z) + +# Matsubara GF +gm = GfImFreq(indices = [0], beta = beta, name = "gm") +gm <<= Function(G) +gm.tail.zero() +gm.tail[1] = numpy.array([[1.0]]) + +# Real frequency BlockGf(reference) +gr = GfReFreq(indices = [0], window = (-5.995, 5.995), n_points = 1200, name = "gr") +gr <<= Function(G) +gr.tail.zero() +gr.tail[1] = numpy.array([[1.0]]) + +# Analytic continuation of gm +g_pade = GfReFreq(indices = [0], window = (-5.995, 5.995), n_points = 1200, name = "g_pade") +g_pade.set_from_pade(gm, n_points = L, freq_offset = eta) + +# Comparison plot +from pytriqs.plot.mpl_interface import oplot +oplot(gr[0,0], '-o', RI = 'S', name = "Original DOS") +oplot(g_pade[0,0], '-x', RI = 'S', name = "Pade-reconstructed DOS") diff --git a/doc/reference/python/green/block/green_refreq.py b/doc/reference/python/green/block/green_refreq.py new file mode 100644 index 00000000..b80a27b9 --- /dev/null +++ b/doc/reference/python/green/block/green_refreq.py @@ -0,0 +1,13 @@ +import numpy as np +from pytriqs.gf.local import GfReFreq, SemiCircular + +g = GfReFreq(indices = ['eg1', 'eg2'], window = (-5, 5), n_points = 1000, name = "egBlock") + +g['eg1','eg1'] = SemiCircular(half_bandwidth = 1) +g['eg2','eg2'] = SemiCircular(half_bandwidth = 2) + +from pytriqs.plot.mpl_interface import oplot +oplot(g['eg1','eg1'], '-o', RI = 'S') # S : spectral function +oplot(g['eg2','eg2'], '-x', RI = 'S') + + diff --git a/doc/reference/python/green/block/green_retime.py b/doc/reference/python/green/block/green_retime.py new file mode 100644 index 00000000..7ef42bb8 --- /dev/null +++ b/doc/reference/python/green/block/green_retime.py @@ -0,0 +1,12 @@ +from pytriqs.gf.local import * + +gw = GfReFreq(indices = [1], window = (-5, 5), n_points = 300, name = "egBlock") +gw <<= SemiCircular(2.0) + +# This is a GfReTime +gt = gw.inverse_fourier() + +from pytriqs.plot.mpl_interface import oplot +oplot(gt.imag, '-o') + + diff --git a/doc/reference/python/green/descriptors.rst b/doc/reference/python/green/descriptors.rst new file mode 100644 index 00000000..d935d0c2 --- /dev/null +++ b/doc/reference/python/green/descriptors.rst @@ -0,0 +1,31 @@ + +.. index:: + single: Green's functions; initializers + +.. _descriptors: + +descriptors +------------ + +descriptors are simple objects that describe a function of frequencies +and permits to compute it with its high frequencies expansion. + +They can be combined into simple expressions. +Example: + +.. literalinclude:: impinbath.py + :lines: 1-13 + + +Reference +^^^^^^^^^^^^^ + +.. class:: pytriqs.gf.local.descriptors.Omega + + The function :math:`\omega \rightarrow \omega`. If used with Matsubara Green's functions, the corresponding + class member is called `iOmega_n`. + +.. automodule:: pytriqs.gf.local.descriptors + :members: Function,SemiCircular, Wilson + + diff --git a/doc/reference/python/green/example.py b/doc/reference/python/green/example.py new file mode 100644 index 00000000..ffd14e1c --- /dev/null +++ b/doc/reference/python/green/example.py @@ -0,0 +1,10 @@ +# Import the Green's functions +from pytriqs.gf.local import GfImFreq, iOmega_n, inverse + +# Create the Matsubara-frequency Green's function and initialize it +g = GfImFreq(indices = [1], beta = 50, n_points = 1000, name = "imp") +g <<= inverse( iOmega_n + 0.5 ) + +from pytriqs.plot.mpl_interface import oplot +oplot(g, '-o', x_window = (0,10)) + diff --git a/doc/reference/python/green/fourier.py b/doc/reference/python/green/fourier.py new file mode 100644 index 00000000..72fa1c40 --- /dev/null +++ b/doc/reference/python/green/fourier.py @@ -0,0 +1,11 @@ +from pytriqs.gf.local import * +from pytriqs.plot.mpl_interface import oplot,plt + +# A Green's function on the Matsubara axis set to a semicircular +gw = GfImFreq(indices = [1], beta = 50) +gw <<= SemiCircular(half_bandwidth = 1) + +# Create an imaginary-time Green's function and plot it +gt = GfImTime(indices = [1], beta = 50) +gt <<= InverseFourier(gw) +oplot(gt, '-') diff --git a/doc/reference/python/green/full.rst b/doc/reference/python/green/full.rst new file mode 100644 index 00000000..dc8f15ae --- /dev/null +++ b/doc/reference/python/green/full.rst @@ -0,0 +1,231 @@ +.. index:: + single: Green's functions; full Green's function + module: gf.local + +.. _fullgreen: + +The complete Green's function (BlockGf) +======================================= + +As mentioned in the introduction, due to the symmetry, a local Green's function usually +has a block structure. +We refer to this object as the `full` or `complete` Green's function, in contrast to +the blocks it is made of. + +Most properties of this object can be remembered by the simple sentence: + +`A full Green's function is an ordered dictionary name -> block, or equivalently a list of tuples (name, block).` + +The blocks can be any of the matrix-valued Green's functions described :ref:`above`. +The role of this object is to gather them, and simplify the code writing +by factorizing some simple operations. + +A little example +-------------------- + +To start with an example, imagine that the problem +that we consider could involve 5 d-bands of a solid that, for symmetry reasons, +are separated into 2 eg and 3 t2g bands. We therefore first construct the 2 +corresponding block Green's functions (in Matsubara frequencies for example) +and group these blocks into a full Green's function `G` with:: + + from pytriqs.gf.local import * + g1 = GfImFreq(indices = ['eg1','eg2'], beta = 50, n_points = 1000, name = "egBlock") + g2 = GfImFreq(indices = ['t2g1','t2g2','t2g3'], beta = 50, n_points = 1000, name = "t2gBlock") + G = BlockGf(name_list = ('eg','t2g'), block_list = (g1,g2), make_copies = False) + +where: + +* `NameList` is the ordered list of the names of the blocks. +* `BlockList` is the corresponding list of block Green's function. +* `Copy` lets you specify if the blocks of the full Green's function are **copies** of the blocks given in +* `BlockList` of if they are **views** of these blocks, see :ref:`below` + +These names will be used when we try to access a particular block, for example :: + + >>> G + Green's Function composed of 2 blocks at inverse temperature Beta = 50.0: + GfImFreq eg : Beta = 50.000; IndicesL = ['eg1', 'eg2'], IndicesR = ['eg1', 'eg2'] + GfImFreq t2g : Beta = 50.000; IndicesL = ['t2g1', 't2g2', 't2g3'], IndicesR = ['t2g1', 't2g2', 't2g3'] + + >>> G['eg'] + GfImFreq eg : Beta = 50.000; IndicesL = ['eg1', 'eg2'], IndicesR = ['eg1', 'eg2'] + + +Reference +---------------- + +.. autoclass:: pytriqs.gf.local.BlockGf + :members: copy, copy_from + + +Operations +--------------- + +The full Green's functions support various simple operations, that are simply done block by block. + +.. note:: + All these operations compute the array of data, but also, if present in the object, the high frequency expansion tail automatically. + +* compound operators, `+=`, `-=`, `*=`, `\=` : RHS can be a Green's function of the same type or an expression + +* arithmetic operations : `+`, `-`, `*`, `/`, e.g. :: + + G = G1 + 2*G2 + +* inversion, e.g. :: + + inv = inverse(g) + g2=inverse(inverse( g ) - sigma) # this is a Dyson equation + +Block access +---------------- + +Blocks can be accessed like in a `dict` : + +These names will be used when we try to access a particular block, for example :: + + G['eg'] + +The generic way to access a Green's function element :math:`G^a_{i j}` is therefore :: + + G[a][i,j] + +Iterator +-------------------- + +One can iterate on the blocks :: + + for name, g in G: + do_something() + +In the example above :: + + >>> for name, g in G: + ... print name, g + + eg GfImFreq eg : Beta = 50.000; IndicesL = ['eg1', 'eg2'], IndicesR = ['eg1', 'eg2'] + t2g GfImFreq t2g : Beta = 50.000; IndicesL = ['t2g1', 't2g2', 't2g3'], IndicesR = ['t2g1', 't2g2', 't2g3'] + + +As a result :: + + BlockGf( name_block_generator= G, copy=False) + +generates a new Green's function `G`, viewing the same blocks. +More interestingly :: + + BlockGf( name_block_generator= [ (index,g) for (index,g) in G if Test(index), copy=False)] + + +makes a partial view of some of the blocks selected by the `Test` condition. + +.. warning:: + The order in which the blocks appear is guaranteed to be the same as in the constructor. + This is why the Green's function is similar to an **ordered** dictionary, not a simple dict. + +View or copies ? +--------------------- +.. _fullgreencopypolicy: + +The Green's function is to be thought like a dict, hence accessing the +block returns references. When constructing the Green's function BlockGf, +the parameter `Copy` tells whether a copy of the block must be made before +putting them in the Green function or not. + +.. note:: + This is the standard behaviour in python for a list of a dict. + +Example: + +* If you define a Green's function with:: + + G = BlockGf(name_list = ('eg','t2g'), block_list = (g1,g2), make_copies = False) + + .. note:: + + Copy is optional, False is the default value. We keep it here for clarity. + + The ``Copy = False`` implies that the blocks of ``G`` are *references* ``g1`` and ``g2``. + So, if you modify ``g1``, say by putting it to zero with ``g1.zero()``, then the + first block of G will also be put to zero. Similarly, imagine you define two + Green's functions like this:: + + G1 = BlockGf(name_list = ('eg','t2g'), block_list = (g1,g2), make_copies = False) + G2 = BlockGf(name_list = ('eg','t2g'), block_list = (g1,g2), make_copies = False) + + Here G1 and G2 are exactly the same object, because they both have blocks + which are views of ``g1`` and ``g2``. + +* Instead, if you write:: + + G = BlockGf(name_list = ('eg','t2g'), block_list = (g1,g2), make_copies = True) + + The ``Copy = True`` ensures that the blocks of G are new copies of ``g1`` + and ``g2``. If you then modify ``g1`` it will not have any effect on G. + Clearly if you define:: + + G1 = BlockGf(name_list = ('eg','t2g'), block_list = (g1,g2), make_copies = True) + G2 = BlockGf(name_list = ('eg','t2g'), block_list = (g1,g2), make_copies = True) + + Here ``G1`` and ``G2`` are different objects, both having made copies + of ``g1`` and ``g2`` for their blocks. + + An equivalent writing is :: + + G1 = BlockGf(name_list = ('eg','t2g'), block_list = (g1.copy(),g2.copy())) + G2 = BlockGf(name_list = ('eg','t2g'), block_list = (g1.copy(),g2.copy())) + +shelve / pickle +--------------------- + +Green's functions are `pickable`, i.e. they support the standard python serialization techniques. + +* It can be used with the `shelve `_ and `pickle `_ module:: + + import shelve + s = shelve.open('myfile','w') + s['G'] = G # G is stored in the file. + +* It can be sent/broadcasted/reduced over mpi :: + + from pytriqs.utility import MPI + mpi.send (G, destination) + +.. warning:: + Shelve is not a portable format, it may change from python version to another (and it does). + For portability, we recommend using the HDF5 interface for storing data on disks. + + +HDF5 +-------- + +BlockGf are hdf-compatible with the following HDF5 data scheme + +The BlockGf(TRIQS_HDF5_data_scheme = "BlockGf") is decomposed in the following objects : + +========================= =========================== =========================================================================== +Name Type Meaning +========================= =========================== =========================================================================== +__BlockIndicesList string The python repr of the list of blocks, e.g. ('up', 'down') +__Name string Name of the Green's function block +__Note string Note +For each block name type of the block The Block Green's function +========================= =========================== =========================================================================== + +Example:: + + /Gtau Group + /Gtau/__BlockIndicesList Dataset {SCALAR} + /Gtau/__Name Dataset {SCALAR} + /Gtau/__Note Dataset {SCALAR} + /Gtau/down Group + /Gtau/down/Data Dataset {1, 1, 1000} + /Gtau/down/ ... + ... + /Gtau/up Group + /Gtau/up/Data Dataset {1, 1, 1000} + /Gtau/up/ ... + + + diff --git a/doc/reference/python/green/green.rst b/doc/reference/python/green/green.rst new file mode 100644 index 00000000..194ef256 --- /dev/null +++ b/doc/reference/python/green/green.rst @@ -0,0 +1,38 @@ + +.. index:: Green's functions + +.. module:: pytriqs.gf.local + +.. _green: + + +Green's functions +================= + +Green's functions are among the most important objects when dealing with +many-body problems. TRIQS makes it easy for you to manipulate them. Before +starting with some example, let us readily emphasize the essential notion +that Green's functions have a **block** structure: + +.. math:: + + G^a_{\alpha_a \beta_a} (\tau) = - \mathcal{T} + +Here, :math:`a` labels a block, while :math:`\alpha_a, \beta_a` are indices +**within** the block :math:`a`. In other words, there can be off-diagonal +elements within a block but not between blocks. Whenever possible, one should +take advantage of the symmetries of the problem under consideration and define +blocks for the Green's functions. + +In this documentation, we will start with the block Green's function, +and then proceed with the general Green's function and its block structure. + + +.. toctree:: + :maxdepth: 2 + + tutorial + block + transforms + full + diff --git a/doc/reference/python/green/impinbath.py b/doc/reference/python/green/impinbath.py new file mode 100644 index 00000000..8ce7c0dc --- /dev/null +++ b/doc/reference/python/green/impinbath.py @@ -0,0 +1,17 @@ +from pytriqs.gf.local import GfReFreq, Omega, Wilson, inverse +import numpy + +eps_d,V = 0.3, 0.2 + +# Create the real-frequency Green's function and initialize it +g = GfReFreq(indices = ['s','d'], window = (-2, 2), n_points = 1000, name = "s+d") +g['d','d'] = Omega - eps_d +g['d','s'] = V +g['s','d'] = V +g['s','s'] = inverse( Wilson(1.0) ) +g.invert() + +# Plot it with matplotlib. 'S' means: spectral function ( -1/pi Imag (g) ) +from pytriqs.plot.mpl_interface import oplot +oplot( g['d','d'], '-o', RI = 'S', x_window = (-1.8,1.8), name = "Impurity" ) +oplot( g['s','s'], '-x', RI = 'S', x_window = (-1.8,1.8), name = "Bath" ) diff --git a/doc/reference/python/green/legendre.py b/doc/reference/python/green/legendre.py new file mode 100644 index 00000000..cfc72669 --- /dev/null +++ b/doc/reference/python/green/legendre.py @@ -0,0 +1,12 @@ +from pytriqs.gf.local import * +from pytriqs.plot.mpl_interface import oplot,plt + +# A Green's function on the Matsubara axis set to a semicircular +gw = GfImFreq(indices = [1], beta = 50) +gw <<= SemiCircular(half_bandwidth = 1) + +# Create a Legendre Green's function with 40 coefficients +# initialize it from gw and plot it +gl = GfLegendre(indices = [1], beta = 50, n_points = 40) +gl <<= MatsubaraToLegendre(gw) +oplot(gl, '-o') diff --git a/doc/reference/python/green/transforms.rst b/doc/reference/python/green/transforms.rst new file mode 100644 index 00000000..6da992d6 --- /dev/null +++ b/doc/reference/python/green/transforms.rst @@ -0,0 +1,33 @@ +.. index:: + single: Transforming Green's functions + + +Fourier and Legendre to Matsubara transforms +============================================ + +Here are the different ways to transform Green's functions of one type into a different type. + +Time to frequency +----------------- + +The command ``Fourier`` (``InverseFourier``) allows you to initialize a block +Green's function defined in frequency (time) from a block Green's function defined +in time (frequency). Here's a simple example: + +.. plot:: reference/python/green/fourier.py + :include-source: + :scale: 70 + +The same command can be used for real-time, real-frequency transformations. + +Legendre to Matsubara +--------------------- + +The commands ``MatsubaraToLegendre`` and ``LegendreToMatsubara`` allow to +initialize a Matsubara Green's function (either in imaginary time or in +imaginary frequencies) from a Legendre Green's function and conversely. +Example: + +.. plot:: reference/python/green/legendre.py + :include-source: + :scale: 70 diff --git a/doc/reference/python/green/tutorial.rst b/doc/reference/python/green/tutorial.rst new file mode 100644 index 00000000..a9ac237d --- /dev/null +++ b/doc/reference/python/green/tutorial.rst @@ -0,0 +1,109 @@ +.. index:: Green's functions + +A little tutorial +######################### + +In this first part, we present a couple of examples in the form of a tutorial. +The full reference is presented in the next sections. + +A simple example +---------------- + +As a first example, we construct and plot the following Matsubara Green's function: + +.. math:: + + G_{11} (i \omega_n) = \frac{1}{i \omega_n + 0.5} + +This is done with the code : + +.. plot:: reference/python/green/example.py + :include-source: + :scale: 70 + +In this very simple example, the Green's function is just a 1x1 block. Let's go through +the different steps of the example: + +.. literalinclude:: example.py + :lines: 1-2 + +This imports all the necessary classes to manipulate Green's functions. In this example it allows +to use ``GfImFreq``, ``BlockGf`` : + +.. literalinclude:: example.py + :lines: 4-5 + +This creates a **block** Green's function which has just one index +(1). ``Beta`` is the inverse temperature, ``NFreqMatsubara`` the number of +Matsubara frequencies. + +.. literalinclude:: example.py + :lines: 6-6 + +This initializes the block with :math:`1/(i \omega_n + 0.5)`. +Two points are worth noting here : + +* The right hand side (RHS) of this statement is a *lazy* expression : its evaluation is delayed until + it is needed to fill the Green function. + +* The funny *<<=* operator means "set from". It fills the Green function with the evaluation of the expression + at the right. + + +.. literalinclude:: example.py + :lines: 9-10 + +These lines plot the block Green's function (both the real and imaginary parts) using +the matplotlib plotter. More details can be found in the section +:ref:`plotting`. + +A slightly more complicated example +-------------------------------------------------- + +Let's turn to another example. This time we consider a problem of a d-impurity +level embedded in a flat conduction bath :math:`\Delta` of s-electrons. We want to +construct the corresponding 2x2 Green's function: + +.. math:: + + \hat{G}^\mathrm{s+d} (i \omega_n) = \begin{pmatrix} i\omega_n - \epsilon_d & V \\ V & \Delta^{-1} \end{pmatrix}^{-1} + +This is done with the code : + +.. plot:: reference/python/green/impinbath.py + :include-source: + :scale: 70 + +Again, the Green's function is just one block, but this time it is a 2x2 block with +off-diagonal elements. Another difference is that we use real-frequency Green's functions in +this example: + +.. literalinclude:: impinbath.py + :lines: 6-7 + +In this constructor for the block Green's function, we specify that there are two indices s and d. +Because it is a real-frequency Green's function we need to define the mesh on which it is +computed. This is done with the ``MeshArray`` option. + +.. literalinclude:: impinbath.py + :lines: 8-11 + +These lines initialize specific entries of the block Green's function. Note how the elements are +accessed with ``[index1,index2]``. These lines also show how to initialize a Green's function +to a constant or to the inverse of a Wilson bath (constant spectral function on an interval [-D,D], with +D=1.0 in our example). + +.. literalinclude:: impinbath.py + :lines: 12-12 + +``invert()`` inverts the entire block Green's function (as a matrix). + +.. literalinclude:: impinbath.py + :lines: 14-17 + +Here, we isolate some elements of the blocks Green's function. It is also the +first example of an operation on the block Green's function, which is +multiplied by a scalar. The last lines of the script just plot these new +objects. + + diff --git a/doc/reference/python/lattice/bravais.rst b/doc/reference/python/lattice/bravais.rst new file mode 100644 index 00000000..9f97d01b --- /dev/null +++ b/doc/reference/python/lattice/bravais.rst @@ -0,0 +1,13 @@ +.. index:: + single: lattices; Bravais lattice + +.. _bravaislattice: + + +Bravais Lattice +=============== + +.. autoclass:: pytriqs.lattice.tight_binding.BravaisLattice + :members: + :undoc-members: + diff --git a/doc/reference/python/lattice/dos.rst b/doc/reference/python/lattice/dos.rst new file mode 100644 index 00000000..6156f953 --- /dev/null +++ b/doc/reference/python/lattice/dos.rst @@ -0,0 +1,35 @@ +.. index:: lattices; dos + +.. module:: pytriqs.dos.dos + +.. _dos: + +Density of state and related tools +======================================= + + +The Density of state : DOS +--------------------------------- + +.. autoclass:: pytriqs.dos.DOS + :members: + :undoc-members: + +Reading a DOS from a text file +--------------------------------- + +.. autofunction:: pytriqs.dos.dos_from_file + +Computing a DOS from a tight_binding +---------------------------------------------- + +.. autofunction:: pytriqs.lattice.tight_binding.dos + +The DOS computed from a function +----------------------------------------------- + +.. autoclass:: pytriqs.dos.DOSFromFunction + :members: + :undoc-members: + + diff --git a/doc/reference/python/lattice/ex1.png b/doc/reference/python/lattice/ex1.png new file mode 100644 index 0000000000000000000000000000000000000000..546855ea9673a5669f3010a2e90f8f53cb55bf3a GIT binary patch literal 27250 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 TGmjtQASwDbGlLvGyTJbd@&y%3 literal 0 HcmV?d00001 diff --git a/doc/reference/python/lattice/ex1.py b/doc/reference/python/lattice/ex1.py new file mode 100644 index 00000000..3a4d8148 --- /dev/null +++ b/doc/reference/python/lattice/ex1.py @@ -0,0 +1,40 @@ +from pytriqs.lattice.tight_binding import * + +# Define the Bravais Lattice : a square lattice in 2d +BL = BravaisLattice(Units = [(1,0,0) , (0,1,0) ], orbital_positions= {"" : (0,0,0)} ) + +# Prepare a nearest neighbour hopping on BL +t = -1.00 # First neighbour Hopping +tp = 0.0*t # Second neighbour Hopping + +# Hopping[ Displacement on the lattice] = [[t11,t12,t13....],[t21,t22,t23....],...,[....,tnn]] +# where n=Number_Orbitals +hop= { (1,0) : [[ t]], + (-1,0) : [[ t]], + (0,1) : [[ t]], + (0,-1) : [[ t]], + (1,1) : [[ tp]], + (-1,-1): [[ tp]], + (1,-1) : [[ tp]], + (-1,1) : [[ tp]]} + +TB = TightBinding ( BL, hop) + +# Compute the density of states +d = dos (TB, n_kpts= 500, n_eps = 101, name = 'dos')[0] + +# Plot the dos it with matplotlib +from pytriqs.plot.mpl_interface import oplot +from matplotlib import pylab as plt +oplot(d,'-o') +plt.xlim ( -5,5 ) +plt.ylim ( 0, 0.4) + + + + + +plt.savefig("./ex1.png") + + + diff --git a/doc/reference/python/lattice/ex_Hilbert.py b/doc/reference/python/lattice/ex_Hilbert.py new file mode 100644 index 00000000..4b860ec3 --- /dev/null +++ b/doc/reference/python/lattice/ex_Hilbert.py @@ -0,0 +1,28 @@ +from pytriqs.lattice.tight_binding import * +from pytriqs.dos import HilbertTransform +from pytriqs.gf.local import GfImFreq + +# Define a DOS (here on a square lattice) +BL = BravaisLattice(Units = [(1,0,0) , (0,1,0) ], orbital_positions= {"" : (0,0,0)} ) +t = -1.00 # First neighbour Hopping +tp = 0.0*t # Second neighbour Hopping +hop= { (1,0) : [[ t]], + (-1,0) : [[ t]], + (0,1) : [[ t]], + (0,-1) : [[ t]], + (1,1) : [[ tp]], + (-1,-1): [[ tp]], + (1,-1) : [[ tp]], + (-1,1) : [[ tp]]} + +TB = TightBinding (BL, hop) +d = dos(TB, n_kpts= 500, n_eps = 101, name = 'dos')[0] + +#define a Hilbert transform +H = HilbertTransform(d) + +#fill a Green function +G = GfImFreq(indices = ['up','down'], beta = 20) +Sigma0 = GfImFreq(indices = ['up','down'], beta = 20); Sigma0.zero() +G <<= H(Sigma = Sigma0,mu=0.) + diff --git a/doc/reference/python/lattice/hilbert.rst b/doc/reference/python/lattice/hilbert.rst new file mode 100644 index 00000000..0f1c5f48 --- /dev/null +++ b/doc/reference/python/lattice/hilbert.rst @@ -0,0 +1,29 @@ + +.. _hilbert_transform: + +.. module:: pytriqs.dos.hilbert_transform + + +Hilbert Transform +======================================= +TRIQS comes with a Hilbert transform. Let us look at an example: + +.. literalinclude:: ex_Hilbert.py + + +Given a density of states `d` (here for a tight-binding model), the Hilbert transform `H` is defined is defined in the following way:: + + H = HilbertTransform(d) + +To construct a Green's function:: + + G = GfImFreq(indices = ['up','down'], beta = 20) + Sigma0 = GfImFreq(indices = ['up','down'], beta = 20); Sigma0.zero() + G <<= H(Sigma = Sigma0, mu=0.) + + +.. autoclass:: pytriqs.dos.HilbertTransform + :members: __call__ + :undoc-members: + + diff --git a/doc/reference/python/lattice/lattice.rst b/doc/reference/python/lattice/lattice.rst new file mode 100644 index 00000000..2ffbd1a0 --- /dev/null +++ b/doc/reference/python/lattice/lattice.rst @@ -0,0 +1,40 @@ +.. index:: lattices + +.. module:: pytriqs.lattice + +.. _lattice: + +Lattice Tools +============= + +TRIQS comes with a couple of modules that allow to work with free fermions on Bravais lattices, with +tight-binding hoppings. + +.. warning:: + This part of the documentation largely is work in progress ... + +Introductory example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. literalinclude:: ex1.py + :lines: 1-34 + +Here, we take the simple square lattice in d=2 and compute the density of state. It produces : + +.. image:: ex1.png + :width: 700 + :align: center + +Reference manual +^^^^^^^^^^^^^^^^^^^^^^ + + +.. toctree:: + + bravais + tightbinding + dos + hilbert + sumk + + diff --git a/doc/reference/python/lattice/sumk.rst b/doc/reference/python/lattice/sumk.rst new file mode 100644 index 00000000..5ab02afe --- /dev/null +++ b/doc/reference/python/lattice/sumk.rst @@ -0,0 +1,13 @@ +.. index:: lattices; k-sums + +.. _sumk: + +Sums over Brillouin zone +================================ + +.. autoclass:: pytriqs.sumk.SumkDiscreteFromLattice + :members: + :inherited-members: + :undoc-members: + + diff --git a/doc/reference/python/lattice/tightbinding.rst b/doc/reference/python/lattice/tightbinding.rst new file mode 100644 index 00000000..f516f9c8 --- /dev/null +++ b/doc/reference/python/lattice/tightbinding.rst @@ -0,0 +1,9 @@ + +Free Fermions with tight binding hopping +=============================================== + + +.. autoclass:: pytriqs.lattice.tight_binding.TightBinding + :members: + :undoc-members: + diff --git a/doc/reference/python/misc/python-powered-w-200x80.png b/doc/reference/python/misc/python-powered-w-200x80.png new file mode 100644 index 0000000000000000000000000000000000000000..c56d4c022a7130beed2ee67d7fff7274aff5de1e GIT binary patch literal 8758 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 +
+ {%- if logo %} + + {%- endif %} + {%- block headertitle %} +

{{ shorttitle|e }}

+ {%- endblock %} +
+ HOME | + {%- for rellink in rellinks %} + {{ rellink[3] }} + {%- if not loop.last %}{{ reldelim2 }}{% endif %} + {%- endfor %} +
+
+ +{% endblock %} + +{% block content %} +
+
+
+ {%- block document %} + {{ super() }} + {%- endblock %} +
+ +
+
+
+{% endblock %} + +{% block footer %} + +{% endblock %} + +{% block relbar1 %}{% endblock %} +{% block relbar2 %}{% endblock %} diff --git a/doc/themes/agogo/static/agogo.css_t b/doc/themes/agogo/static/agogo.css_t new file mode 100644 index 00000000..5e4b0c66 --- /dev/null +++ b/doc/themes/agogo/static/agogo.css_t @@ -0,0 +1,519 @@ +/* + * agogo.css_t + * ~~~~~~~~~~~ + * + * Sphinx stylesheet -- agogo theme. + * + * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +* { + margin: 0px; + padding: 0px; +} + +body { + font-family: {{ theme_bodyfont }}; + font-size: 100%; // TRIQS + line-height: 1.0em; // TRIQS + color: black; + background-color: {{ theme_bgcolor }}; +} + + +/* Page layout */ + +div.header, div.content, div.footer { + width: {{ theme_pagewidth }}; + margin-left: auto; + margin-right: auto; +} + +div.header-wrapper { + background: {{ theme_headerbg }}; + border-bottom: 3px solid #2e3436; +} + + +/* Default body styles */ +a { + color: {{ theme_linkcolor }}; +} + +div.bodywrapper a, div.footer a { + text-decoration: none; // TRIQS +} + +div.bodywrapper a:hover, div.footer a:hover { + text-decoration: underline; // TRIQS +} + +.clearer { + clear: both; +} + +.left { + float: left; +} + +.right { + float: right; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +h1, h2, h3, h4 { + font-family: {{ theme_headerfont }}; + font-weight: normal; + color: {{ theme_headercolor2 }}; + margin-bottom: .8em; +} + +h1 { + color: {{ theme_headercolor1 }}; +} + +h2 { + padding-bottom: .5em; + border-bottom: 1px solid {{ theme_headercolor2 }}; +} + +a.headerlink { + visibility: hidden; + color: #dddddd; + padding-left: .3em; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + +img { + border: 0; +} + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 2px 7px 1px 7px; + border-left: 0.2em solid black; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; + color: red; // TRIQS +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +/* Header */ + +div.header { + padding-top: 10px; + padding-bottom: 10px; +} + +div.header h1 { + font-family: {{ theme_headerfont }}; + font-weight: normal; + font-size: 180%; + letter-spacing: .08em; +} + +div.header h1 a { + color: white; +} + +div.header div.rel { + margin-top: -1em; // TRIQS +} + +div.header div.rel a { + color: {{ theme_headerlinkcolor }}; + letter-spacing: .1em; + text-transform: uppercase; +} + +p.logo { + float: right; +} + +img.logo { + border: 0; +} + + +/* Content */ +div.content-wrapper { + background-color: white; + padding-top: 20px; + padding-bottom: 20px; +} + +div.document { + width: {{ theme_documentwidth }}; + float: left; +} + +div.body { + padding-right: 2em; + text-align: {{ theme_textalign }}; +} + +div.document ul { + margin: 1.5em; + list-style-type: square; +} + +div.document dd { + margin-left: 1.2em; + margin-top: .4em; + margin-bottom: 1em; +} + +div.document .section { + margin-top: 1.7em; +} +div.document .section:first-child { + margin-top: 0px; +} + +div.document div.highlight { + line-height: 1.0em; // TRIQS + padding: 3px; + background-color: #eeeeec; + border-top: 2px solid #dddddd; + border-bottom: 2px solid #dddddd; + margin-top: .8em; + margin-bottom: .8em; +} + +div.document h2 { + margin-top: .7em; +} + +div.document p { + margin-bottom: .5em; +} + +div.document li.toctree-l1 { + margin-bottom: 0em; // TRIQS +} +div.document li.toctree-l2 { + margin-bottom: 0em; // TRIQS +} + +div.document .descname { + font-weight: bold; + color: blue; // TRIQS +} + +div.document .docutils.literal { + background-color: #eeeeec; + padding: 1px; +} + +div.document .docutils.xref.literal { + background-color: transparent; + padding: 0px; +} + +div.document blockquote { + margin: 1em; +} + +div.document ol { + margin: 1.5em; +} + + +/* Sidebar */ + +div.sidebar { + width: {{ theme_sidebarwidth }}; + float: right; + font-size: .9em; +} + +div.sidebar a, div.header a { + text-decoration: none; +} + +div.sidebar a:hover, div.header a:hover { + text-decoration: underline; +} + +div.sidebar h3 { + color: #2e3436; + text-transform: uppercase; + font-size: 130%; + letter-spacing: .1em; +} + +div.sidebar ul { + list-style-type: none; +} + +div.sidebar li.toctree-l1 a { + display: block; + padding: 1px; + border: 1px solid #dddddd; + background-color: #eeeeec; + margin-bottom: .4em; + padding-left: 3px; + color: #2e3436; +} + +div.sidebar li.toctree-l2 a { + background-color: transparent; + border: none; + margin-left: 1em; + border-bottom: 1px solid #dddddd; +} + +div.sidebar li.toctree-l3 a { + background-color: transparent; + border: none; + margin-left: 2em; + border-bottom: 1px solid #dddddd; +} + +div.sidebar li.toctree-l2:last-child a { + border-bottom: none; +} + +div.sidebar li.toctree-l1.current a { + border-right: 5px solid {{ theme_headerlinkcolor }}; +} + +div.sidebar li.toctree-l1.current li.toctree-l2 a { + border-right: none; +} + + +/* Footer */ + +div.footer-wrapper { + background: {{ theme_footerbg }}; + border-top: 4px solid #babdb6; + padding-top: 10px; + padding-bottom: 10px; + min-height: 80px; +} + +div.footer, div.footer a { + color: #888a85; +} + +div.footer .right { + text-align: right; +} + +div.footer .left { + text-transform: uppercase; +} + + +/* Styles copied from basic theme */ + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 100%; +} + +table.contentstable td { + padding: 10px 10px 10px 0; +} + +table.contentstable p.biglink { + line-height: 150%; + text-align: left; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +/* -- viewcode extension ---------------------------------------------------- */ + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family:: {{ theme_bodyfont }}; +} + +div.viewcode-block:target { + margin: -1px -3px; + padding: 0 3px; + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} + +/* -- added for TRIQS ------------------------------------------------------- */ + +div.warning { + margin: 1em 0 1em 0; + border: 1px solid #86989B; + background-color: lightpink; //#f7f7f7; +} + +div.note { + margin: 1em 0 1em 0; + border: 1px solid #86989B; + background-color: lightcyan; //#f7f7f7; +} + +div.note p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; + color : blue; +} + +div.highlight-python { + margin-top : 5px; + margin-bottom : 7px; + background-color: lightcyan; //#f4debf; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table.docutils head { + color : blue; +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.field-list td, table.field-list th { + border: 0 !important; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + diff --git a/doc/themes/agogo/static/bgfooter.png b/doc/themes/agogo/static/bgfooter.png new file mode 100644 index 0000000000000000000000000000000000000000..9ce5bdd902943fdf8b0c0ca6a545297e1e2cc665 GIT binary patch literal 434 zcmV;j0ZsmiP)Px#24YJ`L;%wO*8tD73qoQ5000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXD> z2Q(2CT#42I000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0003ENklR?sq9~H`=l5UI-{JW_f9!)=Hwush3JC}Y z1gFM&r>$lJNPt^*1k!w;l|obx>lr$2IOaI$n=(gBBaj^I0=y%@K5N&GIU&-%OE_~V zX=m=_j7d`hvubQRuF+xT63vIfWnC3%kKN*T3l7ob3nEC2R->wU1Y)4)(7_t^thiqb zj$CO7xBn9gg`*!MY$}SI|_*)!a*&V0w7h>cUb&$Grh37iJ=C%Yn c>}w1E0Z4f>1OEiDlmGw#07*qoM6N<$g4BwtIsgCw literal 0 HcmV?d00001 diff --git a/doc/themes/agogo/static/bgtop.png b/doc/themes/agogo/static/bgtop.png new file mode 100644 index 0000000000000000000000000000000000000000..a0d4709bac8f79943a817195c086461c8c4d5419 GIT binary patch literal 430 zcmV;f0a5;mP)Px#24YJ`L;zI)R{&FzA;Z4_000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXD> z2Q3AZhV-)l000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0003ANklMo8vqN`cM=KwSQV|n zk}naE+VzlN;kK@Ej${PSkI$-R6-Yfp`zA;^O$`)7`gRi{-0i?owGIbX{p>Nc##93U z;sA|ayOYkG%F9M0iEMUM*s3NDYSS=KN2ht8Rv|7nv77i{NTO47R)}V_+2H~mL-nTR z_8j}*%6Qm8?#7NU2kM$#gcP&kO?iw|n}ynz+r-~FA9nKcZnfixWvZ&d28Cc_6&_Pe zMpbjI>9r+<=}NIDz4mCd3U++H?rrHcYxH&eeB|)>mnv*N#44ILM2zL6yU!VVWSrgp Y0Yu&#qm)=by8r+H07*qoM6N<$f@HC)j{pDw literal 0 HcmV?d00001 diff --git a/doc/themes/agogo/theme.conf b/doc/themes/agogo/theme.conf new file mode 100644 index 00000000..e2108d96 --- /dev/null +++ b/doc/themes/agogo/theme.conf @@ -0,0 +1,20 @@ +[theme] +inherit = basic +stylesheet = agogo.css +pygments_style = tango + +[options] +bodyfont = "Verdana", Arial, sans-serif +headerfont = "Georgia", "Times New Roman", serif +pagewidth = 80% +documentwidth = 75% +sidebarwidth = 22.5% +bgcolor = #eeeeec +headerbg = url(bgtop.png) top left repeat-x +footerbg = url(bgfooter.png) top left repeat-x +linkcolor = #ce5c00 +headercolor1 = #204a87 +headercolor2 = #3465a4 +headerlinkcolor = #fcaf3e +textalign = justify +index = index diff --git a/doc/tutorials/c++/contents.rst b/doc/tutorials/c++/contents.rst new file mode 100644 index 00000000..62870786 --- /dev/null +++ b/doc/tutorials/c++/contents.rst @@ -0,0 +1,8 @@ +C++ libraries +================================= + +.. toctree:: + :maxdepth: 1 + + ../../reference/c++/arrays/cookbook/contents + ../../reference/c++/gf/cookbook/contents diff --git a/doc/tutorials/contents.rst b/doc/tutorials/contents.rst new file mode 100644 index 00000000..fb281c53 --- /dev/null +++ b/doc/tutorials/contents.rst @@ -0,0 +1,10 @@ +Tutorials +================= + +.. toctree:: + :maxdepth: 2 + + intro + python/introduction + c++/contents + diff --git a/doc/tutorials/python/aim_plot1.png b/doc/tutorials/python/aim_plot1.png new file mode 100644 index 0000000000000000000000000000000000000000..5cb5709c7a096303b917f014ad7f262dc44b48cf GIT binary patch literal 35018 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 IL+|`). +It is implemented as a `Python `_ library, with Python, C++ and Fortran codes and contains : + +* Various basic objects e.g. : + + * Local Green's functions of various kinds. + * Bravais lattices, tight-binding hoppings, local density of states, superlattices (for cluster methods) + * Some simple *k*-sums over the Brillouin zone. + +* Optional extension modules : + + * Quantum impurity solvers : + + * :ref:`Continuous-time hybridization Quantum Monte Carlo `. + * :ref:`Hubbard I `. + + * :ref:`Wien2TRIQS ` : an interface to the Wien2k electronic structure code for performing LDA+DMFT computations. + +The rest of the introduction is a little demo of examples used elsewhere in the documentation. +The goal is not to explain them here in details but to quickly show some of TRIQS's current capabilities. + +.. toctree:: + :maxdepth: 1 + + tour1 + tour2 + tour3 + tour4 + reading + diff --git a/doc/tutorials/python/logo.png b/doc/tutorials/python/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cc2ff1d54a360d61a7a98301932a1184f3358822 GIT binary patch literal 14699 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 mQJ49DzkU1vLw5sWJ)ufd2uCfV5-) literal 0 HcmV?d00001 diff --git a/doc/tutorials/python/reading.rst b/doc/tutorials/python/reading.rst new file mode 100644 index 00000000..d29513ee --- /dev/null +++ b/doc/tutorials/python/reading.rst @@ -0,0 +1,29 @@ + +Recommended reading and references +---------------------------------------------------------- + +* A good set of lectures is the `Scipy lecture notes `_. + +* A good starting point to learn about scientific computing with Python and related ideas is + `Software carpentry `_, which provides nice video/slides `lectures on Python `_ + +* To learn the Python language itself the recommended starting point is the standard `python tutorial `_. + +* Python has a large number of libraries, which can be used in combination with TRIQS. For example, + + * The Python's `standard library `_ is already very rich. + + * `Numpy `_ allows to manipulate multidimensionnal arrays (cf also the `tutorial `_). + + * `Scipy `_ includes many packages for scientific computing. + + * `Matplotlib `_ offers very nice plotting possibilities. + + * `SymPy `_ provides some formal computing capabilities. + + * `Cython `_ is a quick way to build simple `C` modules in computationally intense case. For more complex situations we use boost.python tools. + + + + + diff --git a/doc/tutorials/python/tour1.rst b/doc/tutorials/python/tour1.rst new file mode 100644 index 00000000..4f4ad977 --- /dev/null +++ b/doc/tutorials/python/tour1.rst @@ -0,0 +1,26 @@ + + +Tour 1: Manipulations with local Green functions +------------------------------------------------ + +Let use start with a problem of free electrons : an impurity `d` +level embedded in a flat conduction bath :math:`\Delta` of `s`-electrons. +To construct and plot the corresponding 2x2 Green's function: + +.. math:: + + \hat{G}^\mathrm{s+d} ( \omega) = \begin{pmatrix} \omega - \epsilon_d & V \\ V & \Delta^{-1} \end{pmatrix}^{-1} + +we first create the corresponding energy +mesh `a` on the real axis in the energy interval :math:`\omega \in (-2:2]` +The Green's function is generated using classes of the ``gf.local`` module by setting up +:math:`\left[\hat{G}^\mathrm{s+d}\right]^{-1}` and inverting it. +Finally, the obtained bath and impurity densities of states are plotted using the TRIQS function ``oplot``: + +.. plot:: reference/python/green/impinbath.py + :include-source: + :scale: 70 + +You will find more information on the local Green's function implementation in TRIQS in :ref:`the corresponding chapter of the manual ` + + diff --git a/doc/tutorials/python/tour2.rst b/doc/tutorials/python/tour2.rst new file mode 100644 index 00000000..bd183c9a --- /dev/null +++ b/doc/tutorials/python/tour2.rst @@ -0,0 +1,20 @@ + + +Tour 2: A tight-binding model on a square lattice +------------------------------------------------- + +Let us now consider free fermions on a Bravais lattice. +We will set up a square lattice with the nearest +neighbour hopping using the ``BravaisLattice`` class of TRIQS, compute its +density of states (DOS) and then plot it by using again the ``oplot`` function. + + +.. literalinclude:: ../lattice/ex1.py + :lines: 1-34 + +.. image:: ../lattice/ex1.png + :width: 700 + :align: center + +More information on the lattice tools implemeted in TRIQS can be :ref:`found here ` + diff --git a/doc/tutorials/python/tour3.rst b/doc/tutorials/python/tour3.rst new file mode 100644 index 00000000..ab3a7c62 --- /dev/null +++ b/doc/tutorials/python/tour3.rst @@ -0,0 +1,47 @@ + + +Tour 3: Solving a quantum impurity model with QMC +---------------------------------------------------------- + +Free electrons are nice, but the `I` in TRIQS means `interacting`. +So let us solve a simple one-band Anderson impurity model + +.. math:: + + \mathcal{H}_\mathrm{loc} = U n_\uparrow n_\downarrow, + +where the non-interacting Green's function is: + +.. math:: + + G^{-1}_{0,\sigma} (i \omega_n) = i \omega_n - \epsilon_f - V^2 \Gamma_\sigma(i \omega_n). + +In this example, an impurity with the non-interacting level position at energy :math:`\epsilon_f` and on-site Coulomb repulsion :math:`U` is embedded into an electronic bath. +The +electronic bath has a flat density of states over the interval +:math:`[-1,1]` and hybridizes with the impurity with the amplitude :math:`V`. + +We solve this model using the hybridization expansion Continuous Time Quantum Monte Carlo method (CT-Hyb) +proposed by `P. Werner et al. `_ + +To this end we first initialize the ``Solver`` class of the TRIQS CT-Hyb implementaion +``pytriqs.applications.impurity_solvers.ctqmc_hyb``. +Then, after having constructed the non-interacting Green's function :math:`G^{-1}_{0,\sigma}`, +we launch the CT-Hyb calculations by calling the ``Solve`` method of the ``Solver`` class. +Finally, the resulting interacting Green's function as well as average impurity occupancy +is stored in the :ref:`HDF5 format`. + + +.. literalinclude:: ../solvers/aim.py + +The result can be then read from the ``HDF5`` file and plotted using the ``oplot`` function: + +.. literalinclude:: aim_plot.py + +.. image:: aim_plot1.png + :width: 700 + :align: center + + +We go through this example in more details in the tutorial :ref:`Anderson impurity model ` + diff --git a/doc/tutorials/python/tour4.rst b/doc/tutorials/python/tour4.rst new file mode 100644 index 00000000..a8d6151b --- /dev/null +++ b/doc/tutorials/python/tour4.rst @@ -0,0 +1,24 @@ + +Tour 4: Dynamical Mean Field Theory on a Bethe lattice +------------------------------------------------------ + +In the case of Bethe lattice the dynamical mean-field theory (DMFT) self-consistency condition takes a particularly simple form + +.. math:: + + G^{-1}_{0,\sigma} (i \omega_n) = i \omega_n + \mu - t^2 G_{\sigma} (i \omega_n). + + +Hence, from a strictly technical point of view, in this case DMFT cycle can be implemented by modifying +the previous single-impurity example to the case of a bath with semi-circular density of states and adding a python loop to update :math:`G_0` as function of :math:`G`. + +Here is a complete program doing this plain vanilla DMFT on a half-filled one-band Bethe lattice: + + +.. literalinclude:: ../solvers/dmft/single_site_bethe.py + + +A general introduction to DMFT calculations with TRIQS can be found :ref:`here ` + +Chapter :ref:`Wien2TRIQS ` discusses the TRIQS implementation for DMFT calculations of real materials and the interface between TRIQS and the Wien2k band structure code. + diff --git a/examples/simple/CMakeLists.txt b/examples/simple/CMakeLists.txt new file mode 100644 index 00000000..5f72b9b6 --- /dev/null +++ b/examples/simple/CMakeLists.txt @@ -0,0 +1,10 @@ +list(APPEND CMAKE_MODULE_PATH ${TRIQS_PATH}/share/triqs/cmake) +cmake_minimum_required(VERSION 2.8) +project(myproj CXX) +set(CMAKE_BUILD_TYPE Release) + +find_package(TRIQS) + +add_executable(hdf5 hdf5.cpp) +include_directories(${TRIQS_INCLUDE_ALL}) +target_link_libraries(hdf5 ${TRIQS_LIBRARY_ALL}) diff --git a/examples/simple/hdf5.cpp b/examples/simple/hdf5.cpp new file mode 100644 index 00000000..134d08f9 --- /dev/null +++ b/examples/simple/hdf5.cpp @@ -0,0 +1,104 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include + +using std::cout; using std::endl; +namespace tqa = triqs::arrays; +namespace h5 = triqs::h5; +using tqa::range; + +template +std::ostream & operator << (std::ostream & out, std::vector const & v) { +for (size_t i =0; i A (2,3),B,vc; + tqa::array D (2,3), D2; + + tqa::array Af(FORTRAN_LAYOUT),Bf(FORTRAN_LAYOUT),vf(FORTRAN_LAYOUT); + + tqa::array,1> C(5), C2; + std::complex z(1,2); + + for (int i =0; i<5; ++i) { + C(i) = std::complex(i,i); + } + + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + { + A(i,j) = 10*i+ j; + D (i,j) = A(i,j) / 10.0; + } + + Af = A; + + std::cout<<" A= "< E; h5_read (top, "A",E); std::cout<< "E = "<< E<>>', source + more = console.runsource(source) + while more: + next_line = source_lines.next() + print '...', next_line + source += '\n' + next_line + more = console.runsource(source) + except StopIteration: + if more: + print '... ' + more = console.runsource(source + '\n') + + + +if __name__ == '__main__': + main() + + +# vim: set expandtab shiftwidth=4 softtabstop=4 : + diff --git a/foreignlibs/boost/CMakeLists.txt b/foreignlibs/boost/CMakeLists.txt new file mode 100644 index 00000000..938ab32d --- /dev/null +++ b/foreignlibs/boost/CMakeLists.txt @@ -0,0 +1,90 @@ +# boost libraries +# python and mpi have already be set before. +# here add the other boost part we want to compile + +# we can not be here if boost is installed.. just check +if(NOT BOOST_SOURCE_DIR) + message( FATAL_ERROR " cmake error in boost") +endif(NOT BOOST_SOURCE_DIR) + +# Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp +# Read the whole file: +# +set(BOOST_VERSION 0) +set(BOOST_LIB_VERSION "") +file(READ "${BOOST_SOURCE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS) +# message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp") + +string(REGEX REPLACE ".*#define BOOST_VERSION ([0-9]+).*" "\\1" Boost_VERSION "${_boost_VERSION_HPP_CONTENTS}") +string(REGEX REPLACE ".*#define BOOST_LIB_VERSION \"([0-9_]+)\".*" "\\1" Boost_LIB_VERSION "${_boost_VERSION_HPP_CONTENTS}") + +if(NOT "${Boost_VERSION}" STREQUAL "0") + math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") + math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") + math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") + + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") +endif(NOT "${Boost_VERSION}" STREQUAL "0") + +message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "version.hpp reveals boost " + "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") + + ### +set(BOOST_INCLUDE_DIR ${BOOST_INSTALL_ROOT_DIR}/include PARENT_SCOPE) + +# Test version is high enough ... +if(CMAKE_COMPILER_IS_ICC) + if ( "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}" VERSION_LESS "1.53.0") + MESSAGE(FATAL_ERROR "With Intel compiler, you need boost version >= 1.53, while this is ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION} ") + endif() +endif() + +MESSAGE(STATUS "I am using boost sources from ${BOOST_SOURCE_DIR} to compile a mini boost_for_triqs ") + +# what to compile ? +SET( BUILD_BOOST_SERIALIZATION ON) +#SET( BUILD_BOOST_FILESYSTEM ON) +SET( BUILD_BOOST_SYSTEM ON) + +SET( BUILD_BOOST_FILESYSTEM OFF) +SET (BUILD_BOOST_THREAD ON) +SET (BUILD_BOOST_DATE_TIME OFF ) +SET (BUILD_BOOST_PROGRAM_OPTIONS OFF) +SET (BUILD_BOOST_REGEX OFF) + +set(ALPS_BOOST_LIBRARY_NAME "boost_for_triqs" ) +include (CompileBoost) + +include_directories(${BOOST_SOURCE_DIR}) # this one is for the compilation in this dir +if(TRIQS_BUILD_STATIC) + set(BOOST_LIBRARY boost_for_triqs mpi ${ALPS_EXTRA_LIBRARIES} PARENT_SCOPE ) +else(TRIQS_BUILD_STATIC) + set(BOOST_LIBRARY boost_for_triqs ${ALPS_EXTRA_LIBRARIES} PARENT_SCOPE ) +endif(TRIQS_BUILD_STATIC) +set(BOOST_INCLUDE_DIR ${BOOST_SOURCE_DIR} PARENT_SCOPE) # this is for later compilation in the project + +# install the python sources +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ) + +if(TRIQS_BUILD_STATIC) + + set_property(GLOBAL APPEND PROPERTY Modules_actually_compiled mpi) + +else(TRIQS_BUILD_STATIC) + + install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/boost) + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/mpi.so DESTINATION ${TRIQS_PYTHON_LIB_DEST}/boost) + + # for tests + FILE (COPY ${PYTHON_SOURCES} DESTINATION ${CMAKE_BINARY_DIR}/pytriqs/boost) + execute_process(COMMAND ln -fs ${CMAKE_CURRENT_BINARY_DIR}/mpi.so ${CMAKE_BINARY_DIR}/pytriqs/boost) + +endif(TRIQS_BUILD_STATIC) + +if(Install_dev) + install(DIRECTORY numeric DESTINATION include/boost) +endif(Install_dev) diff --git a/foreignlibs/boost/__init__.py b/foreignlibs/boost/__init__.py new file mode 100644 index 00000000..ffd3862e --- /dev/null +++ b/foreignlibs/boost/__init__.py @@ -0,0 +1,10 @@ +import sys +if sys.platform == 'linux2': + import DLFCN as dl + flags = sys.getdlopenflags() + sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL) + import mpi + sys.setdlopenflags(flags) +else: + import mpi + diff --git a/foreignlibs/breathe/LICENCE b/foreignlibs/breathe/LICENCE new file mode 100644 index 00000000..46a85058 --- /dev/null +++ b/foreignlibs/breathe/LICENCE @@ -0,0 +1,28 @@ +// BSD licence, modified to remove the organisation as there isn't one. + +Copyright (c) 2009, Michael Jones +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/foreignlibs/breathe/README.rst b/foreignlibs/breathe/README.rst new file mode 100644 index 00000000..1d6de527 --- /dev/null +++ b/foreignlibs/breathe/README.rst @@ -0,0 +1,70 @@ +Breathe +======= + +This is an extension to reStructuredText and Sphinx to be able to read and +render the Doxygen xml output. + +Download +-------- + +Breathe is available from github and `PyPI, the Python Package Index +`_ + +Documentation +------------- + +Documentation is available in the ``testsuite`` folder and up in full `here +`_. + +Running Testsuite +----------------- + +Run ``make`` in the root of the project. + +This will run doxygen over the example code and then run the Breathe +documentation/testsuite. View the results at:: + + testsuite/build/html/index.html + +Requirements +------------ + +Development is currently done with: + +- Python 2.7 +- Docutils 0.7 +- Sphinx 1.0.7 +- Doxygen 1.7.2 + +Doxygen 1.5.1 seems to produce xml with repeated sections which causes Breathe +some confusion. Not sure when this was resolved but it might be best to go for +the latest possible. + +Mailing List +------------ + +There is a mailing list available thanks to `LibreList `_:: + + breathe@librelist.com + +The archives are available `here `_. + +Credits +------- + +Thank you to: + +- `nijel `_ +- `sebastianschaetz `_ +- `mbolivar `_ +- `queezythegreat `_ +- `abingham `_ +- `davidm `_ +- `hobu `_ + +For their contributions; improving the code and the documentation. And thanks to: + +- Dimitri van Heesch for `Doxygen `_. +- Georg Brandl for `Sphinx `_. +- David Goodger for `Docutils `_ and reStructuredText. + diff --git a/foreignlibs/breathe/breathe/__init__.py b/foreignlibs/breathe/breathe/__init__.py new file mode 100644 index 00000000..11689a38 --- /dev/null +++ b/foreignlibs/breathe/breathe/__init__.py @@ -0,0 +1,841 @@ + +from docutils import nodes +from docutils.parsers.rst.directives import unchanged_required, unchanged, flag + +import os +import sys +import copy +import fnmatch +import re +import textwrap + +from docutils.parsers import rst +from docutils.statemachine import ViewList +from sphinx.domains.cpp import DefinitionParser + +from breathe.finder import FinderFactory, NoMatchesError, MultipleMatchesError +from breathe.parser import DoxygenParserFactory, CacheFactory, ParserError +from breathe.renderer.rst.doxygen import DoxygenToRstRendererFactoryCreatorConstructor, RstContentCreator +from breathe.renderer.rst.doxygen.domain import DomainHandlerFactoryCreator, NullDomainHandler +from breathe.renderer.rst.doxygen.domain import CppDomainHelper, CDomainHelper +from breathe.renderer.rst.doxygen.filter import FilterFactory, GlobFactory +from breathe.renderer.rst.doxygen.target import TargetHandlerFactory +from breathe.finder.doxygen import DoxygenItemFinderFactoryCreator, ItemMatcherFactory + +import docutils.nodes +import sphinx.addnodes + +# Somewhat outrageously, reach in and fix a Sphinx regex +import sphinx.domains.cpp +sphinx.domains.cpp._identifier_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*)\b') + +__version__ = '0.7.0' + +class BaseDirective(rst.Directive): + + def __init__( + self, + root_data_object, + renderer_factory_creator_constructor, + finder_factory, + matcher_factory, + project_info_factory, + filter_factory, + target_handler_factory, + *args + ): + rst.Directive.__init__(self, *args) + + self.root_data_object = root_data_object + self.renderer_factory_creator_constructor = renderer_factory_creator_constructor + self.finder_factory = finder_factory + self.matcher_factory = matcher_factory + self.project_info_factory = project_info_factory + self.filter_factory = filter_factory + self.target_handler_factory = target_handler_factory + + +# Directives +# ---------- + +class DoxygenIndexDirective(BaseDirective): + + required_arguments = 0 + optional_arguments = 2 + option_spec = { + "path": unchanged_required, + "project": unchanged_required, + "outline": flag, + "no-link": flag, + } + has_content = False + + def run(self): + + project_info = self.project_info_factory.create_project_info(self.options) + + try: + finder = self.finder_factory.create_finder(project_info) + except ParserError, e: + warning = 'doxygenindex: Unable to parse file "%s"' % e + return [docutils.nodes.warning("", docutils.nodes.paragraph("", "", docutils.nodes.Text(warning))), + self.state.document.reporter.warning(warning, line=self.lineno)] + + data_object = finder.root() + + target_handler = self.target_handler_factory.create(self.options, project_info, self.state.document) + filter_ = self.filter_factory.create_index_filter(self.options) + + renderer_factory_creator = self.renderer_factory_creator_constructor.create_factory_creator( + project_info, + self.state.document, + self.options, + ) + renderer_factory = renderer_factory_creator.create_factory( + data_object, + self.state, + self.state.document, + filter_, + target_handler, + ) + object_renderer = renderer_factory.create_renderer(self.root_data_object, data_object) + node_list = object_renderer.render() + + return node_list + + +class DoxygenFunctionDirective(BaseDirective): + + required_arguments = 1 + optional_arguments = 1 + option_spec = { + "path": unchanged_required, + "project": unchanged_required, + "outline": flag, + "no-link": flag, + } + has_content = False + + def run(self): + + try: + (namespace, function_name) = self.arguments[0].rsplit("::", 1) + except ValueError: + (namespace, function_name) = "", self.arguments[0] + + project_info = self.project_info_factory.create_project_info(self.options) + + finder = self.finder_factory.create_finder(project_info) + + matcher_stack = self.matcher_factory.create_matcher_stack( + { + "compound": self.matcher_factory.create_name_matcher(namespace), + "member": self.matcher_factory.create_name_type_matcher(function_name, "function") + }, + "member" + ) + + try: + data_object = finder.find_one(matcher_stack) + except NoMatchesError, e: + warning = ('doxygenfunction: Cannot find function "%s%s" in doxygen xml output ' + 'for project "%s" from directory: %s' + % (namespace, function_name, project_info.name(), project_info.path())) + return [docutils.nodes.warning("", docutils.nodes.paragraph("", "", docutils.nodes.Text(warning))), + self.state.document.reporter.warning(warning, line=self.lineno)] + + target_handler = self.target_handler_factory.create(self.options, project_info, self.state.document) + filter_ = self.filter_factory.create_outline_filter(self.options) + + renderer_factory_creator = self.renderer_factory_creator_constructor.create_factory_creator( + project_info, + self.state.document, + self.options, + ) + renderer_factory = renderer_factory_creator.create_factory( + data_object, + self.state, + self.state.document, + filter_, + target_handler, + ) + object_renderer = renderer_factory.create_renderer(self.root_data_object, data_object) + node_list = object_renderer.render() + + return node_list + + +class DoxygenClassDirective(BaseDirective): + + kind = "class" + + required_arguments = 1 + optional_arguments = 1 + option_spec = { + "path": unchanged_required, + "project": unchanged_required, + "members": unchanged, + "show": unchanged_required, + "outline": flag, + "no-link": flag, + } + has_content = False + + def run(self): + + name = self.arguments[0] + + project_info = self.project_info_factory.create_project_info(self.options) + + finder = self.finder_factory.create_finder(project_info) + + matcher_stack = self.matcher_factory.create_matcher_stack( + { + "compound": self.matcher_factory.create_name_type_matcher(name, self.kind) + }, + "compound" + ) + + try: + data_object = finder.find_one(matcher_stack) + except NoMatchesError, e: + warning = ('doxygen%s: Cannot find %s "%s" in doxygen xml output for project "%s" from directory: %s' + % (self.kind, self.kind, name, project_info.name(), project_info.path())) + return [docutils.nodes.warning("", docutils.nodes.paragraph("", "", docutils.nodes.Text(warning))), + self.state.document.reporter.warning(warning, line=self.lineno)] + + target_handler = self.target_handler_factory.create(self.options, project_info, self.state.document) + filter_ = self.filter_factory.create_class_filter(self.options) + + renderer_factory_creator = self.renderer_factory_creator_constructor.create_factory_creator( + project_info, + self.state.document, + self.options, + ) + renderer_factory = renderer_factory_creator.create_factory( + data_object, + self.state, + self.state.document, + filter_, + target_handler, + ) + object_renderer = renderer_factory.create_renderer(self.root_data_object, data_object) + + node_list = object_renderer.render() + + return node_list + + +class DoxygenFileDirective(BaseDirective): + + kind = "file" + + required_arguments = 1 + optional_arguments = 1 + option_spec = { + "path": unchanged_required, + "project": unchanged_required, + "no-link": flag, + } + has_content = False + + def run(self): + + name = self.arguments[0] + + project_info = self.project_info_factory.create_project_info(self.options) + + finder = self.finder_factory.create_finder(project_info) + + finder_filter = self.filter_factory.create_file_finder_filter(name) + + matches = [] + finder.filter_(finder_filter, matches) + + if len(matches) > 1: + warning = ('doxygenfile: Found multiple matches for file "%s" in doxygen xml output for project "%s" ' + 'from directory: %s' % (name, project_info.name(), project_info.path())) + return [docutils.nodes.warning("", docutils.nodes.paragraph("", "", docutils.nodes.Text(warning))), + self.state.document.reporter.warning(warning, line=self.lineno)] + + elif not matches: + warning = ('doxygenfile: Cannot find file "%s" in doxygen xml output for project "%s" from directory: %s' + % (name, project_info.name(), project_info.path())) + return [docutils.nodes.warning("", docutils.nodes.paragraph("", "", docutils.nodes.Text(warning))), + self.state.document.reporter.warning(warning, line=self.lineno)] + + target_handler = self.target_handler_factory.create(self.options, project_info, self.state.document) + filter_ = self.filter_factory.create_file_filter(name, self.options) + + renderer_factory_creator = self.renderer_factory_creator_constructor.create_factory_creator( + project_info, + self.state.document, + self.options, + ) + node_list = [] + for data_object in matches: + + renderer_factory = renderer_factory_creator.create_factory( + data_object, + self.state, + self.state.document, + filter_, + target_handler, + ) + + object_renderer = renderer_factory.create_renderer(self.root_data_object, data_object) + node_list.extend(object_renderer.render()) + + return node_list + + +class DoxygenBaseDirective(BaseDirective): + + required_arguments = 1 + optional_arguments = 1 + option_spec = { + "path": unchanged_required, + "project": unchanged_required, + "outline": flag, + "no-link": flag, + } + has_content = False + + def run(self): + + try: + namespace, name = self.arguments[0].rsplit("::", 1) + except ValueError: + namespace, name = "", self.arguments[0] + + project_info = self.project_info_factory.create_project_info(self.options) + + finder = self.finder_factory.create_finder(project_info) + + matcher_stack = self.create_matcher_stack(namespace, name) + + try: + data_object = finder.find_one(matcher_stack) + except NoMatchesError, e: + display_name = "%s::%s" % (namespace, name) if namespace else name + warning = ('doxygen%s: Cannot find %s "%s" in doxygen xml output for project "%s" from directory: %s' + % (self.kind, self.kind, display_name, project_info.name(), project_info.path())) + return [docutils.nodes.warning("", docutils.nodes.paragraph("", "", docutils.nodes.Text(warning))), + self.state.document.reporter.warning(warning, line=self.lineno)] + + target_handler = self.target_handler_factory.create(self.options, project_info, self.state.document) + filter_ = self.filter_factory.create_outline_filter(self.options) + renderer_factory_creator = self.renderer_factory_creator_constructor.create_factory_creator( + project_info, + self.state.document, + self.options, + ) + renderer_factory = renderer_factory_creator.create_factory( + data_object, + self.state, + self.state.document, + filter_, + target_handler, + ) + object_renderer = renderer_factory.create_renderer(self.root_data_object, data_object) + + node_list = object_renderer.render() + + return node_list + + +class DoxygenStructDirective(DoxygenBaseDirective): + + kind = "struct" + + def create_matcher_stack(self, namespace, name): + + # Structs are stored in the xml file with their fully namespaced name + # We're using C++ namespaces here, it might be best to make this file + # type dependent + # + xml_name = "%s::%s" % (namespace, name) if namespace else name + + return self.matcher_factory.create_matcher_stack( + { + "compound": self.matcher_factory.create_name_type_matcher(xml_name, self.kind) + }, + "compound" + ) + + +# This class was the same as the DoxygenBaseDirective above, except that it +# wraps the output in a definition_list before passing it back. This should be +# abstracted in a far nicely way to avoid repeating so much code +# +# Now we're removed the definition_list wrap so we really need to refactor this! +class DoxygenBaseItemDirective(BaseDirective): + + required_arguments = 1 + optional_arguments = 1 + option_spec = { + "path": unchanged_required, + "project": unchanged_required, + "outline": flag, + "no-link": flag, + } + has_content = False + + def run(self): + + try: + namespace, name = self.arguments[0].rsplit("::", 1) + except ValueError: + namespace, name = "", self.arguments[0] + + project_info = self.project_info_factory.create_project_info(self.options) + + finder = self.finder_factory.create_finder(project_info) + + matcher_stack = self.create_matcher_stack(namespace, name) + + try: + data_object = finder.find_one(matcher_stack) + except NoMatchesError, e: + display_name = "%s::%s" % (namespace, name) if namespace else name + warning = ('doxygen%s: Cannot find %s "%s" in doxygen xml output for project "%s" from directory: %s' + % (self.kind, self.kind, display_name, project_info.name(), project_info.path())) + return [docutils.nodes.warning("", docutils.nodes.paragraph("", "", docutils.nodes.Text(warning))), + self.state.document.reporter.warning(warning, line=self.lineno)] + + target_handler = self.target_handler_factory.create(self.options, project_info, self.state.document) + filter_ = self.filter_factory.create_outline_filter(self.options) + renderer_factory_creator = self.renderer_factory_creator_constructor.create_factory_creator( + project_info, + self.state.document, + self.options, + ) + renderer_factory = renderer_factory_creator.create_factory( + data_object, + self.state, + self.state.document, + filter_, + target_handler, + ) + object_renderer = renderer_factory.create_renderer(self.root_data_object, data_object) + + node_list = object_renderer.render() + + return node_list + + +class DoxygenVariableDirective(DoxygenBaseItemDirective): + + kind = "variable" + + def create_matcher_stack(self, namespace, name): + + return self.matcher_factory.create_matcher_stack( + { + "compound": self.matcher_factory.create_name_matcher(namespace), + "member": self.matcher_factory.create_name_type_matcher(name, self.kind) + }, + "member" + ) + +class DoxygenDefineDirective(DoxygenBaseItemDirective): + + kind = "define" + + def create_matcher_stack(self, namespace, name): + + return self.matcher_factory.create_matcher_stack( + { + "compound": self.matcher_factory.create_name_matcher(namespace), + "member": self.matcher_factory.create_name_type_matcher(name, self.kind) + }, + "member" + ) + +class DoxygenEnumDirective(DoxygenBaseItemDirective): + + kind = "enum" + + def create_matcher_stack(self, namespace, name): + + return self.matcher_factory.create_matcher_stack( + { + "compound": self.matcher_factory.create_name_matcher(namespace), + "member": self.matcher_factory.create_name_type_matcher(name, self.kind) + }, + "member" + ) + +class DoxygenTypedefDirective(DoxygenBaseItemDirective): + + kind = "typedef" + + def create_matcher_stack(self, namespace, name): + + return self.matcher_factory.create_matcher_stack( + { + "compound": self.matcher_factory.create_name_matcher(namespace), + "member": self.matcher_factory.create_name_type_matcher(name, self.kind) + }, + "member" + ) +# Setup Administration +# -------------------- + +class DirectiveContainer(object): + + def __init__( + self, + directive, + *args + ): + + self.directive = directive + self.args = args + + # Required for sphinx to inspect + self.required_arguments = directive.required_arguments + self.optional_arguments = directive.optional_arguments + self.option_spec = directive.option_spec + self.has_content = directive.has_content + + def __call__(self, *args): + + call_args = [] + call_args.extend(self.args) + call_args.extend(args) + + return self.directive(*call_args) + + +class ProjectInfo(object): + + def __init__(self, name, path, reference, domain_by_extension, domain_by_file_pattern, match): + + self._name = name + self._path = path + self._reference = reference + self._domain_by_extension = domain_by_extension + self._domain_by_file_pattern = domain_by_file_pattern + self._match = match + + def name(self): + return self._name + + def path(self): + return self._path + + def reference(self): + return self._reference + + def domain_for_file(self, file_): + + domain = "" + extension = file_.split(".")[-1] + + try: + domain = self._domain_by_extension[extension] + except KeyError: + pass + + for pattern, pattern_domain in self._domain_by_file_pattern.items(): + if self._match(file_, pattern): + domain = pattern_domain + + return domain + + +class ProjectInfoFactory(object): + + def __init__(self, match): + + self.match = match + + self.projects = {} + self.default_project = None + self.domain_by_extension = {} + self.domain_by_file_pattern = {} + + self.project_count = 0 + self.project_info_store = {} + + def update( + self, + projects, + default_project, + domain_by_extension, + domain_by_file_pattern, + ): + + self.projects = projects + self.default_project = default_project + self.domain_by_extension = domain_by_extension + self.domain_by_file_pattern = domain_by_file_pattern + + def default_path(self): + + return self.projects[self.default_project] + + def create_project_info(self, options): + + name = "" + path = self.default_path() + + if "project" in options: + try: + path = self.projects[options["project"]] + name = options["project"] + except KeyError, e: + sys.stderr.write( + "Unable to find project '%s' in breathe_projects dictionary" % options["project"] + ) + + if "path" in options: + path = options["path"] + + try: + return self.project_info_store[path] + except KeyError: + + reference = name + + if not name: + name = "project%s" % self.project_count + reference = path + self.project_count += 1 + + project_info = ProjectInfo( + name, + path, + reference, + self.domain_by_extension, + self.domain_by_file_pattern, + self.match + ) + + self.project_info_store[path] = project_info + + return project_info + + +class DoxygenDirectiveFactory(object): + + directives = { + "doxygenindex": DoxygenIndexDirective, + "doxygenfunction": DoxygenFunctionDirective, + "doxygenstruct": DoxygenStructDirective, + "doxygenclass": DoxygenClassDirective, + "doxygenvariable": DoxygenVariableDirective, + "doxygendefine": DoxygenDefineDirective, + "doxygenenum": DoxygenEnumDirective, + "doxygentypedef": DoxygenTypedefDirective, + "doxygenfile": DoxygenFileDirective, + } + + def __init__( + self, + root_data_object, + renderer_factory_creator_constructor, + finder_factory, + matcher_factory, + project_info_factory, + filter_factory, + target_handler_factory + ): + self.root_data_object = root_data_object + self.renderer_factory_creator_constructor = renderer_factory_creator_constructor + self.finder_factory = finder_factory + self.matcher_factory = matcher_factory + self.project_info_factory = project_info_factory + self.filter_factory = filter_factory + self.target_handler_factory = target_handler_factory + + def create_index_directive_container(self): + return self.create_directive_container("doxygenindex") + + def create_function_directive_container(self): + return self.create_directive_container("doxygenfunction") + + def create_struct_directive_container(self): + return self.create_directive_container("doxygenstruct") + + def create_enum_directive_container(self): + return self.create_directive_container("doxygenenum") + + def create_typedef_directive_container(self): + return self.create_directive_container("doxygentypedef") + + def create_class_directive_container(self): + return self.create_directive_container("doxygenclass") + + def create_file_directive_container(self): + return self.create_directive_container("doxygenfile") + + def create_variable_directive_container(self): + return self.create_directive_container("doxygenvariable") + + def create_define_directive_container(self): + return self.create_directive_container("doxygendefine") + + def create_directive_container(self, type_): + + return DirectiveContainer( + self.directives[type_], + self.root_data_object, + self.renderer_factory_creator_constructor, + self.finder_factory, + self.matcher_factory, + self.project_info_factory, + self.filter_factory, + self.target_handler_factory + ) + + def get_config_values(self, app): + + # All DirectiveContainers maintain references to this project info factory + # so we can update this to update them + self.project_info_factory.update( + app.config.breathe_projects, + app.config.breathe_default_project, + app.config.breathe_domain_by_extension, + app.config.breathe_domain_by_file_pattern, + ) + + +class NodeFactory(object): + + def __init__(self, *args): + + self.sources = args + + def __getattr__(self, node_name): + + for source in self.sources: + try: + return getattr(source, node_name) + except AttributeError: + pass + + raise NodeNotFoundError(node_name) + + +class RootDataObject(object): + + node_type = "root" + + +class PathHandler(object): + + def __init__(self, sep, basename, join): + + self.sep = sep + self.basename = basename + self.join = join + + def includes_directory(self, file_path): + + return bool( file_path.count( self.sep ) ) + + +# Setup +# ----- + +def setup(app): + + cache_factory = CacheFactory() + cache = cache_factory.create_cache() + path_handler = PathHandler(os.sep, os.path.basename, os.path.join) + parser_factory = DoxygenParserFactory(cache, path_handler) + matcher_factory = ItemMatcherFactory() + item_finder_factory_creator = DoxygenItemFinderFactoryCreator(parser_factory, matcher_factory) + index_parser = parser_factory.create_index_parser() + finder_factory = FinderFactory(index_parser, item_finder_factory_creator) + + node_factory = NodeFactory(docutils.nodes, sphinx.addnodes) + + cpp_domain_helper = CppDomainHelper(DefinitionParser, re.sub) + c_domain_helper = CDomainHelper() + domain_helpers = {"c": c_domain_helper, "cpp": cpp_domain_helper} + domain_handler_factory_creator = DomainHandlerFactoryCreator(node_factory, domain_helpers) + + rst_content_creator = RstContentCreator(ViewList, textwrap.dedent) + default_domain_handler = NullDomainHandler() + renderer_factory_creator_constructor = DoxygenToRstRendererFactoryCreatorConstructor( + node_factory, + parser_factory, + default_domain_handler, + domain_handler_factory_creator, + rst_content_creator + ) + + project_info_factory = ProjectInfoFactory(fnmatch.fnmatch) + glob_factory = GlobFactory(fnmatch.fnmatch) + filter_factory = FilterFactory(glob_factory, path_handler) + target_handler_factory = TargetHandlerFactory(node_factory) + + root_data_object = RootDataObject() + + directive_factory = DoxygenDirectiveFactory( + root_data_object, + renderer_factory_creator_constructor, + finder_factory, + matcher_factory, + project_info_factory, + filter_factory, + target_handler_factory + ) + + app.add_directive( + "doxygenindex", + directive_factory.create_index_directive_container(), + ) + + app.add_directive( + "doxygenfunction", + directive_factory.create_function_directive_container(), + ) + + app.add_directive( + "doxygenstruct", + directive_factory.create_struct_directive_container(), + ) + + app.add_directive( + "doxygenenum", + directive_factory.create_enum_directive_container(), + ) + + app.add_directive( + "doxygentypedef", + directive_factory.create_typedef_directive_container(), + ) + + app.add_directive( + "doxygenclass", + directive_factory.create_class_directive_container(), + ) + + app.add_directive( + "doxygenfile", + directive_factory.create_file_directive_container(), + ) + + app.add_directive( + "doxygenvariable", + directive_factory.create_variable_directive_container(), + ) + + app.add_directive( + "doxygendefine", + directive_factory.create_define_directive_container(), + ) + + app.add_config_value("breathe_projects", {}, True) + app.add_config_value("breathe_default_project", "", True) + app.add_config_value("breathe_domain_by_extension", {}, True) + app.add_config_value("breathe_domain_by_file_pattern", {}, True) + + app.add_stylesheet("breathe.css") + + app.connect("builder-inited", directive_factory.get_config_values) + diff --git a/foreignlibs/breathe/breathe/finder/__init__.py b/foreignlibs/breathe/breathe/finder/__init__.py new file mode 100644 index 00000000..1c97dfcf --- /dev/null +++ b/foreignlibs/breathe/breathe/finder/__init__.py @@ -0,0 +1,65 @@ + +class FinderError(Exception): + pass + +class MultipleMatchesError(FinderError): + pass + +class NoMatchesError(FinderError): + pass + +class Finder(object): + + def __init__(self, root, item_finder_factory): + + self._root = root + self.item_finder_factory = item_finder_factory + + def find(self, matcher_stack): + + item_finder = self.item_finder_factory.create_finder(self._root) + + return item_finder.find(matcher_stack) + + def filter_(self, filter_, matches): + + item_finder = self.item_finder_factory.create_finder(self._root) + item_finder.filter_(filter_, matches) + + def find_one(self, matcher_stack): + + results = self.find(matcher_stack) + + count = len(results) + if count == 1: + return results[0] + elif count > 1: + # Multiple matches can easily happen as same thing + # can be present in both file and group sections + return results[0] + elif count < 1: + raise NoMatchesError(matcher_stack) + + + def root(self): + + return self._root + + +class FinderFactory(object): + + def __init__(self, parser, item_finder_factory_creator): + + self.parser = parser + self.item_finder_factory_creator = item_finder_factory_creator + + + def create_finder(self, project_info): + + root = self.parser.parse(project_info) + item_finder_factory = self.item_finder_factory_creator.create_factory(project_info) + + return Finder(root, item_finder_factory) + + + diff --git a/foreignlibs/breathe/breathe/finder/doxygen/__init__.py b/foreignlibs/breathe/breathe/finder/doxygen/__init__.py new file mode 100644 index 00000000..281dd2a7 --- /dev/null +++ b/foreignlibs/breathe/breathe/finder/doxygen/__init__.py @@ -0,0 +1,147 @@ + +from breathe.finder.doxygen import index as indexfinder +from breathe.finder.doxygen import compound as compoundfinder + +from breathe.parser.doxygen import index, compound + +class MissingLevelError(Exception): + pass + +class Matcher(object): + pass + +class ItemMatcher(Matcher): + + def __init__(self, name, type_): + self.name = name + self.type_ = type_ + + def match(self, data_object): + return self.name == data_object.name and self.type_ == data_object.kind + + def __repr__(self): + return "" % (self.name, self.type_) + +class NameMatcher(Matcher): + + def __init__(self, name): + self.name = name + + def match(self, data_object): + return self.name == data_object.name + + +class RefMatcher(Matcher): + + def __init__(self, refid): + + self.refid = refid + + def match(self, data_object): + return self.refid == data_object.refid + +class AnyMatcher(Matcher): + + def match(self, data_object): + return True + + +class MatcherStack(object): + + def __init__(self, matchers, lowest_level): + + self.matchers = matchers + self.lowest_level = lowest_level + + def match(self, level, data_object): + + try: + return self.matchers[level].match(data_object) + except KeyError: + return False + + def full_match(self, level, data_object): + + try: + return self.matchers[level].match(data_object) and level == self.lowest_level + except KeyError: + raise MissingLevelError(level) + + +class ItemMatcherFactory(Matcher): + + def create_name_type_matcher(self, name, type_): + + return ItemMatcher(name, type_) + + def create_name_matcher(self, name): + + return NameMatcher(name) if name else AnyMatcher() + + def create_ref_matcher(self, ref): + + return RefMatcher(ref) + + def create_matcher_stack(self, matchers, lowest_level): + + return MatcherStack(matchers, lowest_level) + + def create_ref_matcher_stack(self, class_, ref): + + matchers = { + "compound" : ItemMatcher(class_, "class") if class_ else AnyMatcher(), + "member" : RefMatcher(ref), + } + + return MatcherStack(matchers, "member") + + +class CreateCompoundTypeSubFinder(object): + + def __init__(self, parser_factory, matcher_factory): + + self.parser_factory = parser_factory + self.matcher_factory = matcher_factory + + def __call__(self, project_info, *args): + + compound_parser = self.parser_factory.create_compound_parser(project_info) + return indexfinder.CompoundTypeSubItemFinder(self.matcher_factory, compound_parser, project_info, *args) + + + +class DoxygenItemFinderFactory(object): + + def __init__(self, finders, project_info): + + self.finders = finders + self.project_info = project_info + + def create_finder(self, data_object): + + return self.finders[data_object.node_type](self.project_info, data_object, self) + + +class DoxygenItemFinderFactoryCreator(object): + + def __init__(self, parser_factory, matcher_factory): + + self.parser_factory = parser_factory + self.matcher_factory = matcher_factory + + def create_factory(self, project_info): + + finders = { + "doxygen" : indexfinder.DoxygenTypeSubItemFinder, + "compound" : CreateCompoundTypeSubFinder(self.parser_factory, self.matcher_factory), + "member" : indexfinder.MemberTypeSubItemFinder, + "doxygendef" : compoundfinder.DoxygenTypeSubItemFinder, + "compounddef" : compoundfinder.CompoundDefTypeSubItemFinder, + "sectiondef" : compoundfinder.SectionDefTypeSubItemFinder, + "memberdef" : compoundfinder.MemberDefTypeSubItemFinder, + } + + return DoxygenItemFinderFactory(finders, project_info) + + + diff --git a/foreignlibs/breathe/breathe/finder/doxygen/base.py b/foreignlibs/breathe/breathe/finder/doxygen/base.py new file mode 100644 index 00000000..7678f789 --- /dev/null +++ b/foreignlibs/breathe/breathe/finder/doxygen/base.py @@ -0,0 +1,10 @@ + +class ItemFinder(object): + + def __init__(self, project_info, data_object, item_finder_factory): + + self.data_object = data_object + self.item_finder_factory = item_finder_factory + self.project_info = project_info + + diff --git a/foreignlibs/breathe/breathe/finder/doxygen/compound.py b/foreignlibs/breathe/breathe/finder/doxygen/compound.py new file mode 100644 index 00000000..2cb861b2 --- /dev/null +++ b/foreignlibs/breathe/breathe/finder/doxygen/compound.py @@ -0,0 +1,65 @@ + +from breathe.finder.doxygen.base import ItemFinder + +class DoxygenTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + compound_finder = self.item_finder_factory.create_finder(self.data_object.compounddef) + return compound_finder.find(matcher_stack) + + def filter_(self, parent, filter_, matches): + + compound_finder = self.item_finder_factory.create_finder(self.data_object.compounddef) + compound_finder.filter_(self.data_object, filter_, matches) + + +class CompoundDefTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + results = [] + for sectiondef in self.data_object.sectiondef: + finder = self.item_finder_factory.create_finder(sectiondef) + results.extend(finder.find(matcher_stack)) + + return results + + def filter_(self, parent, filter_, matches): + + if filter_.allow(parent, self.data_object): + matches.append(self.data_object) + + for sectiondef in self.data_object.sectiondef: + finder = self.item_finder_factory.create_finder(sectiondef) + finder.filter_(self.data_object, filter_, matches) + +class SectionDefTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + results = [] + for memberdef in self.data_object.memberdef: + finder = self.item_finder_factory.create_finder(memberdef) + results.extend(finder.find(matcher_stack)) + + return results + + def filter_(self, parent, filter_, matches): + + for memberdef in self.data_object.memberdef: + finder = self.item_finder_factory.create_finder(memberdef) + finder.filter_(self.data_object, filter_, matches) + +class MemberDefTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + if matcher_stack.match("member", self.data_object): + return [self.data_object] + else: + return [] + + def filter_(self, parent, filter_, matches): + + pass diff --git a/foreignlibs/breathe/breathe/finder/doxygen/index.py b/foreignlibs/breathe/breathe/finder/doxygen/index.py new file mode 100644 index 00000000..9d23ccd6 --- /dev/null +++ b/foreignlibs/breathe/breathe/finder/doxygen/index.py @@ -0,0 +1,84 @@ + +from breathe.finder.doxygen.base import ItemFinder + +class DoxygenTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + compounds = self.data_object.get_compound() + + results = [] + + for compound in compounds: + + if matcher_stack.match("compound", compound): + compound_finder = self.item_finder_factory.create_finder(compound) + results.extend(compound_finder.find(matcher_stack)) + + return results + + + def filter_(self, filter_, matches): + + compounds = self.data_object.get_compound() + + for compound in compounds: + compound_finder = self.item_finder_factory.create_finder(compound) + compound_finder.filter_(self.data_object, filter_, matches) + +class CompoundTypeSubItemFinder(ItemFinder): + + def __init__(self, matcher_factory, compound_parser, *args): + ItemFinder.__init__(self, *args) + + self.matcher_factory = matcher_factory + self.compound_parser = compound_parser + + def find(self, matcher_stack): + + members = self.data_object.get_member() + + member_results = [] + + for member in members: + if matcher_stack.match("member", member): + member_finder = self.item_finder_factory.create_finder(member) + member_results.extend(member_finder.find(matcher_stack)) + + results = [] + + # If there are members in this compound that match the criteria + # then load up the file for this compound and get the member data objects + if member_results: + + file_data = self.compound_parser.parse(self.data_object.refid) + finder = self.item_finder_factory.create_finder(file_data) + + for member_data in member_results: + ref_matcher_stack = self.matcher_factory.create_ref_matcher_stack("", member_data.refid) + # TODO: Fix this! Should be ref_matcher_stack! + results.extend(finder.find(matcher_stack)) + + elif matcher_stack.full_match("compound", self.data_object): + results.append(self.data_object) + + return results + + + def filter_(self, parent, filter_, matches): + + file_data = self.compound_parser.parse(self.data_object.refid) + finder = self.item_finder_factory.create_finder(file_data) + + finder.filter_(self.data_object, filter_, matches) + +class MemberTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + if matcher_stack.full_match("member", self.data_object): + return [self.data_object] + else: + return [] + + diff --git a/foreignlibs/breathe/breathe/parser/__init__.py b/foreignlibs/breathe/breathe/parser/__init__.py new file mode 100644 index 00000000..3ff89710 --- /dev/null +++ b/foreignlibs/breathe/breathe/parser/__init__.py @@ -0,0 +1,83 @@ + +import breathe.parser.doxygen.index +import breathe.parser.doxygen.compound +import os + +class ParserError(Exception): + pass + +class Parser(object): + + def __init__(self, cache, path_handler): + + self.cache = cache + self.path_handler = path_handler + + +class DoxygenIndexParser(Parser): + + def parse(self, project_info): + + filename = self.path_handler.join(project_info.path(), "index.xml") + + try: + # Try to get from our cache + return self.cache[filename] + except KeyError: + + # If that fails, parse it afresh + try: + result = breathe.parser.doxygen.index.parse(filename) + self.cache[filename] = result + return result + except breathe.parser.doxygen.index.ParseError: + raise ParserError(filename) + +class DoxygenCompoundParser(Parser): + + def __init__(self, cache, path_handler, project_info): + Parser.__init__(self, cache, path_handler) + + self.project_info = project_info + + def parse(self, refid): + + filename = self.path_handler.join(self.project_info.path(), "%s.xml" % refid) + + try: + # Try to get from our cache + return self.cache[filename] + except KeyError: + + # If that fails, parse it afresh + try: + result = breathe.parser.doxygen.compound.parse(filename) + self.cache[filename] = result + return result + except breathe.parser.doxygen.compound.ParseError: + raise ParserError(filename) + +class CacheFactory(object): + + def create_cache(self): + + # Return basic dictionary as cache + return {} + +class DoxygenParserFactory(object): + + def __init__(self, cache, path_handler): + + self.cache = cache + self.path_handler = path_handler + + def create_index_parser(self): + + return DoxygenIndexParser(self.cache, self.path_handler) + + def create_compound_parser(self, project_info): + + return DoxygenCompoundParser(self.cache, self.path_handler, project_info) + + + diff --git a/foreignlibs/breathe/breathe/parser/doxygen/__init__.py b/foreignlibs/breathe/breathe/parser/doxygen/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/foreignlibs/breathe/breathe/parser/doxygen/compound.py b/foreignlibs/breathe/breathe/parser/doxygen/compound.py new file mode 100644 index 00000000..b27f08da --- /dev/null +++ b/foreignlibs/breathe/breathe/parser/doxygen/compound.py @@ -0,0 +1,867 @@ +#!/usr/bin/env python + +""" +Generated Mon Feb 9 19:08:05 2009 by generateDS.py. +""" + +from string import lower as str_lower +from xml.dom import minidom +from xml.dom import Node +from docutils import nodes + + +import sys + +import compoundsuper as supermod +from compoundsuper import MixedContainer + + +class DoxygenTypeSub(supermod.DoxygenType): + + node_type = "doxygendef" + + def __init__(self, version=None, compounddef=None): + supermod.DoxygenType.__init__(self, version, compounddef) +supermod.DoxygenType.subclass = DoxygenTypeSub +# end class DoxygenTypeSub + + +class compounddefTypeSub(supermod.compounddefType): + + node_type = "compounddef" + + def __init__(self, kind=None, prot=None, id=None, compoundname='', title='', basecompoundref=None, derivedcompoundref=None, includes=None, includedby=None, incdepgraph=None, invincdepgraph=None, innerdir=None, innerfile=None, innerclass=None, innernamespace=None, innerpage=None, innergroup=None, templateparamlist=None, sectiondef=None, briefdescription=None, detaileddescription=None, inheritancegraph=None, collaborationgraph=None, programlisting=None, location=None, listofallmembers=None): + supermod.compounddefType.__init__(self, kind, prot, id, compoundname, title, basecompoundref, derivedcompoundref, includes, includedby, incdepgraph, invincdepgraph, innerdir, innerfile, innerclass, innernamespace, innerpage, innergroup, templateparamlist, sectiondef, briefdescription, detaileddescription, inheritancegraph, collaborationgraph, programlisting, location, listofallmembers) +supermod.compounddefType.subclass = compounddefTypeSub +# end class compounddefTypeSub + + +class listofallmembersTypeSub(supermod.listofallmembersType): + + node_type = "listofallmembers" + + + def __init__(self, member=None): + supermod.listofallmembersType.__init__(self, member) +supermod.listofallmembersType.subclass = listofallmembersTypeSub +# end class listofallmembersTypeSub + + +class memberRefTypeSub(supermod.memberRefType): + + node_type = "memberref" + + def __init__(self, virt=None, prot=None, refid=None, ambiguityscope=None, scope='', name=''): + supermod.memberRefType.__init__(self, virt, prot, refid, ambiguityscope, scope, name) +supermod.memberRefType.subclass = memberRefTypeSub +# end class memberRefTypeSub + + +class compoundRefTypeSub(supermod.compoundRefType): + + node_type = "compoundref" + + def __init__(self, virt=None, prot=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + supermod.compoundRefType.__init__(self, mixedclass_, content_) +supermod.compoundRefType.subclass = compoundRefTypeSub +# end class compoundRefTypeSub + + +class reimplementTypeSub(supermod.reimplementType): + + node_type = "reimplement" + + def __init__(self, refid=None, valueOf_='', mixedclass_=None, content_=None): + supermod.reimplementType.__init__(self, mixedclass_, content_) +supermod.reimplementType.subclass = reimplementTypeSub +# end class reimplementTypeSub + + +class incTypeSub(supermod.incType): + + node_type = "inc" + + def __init__(self, local=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + supermod.incType.__init__(self, mixedclass_, content_) +supermod.incType.subclass = incTypeSub +# end class incTypeSub + + +class refTypeSub(supermod.refType): + + node_type = "ref" + + def __init__(self, node_name, prot=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + supermod.refType.__init__(self, mixedclass_, content_) + + self.node_name = node_name + +supermod.refType.subclass = refTypeSub + + +class refTextTypeSub(supermod.refTextType): + + node_type = "reftex" + + def __init__(self, refid=None, kindref=None, external=None, valueOf_='', mixedclass_=None, content_=None): + supermod.refTextType.__init__(self, mixedclass_, content_) + +supermod.refTextType.subclass = refTextTypeSub +# end class refTextTypeSub + +class sectiondefTypeSub(supermod.sectiondefType): + + node_type = "sectiondef" + + def __init__(self, kind=None, header='', description=None, memberdef=None): + supermod.sectiondefType.__init__(self, kind, header, description, memberdef) +supermod.sectiondefType.subclass = sectiondefTypeSub +# end class sectiondefTypeSub + + +class memberdefTypeSub(supermod.memberdefType): + + node_type = "memberdef" + + def __init__(self, initonly=None, kind=None, volatile=None, const=None, raise_=None, virt=None, readable=None, prot=None, explicit=None, new=None, final=None, writable=None, add=None, static=None, remove=None, sealed=None, mutable=None, gettable=None, inline=None, settable=None, id=None, templateparamlist=None, type_=None, definition='', argsstring='', name='', read='', write='', bitfield='', reimplements=None, reimplementedby=None, param=None, enumvalue=None, initializer=None, exceptions=None, briefdescription=None, detaileddescription=None, inbodydescription=None, location=None, references=None, referencedby=None): + supermod.memberdefType.__init__(self, initonly, kind, volatile, const, raise_, virt, readable, prot, explicit, new, final, writable, add, static, remove, sealed, mutable, gettable, inline, settable, id, templateparamlist, type_, definition, argsstring, name, read, write, bitfield, reimplements, reimplementedby, param, enumvalue, initializer, exceptions, briefdescription, detaileddescription, inbodydescription, location, references, referencedby) + + self.parameterlist = supermod.docParamListType.factory() + self.parameterlist.kind = "param" + + + def buildChildren(self, child_, nodeName_): + supermod.memberdefType.buildChildren(self, child_, nodeName_) + + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'param': + + # Get latest param + param = self.param[-1] + + # If it doesn't have a description we're done + if not param.briefdescription: + return + + # Construct our own param list from the descriptions stored inline + # with the parameters + paramdescription = param.briefdescription + paramname = supermod.docParamName.factory() + + # Add parameter name + obj_ = paramname.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', param.declname) + paramname.content_.append(obj_) + + paramnamelist = supermod.docParamNameList.factory() + paramnamelist.parametername.append(paramname) + + paramlistitem = supermod.docParamListItem.factory() + paramlistitem.parameternamelist.append(paramnamelist) + + # Add parameter description + paramlistitem.parameterdescription = paramdescription + + self.parameterlist.parameteritem.append(paramlistitem) + + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'detaileddescription': + + if not self.parameterlist.parameteritem: + # No items in our list + return + + + # Assume supermod.memberdefType.buildChildren has already built the + # description object, we just want to slot our parameterlist in at + # a reasonable point + + if not self.detaileddescription: + # Create one if it doesn't exist + self.detaileddescription = supermod.descriptionType.factory() + + detaileddescription = self.detaileddescription + + para = supermod.docParaType.factory() + para.parameterlist.append(self.parameterlist) + + obj_ = detaileddescription.mixedclass_(MixedContainer.CategoryComplex, MixedContainer.TypeNone, 'para', para) + + index = 0 + detaileddescription.content_.insert( index, obj_ ) + + + +supermod.memberdefType.subclass = memberdefTypeSub +# end class memberdefTypeSub + +class descriptionTypeSub(supermod.descriptionType): + + node_type = "description" + + def __init__(self, title='', para=None, sect1=None, internal=None, mixedclass_=None, content_=None): + supermod.descriptionType.__init__(self, mixedclass_, content_) +supermod.descriptionType.subclass = descriptionTypeSub +# end class descriptionTypeSub + + +class enumvalueTypeSub(supermod.enumvalueType): + + node_type = "enumvalue" + + def __init__(self, prot=None, id=None, name='', initializer=None, briefdescription=None, detaileddescription=None, mixedclass_=None, content_=None): + supermod.enumvalueType.__init__(self, mixedclass_, content_) + + self.initializer = None + + def buildChildren(self, child_, nodeName_): + # Get text from child and put it in self.name + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + value_ = [] + for text_ in child_.childNodes: + value_.append(text_.nodeValue) + valuestr_ = ''.join(value_) + self.name = valuestr_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'briefdescription': + obj_ = supermod.descriptionType.factory() + obj_.build(child_) + self.set_briefdescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'detaileddescription': + obj_ = supermod.descriptionType.factory() + obj_.build(child_) + self.set_detaileddescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'initializer': + childobj_ = supermod.linkedTextType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'initializer', childobj_) + self.set_initializer(obj_) + self.content_.append(obj_) + +supermod.enumvalueType.subclass = enumvalueTypeSub +# end class enumvalueTypeSub + + +class templateparamlistTypeSub(supermod.templateparamlistType): + + node_type = "templateparamlist" + + def __init__(self, param=None): + supermod.templateparamlistType.__init__(self, param) +supermod.templateparamlistType.subclass = templateparamlistTypeSub +# end class templateparamlistTypeSub + + +class paramTypeSub(supermod.paramType): + + node_type = "param" + + def __init__(self, type_=None, declname='', defname='', array='', defval=None, briefdescription=None): + supermod.paramType.__init__(self, type_, declname, defname, array, defval, briefdescription) +supermod.paramType.subclass = paramTypeSub +# end class paramTypeSub + + +class linkedTextTypeSub(supermod.linkedTextType): + + node_type = "linkedtext" + + def __init__(self, ref=None, mixedclass_=None, content_=None): + supermod.linkedTextType.__init__(self, mixedclass_, content_) +supermod.linkedTextType.subclass = linkedTextTypeSub +# end class linkedTextTypeSub + + +class graphTypeSub(supermod.graphType): + + node_type = "graph" + + def __init__(self, node=None): + supermod.graphType.__init__(self, node) +supermod.graphType.subclass = graphTypeSub +# end class graphTypeSub + + +class nodeTypeSub(supermod.nodeType): + + node_type = "node" + + def __init__(self, id=None, label='', link=None, childnode=None): + supermod.nodeType.__init__(self, id, label, link, childnode) +supermod.nodeType.subclass = nodeTypeSub +# end class nodeTypeSub + + +class childnodeTypeSub(supermod.childnodeType): + + node_type = "childnode" + + def __init__(self, relation=None, refid=None, edgelabel=None): + supermod.childnodeType.__init__(self, relation, refid, edgelabel) +supermod.childnodeType.subclass = childnodeTypeSub +# end class childnodeTypeSub + + +class linkTypeSub(supermod.linkType): + + node_type = "link" + + def __init__(self, refid=None, external=None, valueOf_=''): + supermod.linkType.__init__(self, refid, external) +supermod.linkType.subclass = linkTypeSub +# end class linkTypeSub + + +class listingTypeSub(supermod.listingType): + + node_type = "listing" + + def __init__(self, codeline=None): + supermod.listingType.__init__(self, codeline) +supermod.listingType.subclass = listingTypeSub +# end class listingTypeSub + + +class codelineTypeSub(supermod.codelineType): + + node_type = "codeline" + + def __init__(self, external=None, lineno=None, refkind=None, refid=None, highlight=None): + supermod.codelineType.__init__(self, external, lineno, refkind, refid, highlight) +supermod.codelineType.subclass = codelineTypeSub +# end class codelineTypeSub + + +class highlightTypeSub(supermod.highlightType): + + node_type = "highlight" + + def __init__(self, class_=None, sp=None, ref=None, mixedclass_=None, content_=None): + supermod.highlightType.__init__(self, mixedclass_, content_) +supermod.highlightType.subclass = highlightTypeSub +# end class highlightTypeSub + + +class referenceTypeSub(supermod.referenceType): + + node_type = "reference" + + def __init__(self, endline=None, startline=None, refid=None, compoundref=None, valueOf_='', mixedclass_=None, content_=None): + supermod.referenceType.__init__(self, mixedclass_, content_) +supermod.referenceType.subclass = referenceTypeSub +# end class referenceTypeSub + + +class locationTypeSub(supermod.locationType): + + node_type = "location" + + def __init__(self, bodystart=None, line=None, bodyend=None, bodyfile=None, file=None, valueOf_=''): + supermod.locationType.__init__(self, bodystart, line, bodyend, bodyfile, file) +supermod.locationType.subclass = locationTypeSub +# end class locationTypeSub + + +class docSect1TypeSub(supermod.docSect1Type): + + node_type = "docsect1" + + def __init__(self, id=None, title='', para=None, sect2=None, internal=None, mixedclass_=None, content_=None): + supermod.docSect1Type.__init__(self, mixedclass_, content_) +supermod.docSect1Type.subclass = docSect1TypeSub +# end class docSect1TypeSub + + +class docSect2TypeSub(supermod.docSect2Type): + + node_type = "docsect2" + + def __init__(self, id=None, title='', para=None, sect3=None, internal=None, mixedclass_=None, content_=None): + supermod.docSect2Type.__init__(self, mixedclass_, content_) +supermod.docSect2Type.subclass = docSect2TypeSub +# end class docSect2TypeSub + + +class docSect3TypeSub(supermod.docSect3Type): + + node_type = "docsect3" + + def __init__(self, id=None, title='', para=None, sect4=None, internal=None, mixedclass_=None, content_=None): + supermod.docSect3Type.__init__(self, mixedclass_, content_) +supermod.docSect3Type.subclass = docSect3TypeSub +# end class docSect3TypeSub + + +class docSect4TypeSub(supermod.docSect4Type): + + node_type = "docsect4" + + def __init__(self, id=None, title='', para=None, internal=None, mixedclass_=None, content_=None): + supermod.docSect4Type.__init__(self, mixedclass_, content_) +supermod.docSect4Type.subclass = docSect4TypeSub +# end class docSect4TypeSub + + +class docInternalTypeSub(supermod.docInternalType): + + node_type = "docinternal" + + def __init__(self, para=None, sect1=None, mixedclass_=None, content_=None): + supermod.docInternalType.__init__(self, mixedclass_, content_) +supermod.docInternalType.subclass = docInternalTypeSub +# end class docInternalTypeSub + + +class docInternalS1TypeSub(supermod.docInternalS1Type): + + node_type = "docinternals1" + + def __init__(self, para=None, sect2=None, mixedclass_=None, content_=None): + supermod.docInternalS1Type.__init__(self, mixedclass_, content_) +supermod.docInternalS1Type.subclass = docInternalS1TypeSub +# end class docInternalS1TypeSub + + +class docInternalS2TypeSub(supermod.docInternalS2Type): + + node_type = "docinternals2" + + def __init__(self, para=None, sect3=None, mixedclass_=None, content_=None): + supermod.docInternalS2Type.__init__(self, mixedclass_, content_) +supermod.docInternalS2Type.subclass = docInternalS2TypeSub +# end class docInternalS2TypeSub + + +class docInternalS3TypeSub(supermod.docInternalS3Type): + + node_type = "docinternals3" + + def __init__(self, para=None, sect3=None, mixedclass_=None, content_=None): + supermod.docInternalS3Type.__init__(self, mixedclass_, content_) +supermod.docInternalS3Type.subclass = docInternalS3TypeSub +# end class docInternalS3TypeSub + + +class docInternalS4TypeSub(supermod.docInternalS4Type): + + node_type = "docinternals4" + + def __init__(self, para=None, mixedclass_=None, content_=None): + supermod.docInternalS4Type.__init__(self, mixedclass_, content_) +supermod.docInternalS4Type.subclass = docInternalS4TypeSub +# end class docInternalS4TypeSub + + +class docURLLinkSub(supermod.docURLLink): + + node_type = "docurllink" + + def __init__(self, url=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docURLLink.__init__(self, mixedclass_, content_) +supermod.docURLLink.subclass = docURLLinkSub +# end class docURLLinkSub + + +class docAnchorTypeSub(supermod.docAnchorType): + + node_type = "docanchor" + + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docAnchorType.__init__(self, mixedclass_, content_) +supermod.docAnchorType.subclass = docAnchorTypeSub +# end class docAnchorTypeSub + + +class docFormulaTypeSub(supermod.docFormulaType): + + node_type = "docformula" + + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docFormulaType.__init__(self, mixedclass_, content_) +supermod.docFormulaType.subclass = docFormulaTypeSub +# end class docFormulaTypeSub + + +class docIndexEntryTypeSub(supermod.docIndexEntryType): + + node_type = "docindexentry" + + def __init__(self, primaryie='', secondaryie=''): + supermod.docIndexEntryType.__init__(self, primaryie, secondaryie) +supermod.docIndexEntryType.subclass = docIndexEntryTypeSub +# end class docIndexEntryTypeSub + + +class docListTypeSub(supermod.docListType): + + node_type = "doclist" + + def __init__(self, listitem=None): + supermod.docListType.__init__(self, listitem) +supermod.docListType.subclass = docListTypeSub +# end class docListTypeSub + + +class docListItemTypeSub(supermod.docListItemType): + + node_type = "doclistitem" + + def __init__(self, para=None): + supermod.docListItemType.__init__(self, para) +supermod.docListItemType.subclass = docListItemTypeSub +# end class docListItemTypeSub + + +class docSimpleSectTypeSub(supermod.docSimpleSectType): + + node_type = "docsimplesect" + + def __init__(self, kind=None, title=None, para=None): + supermod.docSimpleSectType.__init__(self, kind, title, para) +supermod.docSimpleSectType.subclass = docSimpleSectTypeSub +# end class docSimpleSectTypeSub + + +class docVarListEntryTypeSub(supermod.docVarListEntryType): + + node_type = "docvarlistentry" + + def __init__(self, term=None): + supermod.docVarListEntryType.__init__(self, term) +supermod.docVarListEntryType.subclass = docVarListEntryTypeSub +# end class docVarListEntryTypeSub + + +class docRefTextTypeSub(supermod.docRefTextType): + + node_type = "docreftext" + + def __init__(self, refid=None, kindref=None, external=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docRefTextType.__init__(self, mixedclass_, content_) + + self.para = [] + + def buildChildren(self, child_, nodeName_): + supermod.docRefTextType.buildChildren(self, child_, nodeName_) + + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = supermod.docParaType.factory() + obj_.build(child_) + self.para.append(obj_) + +supermod.docRefTextType.subclass = docRefTextTypeSub +# end class docRefTextTypeSub + + +class docTableTypeSub(supermod.docTableType): + + node_type = "doctable" + + def __init__(self, rows=None, cols=None, row=None, caption=None): + supermod.docTableType.__init__(self, rows, cols, row, caption) +supermod.docTableType.subclass = docTableTypeSub +# end class docTableTypeSub + + +class docRowTypeSub(supermod.docRowType): + + node_type = "docrow" + + def __init__(self, entry=None): + supermod.docRowType.__init__(self, entry) +supermod.docRowType.subclass = docRowTypeSub +# end class docRowTypeSub + + +class docEntryTypeSub(supermod.docEntryType): + + node_type = "docentry" + + def __init__(self, thead=None, para=None): + supermod.docEntryType.__init__(self, thead, para) +supermod.docEntryType.subclass = docEntryTypeSub +# end class docEntryTypeSub + + +class docHeadingTypeSub(supermod.docHeadingType): + + node_type = "docheading" + + def __init__(self, level=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docHeadingType.__init__(self, mixedclass_, content_) +supermod.docHeadingType.subclass = docHeadingTypeSub +# end class docHeadingTypeSub + + +class docImageTypeSub(supermod.docImageType): + + node_type = "docimage" + + def __init__(self, width=None, type_=None, name=None, height=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docImageType.__init__(self, mixedclass_, content_) +supermod.docImageType.subclass = docImageTypeSub +# end class docImageTypeSub + + +class docDotFileTypeSub(supermod.docDotFileType): + + node_type = "docdocfile" + + def __init__(self, name=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docDotFileType.__init__(self, mixedclass_, content_) +supermod.docDotFileType.subclass = docDotFileTypeSub +# end class docDotFileTypeSub + + +class docTocItemTypeSub(supermod.docTocItemType): + + node_type = "doctocitem" + + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docTocItemType.__init__(self, mixedclass_, content_) +supermod.docTocItemType.subclass = docTocItemTypeSub +# end class docTocItemTypeSub + + +class docTocListTypeSub(supermod.docTocListType): + + node_type = "doctoclist" + + def __init__(self, tocitem=None): + supermod.docTocListType.__init__(self, tocitem) +supermod.docTocListType.subclass = docTocListTypeSub +# end class docTocListTypeSub + + +class docLanguageTypeSub(supermod.docLanguageType): + + node_type = "doclanguage" + + def __init__(self, langid=None, para=None): + supermod.docLanguageType.__init__(self, langid, para) +supermod.docLanguageType.subclass = docLanguageTypeSub +# end class docLanguageTypeSub + + +class docParamListTypeSub(supermod.docParamListType): + + node_type = "docparamlist" + + def __init__(self, kind=None, parameteritem=None): + supermod.docParamListType.__init__(self, kind, parameteritem) +supermod.docParamListType.subclass = docParamListTypeSub +# end class docParamListTypeSub + + +class docParamListItemSub(supermod.docParamListItem): + + node_type = "docparamlistitem" + + def __init__(self, parameternamelist=None, parameterdescription=None): + supermod.docParamListItem.__init__(self, parameternamelist, parameterdescription) +supermod.docParamListItem.subclass = docParamListItemSub +# end class docParamListItemSub + + +class docParamNameListSub(supermod.docParamNameList): + + node_type = "docparamnamelist" + + def __init__(self, parametername=None): + supermod.docParamNameList.__init__(self, parametername) +supermod.docParamNameList.subclass = docParamNameListSub +# end class docParamNameListSub + + +class docParamNameSub(supermod.docParamName): + + node_type = "docparamname" + + def __init__(self, direction=None, ref=None, mixedclass_=None, content_=None): + supermod.docParamName.__init__(self, mixedclass_, content_) +supermod.docParamName.subclass = docParamNameSub +# end class docParamNameSub + + +class docXRefSectTypeSub(supermod.docXRefSectType): + + node_type = "docxrefsect" + + def __init__(self, id=None, xreftitle=None, xrefdescription=None): + supermod.docXRefSectType.__init__(self, id, xreftitle, xrefdescription) +supermod.docXRefSectType.subclass = docXRefSectTypeSub +# end class docXRefSectTypeSub + + +class docCopyTypeSub(supermod.docCopyType): + + node_type = "doccopy" + + def __init__(self, link=None, para=None, sect1=None, internal=None): + supermod.docCopyType.__init__(self, link, para, sect1, internal) +supermod.docCopyType.subclass = docCopyTypeSub +# end class docCopyTypeSub + + +class docCharTypeSub(supermod.docCharType): + + node_type = "docchar" + + def __init__(self, char=None, valueOf_=''): + supermod.docCharType.__init__(self, char) +supermod.docCharType.subclass = docCharTypeSub +# end class docCharTypeSub + + +class verbatimTypeSub(object): + """ + New node type. Structure is largely pillaged from other nodes in order to + match the set. + """ + + node_type = "verbatim" + + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + self.text = "" + def factory(*args, **kwargs): + return verbatimTypeSub(*args, **kwargs) + factory = staticmethod(factory) + def buildAttributes(self, attrs): + pass + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.text += child_.nodeValue + +class docParaTypeSub(supermod.docParaType): + + node_type = "docpara" + + def __init__(self, char=None, valueOf_=''): + supermod.docParaType.__init__(self, char) + + self.parameterlist = [] + self.simplesects = [] + self.content = [] + + def buildChildren(self, child_, nodeName_): + supermod.docParaType.buildChildren(self, child_, nodeName_) + + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == "ref": + obj_ = supermod.docRefTextType.factory() + obj_.build(child_) + self.content.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'parameterlist': + obj_ = supermod.docParamListType.factory() + obj_.build(child_) + self.parameterlist.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'simplesect': + obj_ = supermod.docSimpleSectType.factory() + obj_.build(child_) + self.simplesects.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and ( + nodeName_ == 'bold' or + nodeName_ == 'emphasis' or + nodeName_ == 'computeroutput' or + nodeName_ == 'subscript' or + nodeName_ == 'superscript' or + nodeName_ == 'center' or + nodeName_ == 'small'): + obj_ = supermod.docMarkupType.factory() + obj_.build(child_) + obj_.type_ = nodeName_ + self.content.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'verbatim': + childobj_ = verbatimTypeSub.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'verbatim', childobj_) + self.content.append(obj_) + +supermod.docParaType.subclass = docParaTypeSub +# end class docParaTypeSub + + +class docMarkupTypeSub(supermod.docMarkupType): + + node_type = "docmarkup" + + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + supermod.docMarkupType.__init__(self, valueOf_, mixedclass_, content_) + self.type_ = None + + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'ref': + childobj_ = supermod.docRefTextType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'ref', childobj_) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +supermod.docMarkupType.subclass = docMarkupTypeSub +# end class docMarkupTypeSub + + +class docTitleTypeSub(supermod.docTitleType): + + node_type = "doctitle" + + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + supermod.docTitleType.__init__(self, valueOf_, mixedclass_, content_) + self.type_ = None +supermod.docTitleType.subclass = docTitleTypeSub +# end class docTitleTypeSub + + +class ParseError(Exception): + pass + +def parse(inFilename): + + try: + doc = minidom.parse(inFilename) + except IOError, e: + print e + raise ParseError(inFilename) + + rootNode = doc.documentElement + rootObj = supermod.DoxygenType.factory() + rootObj.build(rootNode) + return rootObj + + diff --git a/foreignlibs/breathe/breathe/parser/doxygen/compoundsuper.py b/foreignlibs/breathe/breathe/parser/doxygen/compoundsuper.py new file mode 100644 index 00000000..d03872f9 --- /dev/null +++ b/foreignlibs/breathe/breathe/parser/doxygen/compoundsuper.py @@ -0,0 +1,5801 @@ +#!/usr/bin/env python + +# +# Generated Thu Jun 11 18:44:25 2009 by generateDS.py. +# + +import sys +import getopt +from string import lower as str_lower +from xml.dom import minidom +from xml.dom import Node + +# +# User methods +# +# Calls to the methods in these classes are generated by generateDS.py. +# You can replace these methods by re-implementing the following class +# in a module named generatedssuper.py. + +try: + from generatedssuper import GeneratedsSuper +except ImportError, exp: + + class GeneratedsSuper: + def format_string(self, input_data, input_name=''): + return input_data + def format_integer(self, input_data, input_name=''): + return '%d' % input_data + def format_float(self, input_data, input_name=''): + return '%f' % input_data + def format_double(self, input_data, input_name=''): + return '%e' % input_data + def format_boolean(self, input_data, input_name=''): + return '%s' % input_data + + +# +# If you have installed IPython you can uncomment and use the following. +# IPython is available from http://ipython.scipy.org/. +# + +## from IPython.Shell import IPShellEmbed +## args = '' +## ipshell = IPShellEmbed(args, +## banner = 'Dropping into IPython', +## exit_msg = 'Leaving Interpreter, back to program.') + +# Then use the following line where and when you want to drop into the +# IPython shell: +# ipshell(' -- Entering ipshell.\nHit Ctrl-D to exit') + +# +# Globals +# + +ExternalEncoding = 'ascii' + +# +# Support/utility functions. +# + +def showIndent(outfile, level): + for idx in range(level): + outfile.write(' ') + +def quote_xml(inStr): + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + return s1 + +def quote_attrib(inStr): + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + if '"' in s1: + if "'" in s1: + s1 = '"%s"' % s1.replace('"', """) + else: + s1 = "'%s'" % s1 + else: + s1 = '"%s"' % s1 + return s1 + +def quote_python(inStr): + s1 = inStr + if s1.find("'") == -1: + if s1.find('\n') == -1: + return "'%s'" % s1 + else: + return "'''%s'''" % s1 + else: + if s1.find('"') != -1: + s1 = s1.replace('"', '\\"') + if s1.find('\n') == -1: + return '"%s"' % s1 + else: + return '"""%s"""' % s1 + + +class MixedContainer: + + node_type = "mixedcontainer" + + # Constants for category: + CategoryNone = 0 + CategoryText = 1 + CategorySimple = 2 + CategoryComplex = 3 + # Constants for content_type: + TypeNone = 0 + TypeText = 1 + TypeString = 2 + TypeInteger = 3 + TypeFloat = 4 + TypeDecimal = 5 + TypeDouble = 6 + TypeBoolean = 7 + def __init__(self, category, content_type, name, value): + self.category = category + self.content_type = content_type + self.name = name + self.value = value + def getCategory(self): + return self.category + def getContenttype(self, content_type): + return self.content_type + def getValue(self): + return self.value + def getName(self): + return self.name + + +class _MemberSpec(object): + def __init__(self, name='', data_type='', container=0): + self.name = name + self.data_type = data_type + self.container = container + def set_name(self, name): self.name = name + def get_name(self): return self.name + def set_data_type(self, data_type): self.data_type = data_type + def get_data_type(self): return self.data_type + def set_container(self, container): self.container = container + def get_container(self): return self.container + + +# +# Data representation classes. +# + +class DoxygenType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, version=None, compounddef=None): + self.version = version + self.compounddef = compounddef + def factory(*args_, **kwargs_): + if DoxygenType.subclass: + return DoxygenType.subclass(*args_, **kwargs_) + else: + return DoxygenType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_compounddef(self): return self.compounddef + def set_compounddef(self, compounddef): self.compounddef = compounddef + def get_version(self): return self.version + def set_version(self, version): self.version = version + def hasContent_(self): + if ( + self.compounddef is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('version'): + self.version = attrs.get('version').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'compounddef': + obj_ = compounddefType.factory() + obj_.build(child_) + self.set_compounddef(obj_) +# end class DoxygenType + + +class compounddefType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, prot=None, id=None, compoundname=None, title=None, basecompoundref=None, derivedcompoundref=None, includes=None, includedby=None, incdepgraph=None, invincdepgraph=None, innerdir=None, innerfile=None, innerclass=None, innernamespace=None, innerpage=None, innergroup=None, templateparamlist=None, sectiondef=None, briefdescription=None, detaileddescription=None, inheritancegraph=None, collaborationgraph=None, programlisting=None, location=None, listofallmembers=None): + self.kind = kind + self.prot = prot + self.id = id + self.compoundname = compoundname + self.title = title + if basecompoundref is None: + self.basecompoundref = [] + else: + self.basecompoundref = basecompoundref + if derivedcompoundref is None: + self.derivedcompoundref = [] + else: + self.derivedcompoundref = derivedcompoundref + if includes is None: + self.includes = [] + else: + self.includes = includes + if includedby is None: + self.includedby = [] + else: + self.includedby = includedby + self.incdepgraph = incdepgraph + self.invincdepgraph = invincdepgraph + if innerdir is None: + self.innerdir = [] + else: + self.innerdir = innerdir + if innerfile is None: + self.innerfile = [] + else: + self.innerfile = innerfile + if innerclass is None: + self.innerclass = [] + else: + self.innerclass = innerclass + if innernamespace is None: + self.innernamespace = [] + else: + self.innernamespace = innernamespace + if innerpage is None: + self.innerpage = [] + else: + self.innerpage = innerpage + if innergroup is None: + self.innergroup = [] + else: + self.innergroup = innergroup + self.templateparamlist = templateparamlist + if sectiondef is None: + self.sectiondef = [] + else: + self.sectiondef = sectiondef + self.briefdescription = briefdescription + self.detaileddescription = detaileddescription + self.inheritancegraph = inheritancegraph + self.collaborationgraph = collaborationgraph + self.programlisting = programlisting + self.location = location + self.listofallmembers = listofallmembers + self.namespaces = [] + def factory(*args_, **kwargs_): + if compounddefType.subclass: + return compounddefType.subclass(*args_, **kwargs_) + else: + return compounddefType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_compoundname(self): return self.compoundname + def set_compoundname(self, compoundname): self.compoundname = compoundname + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_basecompoundref(self): return self.basecompoundref + def set_basecompoundref(self, basecompoundref): self.basecompoundref = basecompoundref + def add_basecompoundref(self, value): self.basecompoundref.append(value) + def insert_basecompoundref(self, index, value): self.basecompoundref[index] = value + def get_derivedcompoundref(self): return self.derivedcompoundref + def set_derivedcompoundref(self, derivedcompoundref): self.derivedcompoundref = derivedcompoundref + def add_derivedcompoundref(self, value): self.derivedcompoundref.append(value) + def insert_derivedcompoundref(self, index, value): self.derivedcompoundref[index] = value + def get_includes(self): return self.includes + def set_includes(self, includes): self.includes = includes + def add_includes(self, value): self.includes.append(value) + def insert_includes(self, index, value): self.includes[index] = value + def get_includedby(self): return self.includedby + def set_includedby(self, includedby): self.includedby = includedby + def add_includedby(self, value): self.includedby.append(value) + def insert_includedby(self, index, value): self.includedby[index] = value + def get_incdepgraph(self): return self.incdepgraph + def set_incdepgraph(self, incdepgraph): self.incdepgraph = incdepgraph + def get_invincdepgraph(self): return self.invincdepgraph + def set_invincdepgraph(self, invincdepgraph): self.invincdepgraph = invincdepgraph + def get_innerdir(self): return self.innerdir + def set_innerdir(self, innerdir): self.innerdir = innerdir + def add_innerdir(self, value): self.innerdir.append(value) + def insert_innerdir(self, index, value): self.innerdir[index] = value + def get_innerfile(self): return self.innerfile + def set_innerfile(self, innerfile): self.innerfile = innerfile + def add_innerfile(self, value): self.innerfile.append(value) + def insert_innerfile(self, index, value): self.innerfile[index] = value + def get_innerclass(self): return self.innerclass + def set_innerclass(self, innerclass): self.innerclass = innerclass + def add_innerclass(self, value): self.innerclass.append(value) + def insert_innerclass(self, index, value): self.innerclass[index] = value + def get_innernamespace(self): return self.innernamespace + def set_innernamespace(self, innernamespace): self.innernamespace = innernamespace + def add_innernamespace(self, value): self.innernamespace.append(value) + def insert_innernamespace(self, index, value): self.innernamespace[index] = value + def get_innerpage(self): return self.innerpage + def set_innerpage(self, innerpage): self.innerpage = innerpage + def add_innerpage(self, value): self.innerpage.append(value) + def insert_innerpage(self, index, value): self.innerpage[index] = value + def get_innergroup(self): return self.innergroup + def set_innergroup(self, innergroup): self.innergroup = innergroup + def add_innergroup(self, value): self.innergroup.append(value) + def insert_innergroup(self, index, value): self.innergroup[index] = value + def get_templateparamlist(self): return self.templateparamlist + def set_templateparamlist(self, templateparamlist): self.templateparamlist = templateparamlist + def get_sectiondef(self): return self.sectiondef + def set_sectiondef(self, sectiondef): self.sectiondef = sectiondef + def add_sectiondef(self, value): self.sectiondef.append(value) + def insert_sectiondef(self, index, value): self.sectiondef[index] = value + def get_briefdescription(self): return self.briefdescription + def set_briefdescription(self, briefdescription): self.briefdescription = briefdescription + def get_detaileddescription(self): return self.detaileddescription + def set_detaileddescription(self, detaileddescription): self.detaileddescription = detaileddescription + def get_inheritancegraph(self): return self.inheritancegraph + def set_inheritancegraph(self, inheritancegraph): self.inheritancegraph = inheritancegraph + def get_collaborationgraph(self): return self.collaborationgraph + def set_collaborationgraph(self, collaborationgraph): self.collaborationgraph = collaborationgraph + def get_programlisting(self): return self.programlisting + def set_programlisting(self, programlisting): self.programlisting = programlisting + def get_location(self): return self.location + def set_location(self, location): self.location = location + def get_listofallmembers(self): return self.listofallmembers + def set_listofallmembers(self, listofallmembers): self.listofallmembers = listofallmembers + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_id(self): return self.id + def set_id(self, id): self.id = id + def hasContent_(self): + if ( + self.compoundname is not None or + self.title is not None or + self.basecompoundref is not None or + self.derivedcompoundref is not None or + self.includes is not None or + self.includedby is not None or + self.incdepgraph is not None or + self.invincdepgraph is not None or + self.innerdir is not None or + self.innerfile is not None or + self.innerclass is not None or + self.innernamespace is not None or + self.innerpage is not None or + self.innergroup is not None or + self.templateparamlist is not None or + self.sectiondef is not None or + self.briefdescription is not None or + self.detaileddescription is not None or + self.inheritancegraph is not None or + self.collaborationgraph is not None or + self.programlisting is not None or + self.location is not None or + self.listofallmembers is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'compoundname': + compoundname_ = '' + for text__content_ in child_.childNodes: + compoundname_ += text__content_.nodeValue + self.compoundname = compoundname_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + obj_ = docTitleType.factory() + obj_.build(child_) + self.set_title(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'basecompoundref': + obj_ = compoundRefType.factory() + obj_.build(child_) + self.basecompoundref.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'derivedcompoundref': + obj_ = compoundRefType.factory() + obj_.build(child_) + self.derivedcompoundref.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'includes': + obj_ = incType.factory() + obj_.build(child_) + self.includes.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'includedby': + obj_ = incType.factory() + obj_.build(child_) + self.includedby.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'incdepgraph': + obj_ = graphType.factory() + obj_.build(child_) + self.set_incdepgraph(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'invincdepgraph': + obj_ = graphType.factory() + obj_.build(child_) + self.set_invincdepgraph(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innerdir': + obj_ = refType.factory(nodeName_) + obj_.build(child_) + self.innerdir.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innerfile': + obj_ = refType.factory(nodeName_) + obj_.build(child_) + self.innerfile.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innerclass': + obj_ = refType.factory(nodeName_) + obj_.build(child_) + self.innerclass.append(obj_) + self.namespaces.append(obj_.content_[0].getValue()) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innernamespace': + obj_ = refType.factory(nodeName_) + obj_.build(child_) + self.innernamespace.append(obj_) + self.namespaces.append(obj_.content_[0].getValue()) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innerpage': + obj_ = refType.factory(nodeName_) + obj_.build(child_) + self.innerpage.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innergroup': + obj_ = refType.factory(nodeName_) + obj_.build(child_) + self.innergroup.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'templateparamlist': + obj_ = templateparamlistType.factory() + obj_.build(child_) + self.set_templateparamlist(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sectiondef': + obj_ = sectiondefType.factory() + obj_.build(child_) + self.sectiondef.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'briefdescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_briefdescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'detaileddescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_detaileddescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'inheritancegraph': + obj_ = graphType.factory() + obj_.build(child_) + self.set_inheritancegraph(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'collaborationgraph': + obj_ = graphType.factory() + obj_.build(child_) + self.set_collaborationgraph(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'programlisting': + obj_ = listingType.factory() + obj_.build(child_) + self.set_programlisting(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'location': + obj_ = locationType.factory() + obj_.build(child_) + self.set_location(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'listofallmembers': + obj_ = listofallmembersType.factory() + obj_.build(child_) + self.set_listofallmembers(obj_) +# end class compounddefType + + +class listofallmembersType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, member=None): + if member is None: + self.member = [] + else: + self.member = member + def factory(*args_, **kwargs_): + if listofallmembersType.subclass: + return listofallmembersType.subclass(*args_, **kwargs_) + else: + return listofallmembersType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_member(self): return self.member + def set_member(self, member): self.member = member + def add_member(self, value): self.member.append(value) + def insert_member(self, index, value): self.member[index] = value + def hasContent_(self): + if ( + self.member is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'member': + obj_ = memberRefType.factory() + obj_.build(child_) + self.member.append(obj_) +# end class listofallmembersType + + +class memberRefType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, virt=None, prot=None, refid=None, ambiguityscope=None, scope=None, name=None): + self.virt = virt + self.prot = prot + self.refid = refid + self.ambiguityscope = ambiguityscope + self.scope = scope + self.name = name + def factory(*args_, **kwargs_): + if memberRefType.subclass: + return memberRefType.subclass(*args_, **kwargs_) + else: + return memberRefType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_scope(self): return self.scope + def set_scope(self, scope): self.scope = scope + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_virt(self): return self.virt + def set_virt(self, virt): self.virt = virt + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def get_ambiguityscope(self): return self.ambiguityscope + def set_ambiguityscope(self, ambiguityscope): self.ambiguityscope = ambiguityscope + def hasContent_(self): + if ( + self.scope is not None or + self.name is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('virt'): + self.virt = attrs.get('virt').value + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + if attrs.get('ambiguityscope'): + self.ambiguityscope = attrs.get('ambiguityscope').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'scope': + scope_ = '' + for text__content_ in child_.childNodes: + scope_ += text__content_.nodeValue + self.scope = scope_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + name_ = '' + for text__content_ in child_.childNodes: + name_ += text__content_.nodeValue + self.name = name_ +# end class memberRefType + + +class scope(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if scope.subclass: + return scope.subclass(*args_, **kwargs_) + else: + return scope(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class scope + + +class name(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if name.subclass: + return name.subclass(*args_, **kwargs_) + else: + return name(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class name + + +class compoundRefType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, virt=None, prot=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + self.virt = virt + self.prot = prot + self.refid = refid + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if compoundRefType.subclass: + return compoundRefType.subclass(*args_, **kwargs_) + else: + return compoundRefType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_virt(self): return self.virt + def set_virt(self, virt): self.virt = virt + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('virt'): + self.virt = attrs.get('virt').value + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class compoundRefType + + +class reimplementType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, refid=None, valueOf_='', mixedclass_=None, content_=None): + self.refid = refid + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if reimplementType.subclass: + return reimplementType.subclass(*args_, **kwargs_) + else: + return reimplementType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class reimplementType + + +class incType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, local=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + self.local = local + self.refid = refid + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if incType.subclass: + return incType.subclass(*args_, **kwargs_) + else: + return incType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_local(self): return self.local + def set_local(self, local): self.local = local + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('local'): + self.local = attrs.get('local').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class incType + + +class refType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, prot=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + self.prot = prot + self.refid = refid + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if refType.subclass: + return refType.subclass(*args_, **kwargs_) + else: + return refType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class refType + + +class refTextType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, refid=None, kindref=None, external=None, valueOf_='', mixedclass_=None, content_=None): + self.refid = refid + self.kindref = kindref + self.external = external + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if refTextType.subclass: + return refTextType.subclass(*args_, **kwargs_) + else: + return refTextType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def get_kindref(self): return self.kindref + def set_kindref(self, kindref): self.kindref = kindref + def get_external(self): return self.external + def set_external(self, external): self.external = external + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('refid'): + self.refid = attrs.get('refid').value + if attrs.get('kindref'): + self.kindref = attrs.get('kindref').value + if attrs.get('external'): + self.external = attrs.get('external').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class refTextType + + +class sectiondefType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, header=None, description=None, memberdef=None): + self.kind = kind + self.header = header + self.description = description + if memberdef is None: + self.memberdef = [] + else: + self.memberdef = memberdef + def factory(*args_, **kwargs_): + if sectiondefType.subclass: + return sectiondefType.subclass(*args_, **kwargs_) + else: + return sectiondefType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_header(self): return self.header + def set_header(self, header): self.header = header + def get_description(self): return self.description + def set_description(self, description): self.description = description + def get_memberdef(self): return self.memberdef + def set_memberdef(self, memberdef): self.memberdef = memberdef + def add_memberdef(self, value): self.memberdef.append(value) + def insert_memberdef(self, index, value): self.memberdef[index] = value + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def hasContent_(self): + if ( + self.header is not None or + self.description is not None or + self.memberdef is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'header': + header_ = '' + for text__content_ in child_.childNodes: + header_ += text__content_.nodeValue + self.header = header_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'description': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_description(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'memberdef': + obj_ = memberdefType.factory() + obj_.build(child_) + self.memberdef.append(obj_) +# end class sectiondefType + + +class memberdefType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, initonly=None, kind=None, volatile=None, const=None, raisexx=None, virt=None, readable=None, prot=None, explicit=None, new=None, final=None, writable=None, add=None, static=None, remove=None, sealed=None, mutable=None, gettable=None, inline=None, settable=None, id=None, templateparamlist=None, type_=None, definition=None, argsstring=None, name=None, read=None, write=None, bitfield=None, reimplements=None, reimplementedby=None, param=None, enumvalue=None, initializer=None, exceptions=None, briefdescription=None, detaileddescription=None, inbodydescription=None, location=None, references=None, referencedby=None): + self.initonly = initonly + self.kind = kind + self.volatile = volatile + self.const = const + self.raisexx = raisexx + self.virt = virt + self.readable = readable + self.prot = prot + self.explicit = explicit + self.new = new + self.final = final + self.writable = writable + self.add = add + self.static = static + self.remove = remove + self.sealed = sealed + self.mutable = mutable + self.gettable = gettable + self.inline = inline + self.settable = settable + self.id = id + self.templateparamlist = templateparamlist + self.type_ = type_ + self.definition = definition + self.argsstring = argsstring + self.name = name + self.read = read + self.write = write + self.bitfield = bitfield + if reimplements is None: + self.reimplements = [] + else: + self.reimplements = reimplements + if reimplementedby is None: + self.reimplementedby = [] + else: + self.reimplementedby = reimplementedby + if param is None: + self.param = [] + else: + self.param = param + if enumvalue is None: + self.enumvalue = [] + else: + self.enumvalue = enumvalue + self.initializer = initializer + self.exceptions = exceptions + self.briefdescription = briefdescription + self.detaileddescription = detaileddescription + self.inbodydescription = inbodydescription + self.location = location + if references is None: + self.references = [] + else: + self.references = references + if referencedby is None: + self.referencedby = [] + else: + self.referencedby = referencedby + def factory(*args_, **kwargs_): + if memberdefType.subclass: + return memberdefType.subclass(*args_, **kwargs_) + else: + return memberdefType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_templateparamlist(self): return self.templateparamlist + def set_templateparamlist(self, templateparamlist): self.templateparamlist = templateparamlist + def get_type(self): return self.type_ + def set_type(self, type_): self.type_ = type_ + def get_definition(self): return self.definition + def set_definition(self, definition): self.definition = definition + def get_argsstring(self): return self.argsstring + def set_argsstring(self, argsstring): self.argsstring = argsstring + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_read(self): return self.read + def set_read(self, read): self.read = read + def get_write(self): return self.write + def set_write(self, write): self.write = write + def get_bitfield(self): return self.bitfield + def set_bitfield(self, bitfield): self.bitfield = bitfield + def get_reimplements(self): return self.reimplements + def set_reimplements(self, reimplements): self.reimplements = reimplements + def add_reimplements(self, value): self.reimplements.append(value) + def insert_reimplements(self, index, value): self.reimplements[index] = value + def get_reimplementedby(self): return self.reimplementedby + def set_reimplementedby(self, reimplementedby): self.reimplementedby = reimplementedby + def add_reimplementedby(self, value): self.reimplementedby.append(value) + def insert_reimplementedby(self, index, value): self.reimplementedby[index] = value + def get_param(self): return self.param + def set_param(self, param): self.param = param + def add_param(self, value): self.param.append(value) + def insert_param(self, index, value): self.param[index] = value + def get_enumvalue(self): return self.enumvalue + def set_enumvalue(self, enumvalue): self.enumvalue = enumvalue + def add_enumvalue(self, value): self.enumvalue.append(value) + def insert_enumvalue(self, index, value): self.enumvalue[index] = value + def get_initializer(self): return self.initializer + def set_initializer(self, initializer): self.initializer = initializer + def get_exceptions(self): return self.exceptions + def set_exceptions(self, exceptions): self.exceptions = exceptions + def get_briefdescription(self): return self.briefdescription + def set_briefdescription(self, briefdescription): self.briefdescription = briefdescription + def get_detaileddescription(self): return self.detaileddescription + def set_detaileddescription(self, detaileddescription): self.detaileddescription = detaileddescription + def get_inbodydescription(self): return self.inbodydescription + def set_inbodydescription(self, inbodydescription): self.inbodydescription = inbodydescription + def get_location(self): return self.location + def set_location(self, location): self.location = location + def get_references(self): return self.references + def set_references(self, references): self.references = references + def add_references(self, value): self.references.append(value) + def insert_references(self, index, value): self.references[index] = value + def get_referencedby(self): return self.referencedby + def set_referencedby(self, referencedby): self.referencedby = referencedby + def add_referencedby(self, value): self.referencedby.append(value) + def insert_referencedby(self, index, value): self.referencedby[index] = value + def get_initonly(self): return self.initonly + def set_initonly(self, initonly): self.initonly = initonly + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def get_volatile(self): return self.volatile + def set_volatile(self, volatile): self.volatile = volatile + def get_const(self): return self.const + def set_const(self, const): self.const = const + def get_raise(self): return self.raisexx + def set_raise(self, raisexx): self.raisexx = raisexx + def get_virt(self): return self.virt + def set_virt(self, virt): self.virt = virt + def get_readable(self): return self.readable + def set_readable(self, readable): self.readable = readable + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_explicit(self): return self.explicit + def set_explicit(self, explicit): self.explicit = explicit + def get_new(self): return self.new + def set_new(self, new): self.new = new + def get_final(self): return self.final + def set_final(self, final): self.final = final + def get_writable(self): return self.writable + def set_writable(self, writable): self.writable = writable + def get_add(self): return self.add + def set_add(self, add): self.add = add + def get_static(self): return self.static + def set_static(self, static): self.static = static + def get_remove(self): return self.remove + def set_remove(self, remove): self.remove = remove + def get_sealed(self): return self.sealed + def set_sealed(self, sealed): self.sealed = sealed + def get_mutable(self): return self.mutable + def set_mutable(self, mutable): self.mutable = mutable + def get_gettable(self): return self.gettable + def set_gettable(self, gettable): self.gettable = gettable + def get_inline(self): return self.inline + def set_inline(self, inline): self.inline = inline + def get_settable(self): return self.settable + def set_settable(self, settable): self.settable = settable + def get_id(self): return self.id + def set_id(self, id): self.id = id + def hasContent_(self): + if ( + self.templateparamlist is not None or + self.type_ is not None or + self.definition is not None or + self.argsstring is not None or + self.name is not None or + self.read is not None or + self.write is not None or + self.bitfield is not None or + self.reimplements is not None or + self.reimplementedby is not None or + self.param is not None or + self.enumvalue is not None or + self.initializer is not None or + self.exceptions is not None or + self.briefdescription is not None or + self.detaileddescription is not None or + self.inbodydescription is not None or + self.location is not None or + self.references is not None or + self.referencedby is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('initonly'): + self.initonly = attrs.get('initonly').value + if attrs.get('kind'): + self.kind = attrs.get('kind').value + if attrs.get('volatile'): + self.volatile = attrs.get('volatile').value + if attrs.get('const'): + self.const = attrs.get('const').value + if attrs.get('raise'): + self.raisexx = attrs.get('raise').value + if attrs.get('virt'): + self.virt = attrs.get('virt').value + if attrs.get('readable'): + self.readable = attrs.get('readable').value + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('explicit'): + self.explicit = attrs.get('explicit').value + if attrs.get('new'): + self.new = attrs.get('new').value + if attrs.get('final'): + self.final = attrs.get('final').value + if attrs.get('writable'): + self.writable = attrs.get('writable').value + if attrs.get('add'): + self.add = attrs.get('add').value + if attrs.get('static'): + self.static = attrs.get('static').value + if attrs.get('remove'): + self.remove = attrs.get('remove').value + if attrs.get('sealed'): + self.sealed = attrs.get('sealed').value + if attrs.get('mutable'): + self.mutable = attrs.get('mutable').value + if attrs.get('gettable'): + self.gettable = attrs.get('gettable').value + if attrs.get('inline'): + self.inline = attrs.get('inline').value + if attrs.get('settable'): + self.settable = attrs.get('settable').value + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'templateparamlist': + obj_ = templateparamlistType.factory() + obj_.build(child_) + self.set_templateparamlist(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'type': + obj_ = linkedTextType.factory() + obj_.build(child_) + self.set_type(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'definition': + definition_ = '' + for text__content_ in child_.childNodes: + definition_ += text__content_.nodeValue + self.definition = definition_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'argsstring': + argsstring_ = '' + for text__content_ in child_.childNodes: + argsstring_ += text__content_.nodeValue + self.argsstring = argsstring_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + name_ = '' + for text__content_ in child_.childNodes: + name_ += text__content_.nodeValue + self.name = name_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'read': + read_ = '' + for text__content_ in child_.childNodes: + read_ += text__content_.nodeValue + self.read = read_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'write': + write_ = '' + for text__content_ in child_.childNodes: + write_ += text__content_.nodeValue + self.write = write_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'bitfield': + bitfield_ = '' + for text__content_ in child_.childNodes: + bitfield_ += text__content_.nodeValue + self.bitfield = bitfield_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'reimplements': + obj_ = reimplementType.factory() + obj_.build(child_) + self.reimplements.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'reimplementedby': + obj_ = reimplementType.factory() + obj_.build(child_) + self.reimplementedby.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'param': + obj_ = paramType.factory() + obj_.build(child_) + self.param.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'enumvalue': + obj_ = enumvalueType.factory() + obj_.build(child_) + self.enumvalue.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'initializer': + obj_ = linkedTextType.factory() + obj_.build(child_) + self.set_initializer(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'exceptions': + obj_ = linkedTextType.factory() + obj_.build(child_) + self.set_exceptions(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'briefdescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_briefdescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'detaileddescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_detaileddescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'inbodydescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_inbodydescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'location': + obj_ = locationType.factory() + obj_.build(child_) + self.set_location(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'references': + obj_ = referenceType.factory() + obj_.build(child_) + self.references.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'referencedby': + obj_ = referenceType.factory() + obj_.build(child_) + self.referencedby.append(obj_) +# end class memberdefType + + +class definition(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if definition.subclass: + return definition.subclass(*args_, **kwargs_) + else: + return definition(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class definition + + +class argsstring(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if argsstring.subclass: + return argsstring.subclass(*args_, **kwargs_) + else: + return argsstring(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='argsstring', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='argsstring') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class argsstring + + +class read(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if read.subclass: + return read.subclass(*args_, **kwargs_) + else: + return read(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class read + + +class write(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if write.subclass: + return write.subclass(*args_, **kwargs_) + else: + return write(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class write + + +class bitfield(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if bitfield.subclass: + return bitfield.subclass(*args_, **kwargs_) + else: + return bitfield(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class bitfield + + +class descriptionType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, title=None, para=None, sect1=None, internal=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if descriptionType.subclass: + return descriptionType.subclass(*args_, **kwargs_) + else: + return descriptionType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect1(self): return self.sect1 + def set_sect1(self, sect1): self.sect1 = sect1 + def add_sect1(self, value): self.sect1.append(value) + def insert_sect1(self, index, value): self.sect1[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def hasContent_(self): + if ( + self.title is not None or + self.para is not None or + self.sect1 is not None or + self.internal is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + childobj_ = docTitleType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'title', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect1': + childobj_ = docSect1Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect1', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + childobj_ = docInternalType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'internal', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class descriptionType + + +class enumvalueType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, prot=None, id=None, name=None, initializer=None, briefdescription=None, detaileddescription=None, mixedclass_=None, content_=None): + self.prot = prot + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if enumvalueType.subclass: + return enumvalueType.subclass(*args_, **kwargs_) + else: + return enumvalueType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_initializer(self): return self.initializer + def set_initializer(self, initializer): self.initializer = initializer + def get_briefdescription(self): return self.briefdescription + def set_briefdescription(self, briefdescription): self.briefdescription = briefdescription + def get_detaileddescription(self): return self.detaileddescription + def set_detaileddescription(self, detaileddescription): self.detaileddescription = detaileddescription + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_id(self): return self.id + def set_id(self, id): self.id = id + def hasContent_(self): + if ( + self.name is not None or + self.initializer is not None or + self.briefdescription is not None or + self.detaileddescription is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + value_ = [] + for text_ in child_.childNodes: + value_.append(text_.nodeValue) + valuestr_ = ''.join(value_) + obj_ = self.mixedclass_(MixedContainer.CategorySimple, + MixedContainer.TypeString, 'name', valuestr_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'initializer': + childobj_ = linkedTextType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'initializer', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'briefdescription': + childobj_ = descriptionType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'briefdescription', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'detaileddescription': + childobj_ = descriptionType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'detaileddescription', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class enumvalueType + + +class templateparamlistType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, param=None): + if param is None: + self.param = [] + else: + self.param = param + def factory(*args_, **kwargs_): + if templateparamlistType.subclass: + return templateparamlistType.subclass(*args_, **kwargs_) + else: + return templateparamlistType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_param(self): return self.param + def set_param(self, param): self.param = param + def add_param(self, value): self.param.append(value) + def insert_param(self, index, value): self.param[index] = value + def hasContent_(self): + if ( + self.param is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'param': + obj_ = paramType.factory() + obj_.build(child_) + self.param.append(obj_) +# end class templateparamlistType + + +class paramType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, type_=None, declname=None, defname=None, array=None, defval=None, briefdescription=None): + self.type_ = type_ + self.declname = declname + self.defname = defname + self.array = array + self.defval = defval + self.briefdescription = briefdescription + def factory(*args_, **kwargs_): + if paramType.subclass: + return paramType.subclass(*args_, **kwargs_) + else: + return paramType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_type(self): return self.type_ + def set_type(self, type_): self.type_ = type_ + def get_declname(self): return self.declname + def set_declname(self, declname): self.declname = declname + def get_defname(self): return self.defname + def set_defname(self, defname): self.defname = defname + def get_array(self): return self.array + def set_array(self, array): self.array = array + def get_defval(self): return self.defval + def set_defval(self, defval): self.defval = defval + def get_briefdescription(self): return self.briefdescription + def set_briefdescription(self, briefdescription): self.briefdescription = briefdescription + def hasContent_(self): + if ( + self.type_ is not None or + self.declname is not None or + self.defname is not None or + self.array is not None or + self.defval is not None or + self.briefdescription is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'type': + obj_ = linkedTextType.factory() + obj_.build(child_) + self.set_type(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'declname': + declname_ = '' + for text__content_ in child_.childNodes: + declname_ += text__content_.nodeValue + self.declname = declname_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'defname': + defname_ = '' + for text__content_ in child_.childNodes: + defname_ += text__content_.nodeValue + self.defname = defname_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'array': + array_ = '' + for text__content_ in child_.childNodes: + array_ += text__content_.nodeValue + self.array = array_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'defval': + obj_ = linkedTextType.factory() + obj_.build(child_) + self.set_defval(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'briefdescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_briefdescription(obj_) +# end class paramType + + +class declname(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if declname.subclass: + return declname.subclass(*args_, **kwargs_) + else: + return declname(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class declname + + +class defname(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if defname.subclass: + return defname.subclass(*args_, **kwargs_) + else: + return defname(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class defname + + +class array(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if array.subclass: + return array.subclass(*args_, **kwargs_) + else: + return array(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class array + + +class linkedTextType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, ref=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if linkedTextType.subclass: + return linkedTextType.subclass(*args_, **kwargs_) + else: + return linkedTextType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_ref(self): return self.ref + def set_ref(self, ref): self.ref = ref + def add_ref(self, value): self.ref.append(value) + def insert_ref(self, index, value): self.ref[index] = value + def hasContent_(self): + if ( + self.ref is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'ref': + childobj_ = docRefTextType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'ref', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class linkedTextType + + +class graphType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, node=None): + if node is None: + self.node = [] + else: + self.node = node + def factory(*args_, **kwargs_): + if graphType.subclass: + return graphType.subclass(*args_, **kwargs_) + else: + return graphType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_node(self): return self.node + def set_node(self, node): self.node = node + def add_node(self, value): self.node.append(value) + def insert_node(self, index, value): self.node[index] = value + def hasContent_(self): + if ( + self.node is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'node': + obj_ = nodeType.factory() + obj_.build(child_) + self.node.append(obj_) +# end class graphType + + +class nodeType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, label=None, link=None, childnode=None): + self.id = id + self.label = label + self.link = link + if childnode is None: + self.childnode = [] + else: + self.childnode = childnode + def factory(*args_, **kwargs_): + if nodeType.subclass: + return nodeType.subclass(*args_, **kwargs_) + else: + return nodeType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_label(self): return self.label + def set_label(self, label): self.label = label + def get_link(self): return self.link + def set_link(self, link): self.link = link + def get_childnode(self): return self.childnode + def set_childnode(self, childnode): self.childnode = childnode + def add_childnode(self, value): self.childnode.append(value) + def insert_childnode(self, index, value): self.childnode[index] = value + def get_id(self): return self.id + def set_id(self, id): self.id = id + def hasContent_(self): + if ( + self.label is not None or + self.link is not None or + self.childnode is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'label': + label_ = '' + for text__content_ in child_.childNodes: + label_ += text__content_.nodeValue + self.label = label_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'link': + obj_ = linkType.factory() + obj_.build(child_) + self.set_link(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'childnode': + obj_ = childnodeType.factory() + obj_.build(child_) + self.childnode.append(obj_) +# end class nodeType + + +class label(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if label.subclass: + return label.subclass(*args_, **kwargs_) + else: + return label(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class label + + +class childnodeType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, relation=None, refid=None, edgelabel=None): + self.relation = relation + self.refid = refid + if edgelabel is None: + self.edgelabel = [] + else: + self.edgelabel = edgelabel + def factory(*args_, **kwargs_): + if childnodeType.subclass: + return childnodeType.subclass(*args_, **kwargs_) + else: + return childnodeType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_edgelabel(self): return self.edgelabel + def set_edgelabel(self, edgelabel): self.edgelabel = edgelabel + def add_edgelabel(self, value): self.edgelabel.append(value) + def insert_edgelabel(self, index, value): self.edgelabel[index] = value + def get_relation(self): return self.relation + def set_relation(self, relation): self.relation = relation + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def export(self, outfile, level, namespace_='', name_='childnodeType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='childnodeType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='childnodeType'): + if self.relation is not None: + outfile.write(' relation=%s' % (quote_attrib(self.relation), )) + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='childnodeType'): + for edgelabel_ in self.edgelabel: + showIndent(outfile, level) + outfile.write('<%sedgelabel>%s\n' % (namespace_, self.format_string(quote_xml(edgelabel_).encode(ExternalEncoding), input_name='edgelabel'), namespace_)) + def hasContent_(self): + if ( + self.edgelabel is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('relation'): + self.relation = attrs.get('relation').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'edgelabel': + edgelabel_ = '' + for text__content_ in child_.childNodes: + edgelabel_ += text__content_.nodeValue + self.edgelabel.append(edgelabel_) +# end class childnodeType + + +class edgelabel(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if edgelabel.subclass: + return edgelabel.subclass(*args_, **kwargs_) + else: + return edgelabel(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='edgelabel', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='edgelabel') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='edgelabel'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='edgelabel'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class edgelabel + + +class linkType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, refid=None, external=None, valueOf_=''): + self.refid = refid + self.external = external + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if linkType.subclass: + return linkType.subclass(*args_, **kwargs_) + else: + return linkType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def get_external(self): return self.external + def set_external(self, external): self.external = external + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='linkType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='linkType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='linkType'): + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + if self.external is not None: + outfile.write(' external=%s' % (self.format_string(quote_attrib(self.external).encode(ExternalEncoding), input_name='external'), )) + def exportChildren(self, outfile, level, namespace_='', name_='linkType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('refid'): + self.refid = attrs.get('refid').value + if attrs.get('external'): + self.external = attrs.get('external').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class linkType + + +class listingType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, codeline=None): + if codeline is None: + self.codeline = [] + else: + self.codeline = codeline + def factory(*args_, **kwargs_): + if listingType.subclass: + return listingType.subclass(*args_, **kwargs_) + else: + return listingType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_codeline(self): return self.codeline + def set_codeline(self, codeline): self.codeline = codeline + def add_codeline(self, value): self.codeline.append(value) + def insert_codeline(self, index, value): self.codeline[index] = value + def export(self, outfile, level, namespace_='', name_='listingType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='listingType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='listingType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='listingType'): + for codeline_ in self.codeline: + codeline_.export(outfile, level, namespace_, name_='codeline') + def hasContent_(self): + if ( + self.codeline is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'codeline': + obj_ = codelineType.factory() + obj_.build(child_) + self.codeline.append(obj_) +# end class listingType + + +class codelineType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, external=None, lineno=None, refkind=None, refid=None, highlight=None): + self.external = external + self.lineno = lineno + self.refkind = refkind + self.refid = refid + if highlight is None: + self.highlight = [] + else: + self.highlight = highlight + def factory(*args_, **kwargs_): + if codelineType.subclass: + return codelineType.subclass(*args_, **kwargs_) + else: + return codelineType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_highlight(self): return self.highlight + def set_highlight(self, highlight): self.highlight = highlight + def add_highlight(self, value): self.highlight.append(value) + def insert_highlight(self, index, value): self.highlight[index] = value + def get_external(self): return self.external + def set_external(self, external): self.external = external + def get_lineno(self): return self.lineno + def set_lineno(self, lineno): self.lineno = lineno + def get_refkind(self): return self.refkind + def set_refkind(self, refkind): self.refkind = refkind + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def export(self, outfile, level, namespace_='', name_='codelineType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='codelineType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='codelineType'): + if self.external is not None: + outfile.write(' external=%s' % (quote_attrib(self.external), )) + if self.lineno is not None: + outfile.write(' lineno="%s"' % self.format_integer(self.lineno, input_name='lineno')) + if self.refkind is not None: + outfile.write(' refkind=%s' % (quote_attrib(self.refkind), )) + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='codelineType'): + for highlight_ in self.highlight: + highlight_.export(outfile, level, namespace_, name_='highlight') + def hasContent_(self): + if ( + self.highlight is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('external'): + self.external = attrs.get('external').value + if attrs.get('lineno'): + try: + self.lineno = int(attrs.get('lineno').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (lineno): %s' % exp) + if attrs.get('refkind'): + self.refkind = attrs.get('refkind').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'highlight': + obj_ = highlightType.factory() + obj_.build(child_) + self.highlight.append(obj_) +# end class codelineType + + +class highlightType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, classxx=None, sp=None, ref=None, mixedclass_=None, content_=None): + self.classxx = classxx + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if highlightType.subclass: + return highlightType.subclass(*args_, **kwargs_) + else: + return highlightType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_sp(self): return self.sp + def set_sp(self, sp): self.sp = sp + def add_sp(self, value): self.sp.append(value) + def insert_sp(self, index, value): self.sp[index] = value + def get_ref(self): return self.ref + def set_ref(self, ref): self.ref = ref + def add_ref(self, value): self.ref.append(value) + def insert_ref(self, index, value): self.ref[index] = value + def get_class(self): return self.classxx + def set_class(self, classxx): self.classxx = classxx + def export(self, outfile, level, namespace_='', name_='highlightType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='highlightType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='highlightType'): + if self.classxx is not None: + outfile.write(' class=%s' % (quote_attrib(self.classxx), )) + def exportChildren(self, outfile, level, namespace_='', name_='highlightType'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.sp is not None or + self.ref is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('class'): + self.classxx = attrs.get('class').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sp': + value_ = [] + for text_ in child_.childNodes: + value_.append(text_.nodeValue) + valuestr_ = ''.join(value_) + obj_ = self.mixedclass_(MixedContainer.CategorySimple, + MixedContainer.TypeString, 'sp', valuestr_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'ref': + childobj_ = docRefTextType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'ref', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class highlightType + + +class sp(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if sp.subclass: + return sp.subclass(*args_, **kwargs_) + else: + return sp(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='sp', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='sp') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='sp'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='sp'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class sp + + +class referenceType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, endline=None, startline=None, refid=None, compoundref=None, valueOf_='', mixedclass_=None, content_=None): + self.endline = endline + self.startline = startline + self.refid = refid + self.compoundref = compoundref + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if referenceType.subclass: + return referenceType.subclass(*args_, **kwargs_) + else: + return referenceType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_endline(self): return self.endline + def set_endline(self, endline): self.endline = endline + def get_startline(self): return self.startline + def set_startline(self, startline): self.startline = startline + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def get_compoundref(self): return self.compoundref + def set_compoundref(self, compoundref): self.compoundref = compoundref + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='referenceType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='referenceType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='referenceType'): + if self.endline is not None: + outfile.write(' endline="%s"' % self.format_integer(self.endline, input_name='endline')) + if self.startline is not None: + outfile.write(' startline="%s"' % self.format_integer(self.startline, input_name='startline')) + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + if self.compoundref is not None: + outfile.write(' compoundref=%s' % (self.format_string(quote_attrib(self.compoundref).encode(ExternalEncoding), input_name='compoundref'), )) + def exportChildren(self, outfile, level, namespace_='', name_='referenceType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('endline'): + try: + self.endline = int(attrs.get('endline').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (endline): %s' % exp) + if attrs.get('startline'): + try: + self.startline = int(attrs.get('startline').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (startline): %s' % exp) + if attrs.get('refid'): + self.refid = attrs.get('refid').value + if attrs.get('compoundref'): + self.compoundref = attrs.get('compoundref').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class referenceType + + +class locationType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, bodystart=None, line=None, bodyend=None, bodyfile=None, file=None, valueOf_=''): + self.bodystart = bodystart + self.line = line + self.bodyend = bodyend + self.bodyfile = bodyfile + self.file = file + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if locationType.subclass: + return locationType.subclass(*args_, **kwargs_) + else: + return locationType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_bodystart(self): return self.bodystart + def set_bodystart(self, bodystart): self.bodystart = bodystart + def get_line(self): return self.line + def set_line(self, line): self.line = line + def get_bodyend(self): return self.bodyend + def set_bodyend(self, bodyend): self.bodyend = bodyend + def get_bodyfile(self): return self.bodyfile + def set_bodyfile(self, bodyfile): self.bodyfile = bodyfile + def get_file(self): return self.file + def set_file(self, file): self.file = file + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='locationType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='locationType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='locationType'): + if self.bodystart is not None: + outfile.write(' bodystart="%s"' % self.format_integer(self.bodystart, input_name='bodystart')) + if self.line is not None: + outfile.write(' line="%s"' % self.format_integer(self.line, input_name='line')) + if self.bodyend is not None: + outfile.write(' bodyend="%s"' % self.format_integer(self.bodyend, input_name='bodyend')) + if self.bodyfile is not None: + outfile.write(' bodyfile=%s' % (self.format_string(quote_attrib(self.bodyfile).encode(ExternalEncoding), input_name='bodyfile'), )) + if self.file is not None: + outfile.write(' file=%s' % (self.format_string(quote_attrib(self.file).encode(ExternalEncoding), input_name='file'), )) + def exportChildren(self, outfile, level, namespace_='', name_='locationType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('bodystart'): + try: + self.bodystart = int(attrs.get('bodystart').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (bodystart): %s' % exp) + if attrs.get('line'): + try: + self.line = int(attrs.get('line').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (line): %s' % exp) + if attrs.get('bodyend'): + try: + self.bodyend = int(attrs.get('bodyend').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (bodyend): %s' % exp) + if attrs.get('bodyfile'): + self.bodyfile = attrs.get('bodyfile').value + if attrs.get('file'): + self.file = attrs.get('file').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class locationType + + +class docSect1Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, title=None, para=None, sect2=None, internal=None, mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docSect1Type.subclass: + return docSect1Type.subclass(*args_, **kwargs_) + else: + return docSect1Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect2(self): return self.sect2 + def set_sect2(self, sect2): self.sect2 = sect2 + def add_sect2(self, value): self.sect2.append(value) + def insert_sect2(self, index, value): self.sect2[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='docSect1Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docSect1Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docSect1Type'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docSect1Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.title is not None or + self.para is not None or + self.sect2 is not None or + self.internal is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + childobj_ = docTitleType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'title', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect2': + childobj_ = docSect2Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect2', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + childobj_ = docInternalS1Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'internal', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docSect1Type + + +class docSect2Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, title=None, para=None, sect3=None, internal=None, mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docSect2Type.subclass: + return docSect2Type.subclass(*args_, **kwargs_) + else: + return docSect2Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect3(self): return self.sect3 + def set_sect3(self, sect3): self.sect3 = sect3 + def add_sect3(self, value): self.sect3.append(value) + def insert_sect3(self, index, value): self.sect3[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='docSect2Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docSect2Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docSect2Type'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docSect2Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.title is not None or + self.para is not None or + self.sect3 is not None or + self.internal is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + childobj_ = docTitleType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'title', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect3': + childobj_ = docSect3Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect3', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + childobj_ = docInternalS2Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'internal', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docSect2Type + + +class docSect3Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, title=None, para=None, sect4=None, internal=None, mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docSect3Type.subclass: + return docSect3Type.subclass(*args_, **kwargs_) + else: + return docSect3Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect4(self): return self.sect4 + def set_sect4(self, sect4): self.sect4 = sect4 + def add_sect4(self, value): self.sect4.append(value) + def insert_sect4(self, index, value): self.sect4[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='docSect3Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docSect3Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docSect3Type'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docSect3Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.title is not None or + self.para is not None or + self.sect4 is not None or + self.internal is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + childobj_ = docTitleType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'title', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect4': + childobj_ = docSect4Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect4', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + childobj_ = docInternalS3Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'internal', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docSect3Type + + +class docSect4Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, title=None, para=None, internal=None, mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docSect4Type.subclass: + return docSect4Type.subclass(*args_, **kwargs_) + else: + return docSect4Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='docSect4Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docSect4Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docSect4Type'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docSect4Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.title is not None or + self.para is not None or + self.internal is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + childobj_ = docTitleType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'title', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + childobj_ = docInternalS4Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'internal', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docSect4Type + + +class docInternalType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None, sect1=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docInternalType.subclass: + return docInternalType.subclass(*args_, **kwargs_) + else: + return docInternalType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect1(self): return self.sect1 + def set_sect1(self, sect1): self.sect1 = sect1 + def add_sect1(self, value): self.sect1.append(value) + def insert_sect1(self, index, value): self.sect1[index] = value + def export(self, outfile, level, namespace_='', name_='docInternalType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docInternalType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docInternalType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docInternalType'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.para is not None or + self.sect1 is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect1': + childobj_ = docSect1Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect1', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docInternalType + + +class docInternalS1Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None, sect2=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docInternalS1Type.subclass: + return docInternalS1Type.subclass(*args_, **kwargs_) + else: + return docInternalS1Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect2(self): return self.sect2 + def set_sect2(self, sect2): self.sect2 = sect2 + def add_sect2(self, value): self.sect2.append(value) + def insert_sect2(self, index, value): self.sect2[index] = value + def export(self, outfile, level, namespace_='', name_='docInternalS1Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docInternalS1Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docInternalS1Type'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docInternalS1Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.para is not None or + self.sect2 is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect2': + childobj_ = docSect2Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect2', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docInternalS1Type + + +class docInternalS2Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None, sect3=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docInternalS2Type.subclass: + return docInternalS2Type.subclass(*args_, **kwargs_) + else: + return docInternalS2Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect3(self): return self.sect3 + def set_sect3(self, sect3): self.sect3 = sect3 + def add_sect3(self, value): self.sect3.append(value) + def insert_sect3(self, index, value): self.sect3[index] = value + def export(self, outfile, level, namespace_='', name_='docInternalS2Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docInternalS2Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docInternalS2Type'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docInternalS2Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.para is not None or + self.sect3 is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect3': + childobj_ = docSect3Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect3', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docInternalS2Type + + +class docInternalS3Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None, sect3=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docInternalS3Type.subclass: + return docInternalS3Type.subclass(*args_, **kwargs_) + else: + return docInternalS3Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect3(self): return self.sect3 + def set_sect3(self, sect3): self.sect3 = sect3 + def add_sect3(self, value): self.sect3.append(value) + def insert_sect3(self, index, value): self.sect3[index] = value + def export(self, outfile, level, namespace_='', name_='docInternalS3Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docInternalS3Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docInternalS3Type'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docInternalS3Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.para is not None or + self.sect3 is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect3': + childobj_ = docSect4Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect3', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docInternalS3Type + + +class docInternalS4Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docInternalS4Type.subclass: + return docInternalS4Type.subclass(*args_, **kwargs_) + else: + return docInternalS4Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def export(self, outfile, level, namespace_='', name_='docInternalS4Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docInternalS4Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docInternalS4Type'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docInternalS4Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.para is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docInternalS4Type + + +class docTitleType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docTitleType.subclass: + return docTitleType.subclass(*args_, **kwargs_) + else: + return docTitleType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docTitleType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docTitleType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docTitleType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docTitleType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docTitleType + + +class docParaType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docParaType.subclass: + return docParaType.subclass(*args_, **kwargs_) + else: + return docParaType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docParaType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docParaType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docParaType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docParaType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docParaType + + +class docMarkupType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docMarkupType.subclass: + return docMarkupType.subclass(*args_, **kwargs_) + else: + return docMarkupType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docMarkupType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docMarkupType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docMarkupType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docMarkupType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docMarkupType + + +class docURLLink(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, url=None, valueOf_='', mixedclass_=None, content_=None): + self.url = url + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docURLLink.subclass: + return docURLLink.subclass(*args_, **kwargs_) + else: + return docURLLink(*args_, **kwargs_) + factory = staticmethod(factory) + def get_url(self): return self.url + def set_url(self, url): self.url = url + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docURLLink', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docURLLink') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docURLLink'): + if self.url is not None: + outfile.write(' url=%s' % (self.format_string(quote_attrib(self.url).encode(ExternalEncoding), input_name='url'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docURLLink'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('url'): + self.url = attrs.get('url').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docURLLink + + +class docAnchorType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docAnchorType.subclass: + return docAnchorType.subclass(*args_, **kwargs_) + else: + return docAnchorType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_id(self): return self.id + def set_id(self, id): self.id = id + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docAnchorType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docAnchorType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docAnchorType'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docAnchorType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docAnchorType + + +class docFormulaType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docFormulaType.subclass: + return docFormulaType.subclass(*args_, **kwargs_) + else: + return docFormulaType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_id(self): return self.id + def set_id(self, id): self.id = id + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docFormulaType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docFormulaType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docFormulaType'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docFormulaType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docFormulaType + + +class docIndexEntryType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, primaryie=None, secondaryie=None): + self.primaryie = primaryie + self.secondaryie = secondaryie + def factory(*args_, **kwargs_): + if docIndexEntryType.subclass: + return docIndexEntryType.subclass(*args_, **kwargs_) + else: + return docIndexEntryType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_primaryie(self): return self.primaryie + def set_primaryie(self, primaryie): self.primaryie = primaryie + def get_secondaryie(self): return self.secondaryie + def set_secondaryie(self, secondaryie): self.secondaryie = secondaryie + def export(self, outfile, level, namespace_='', name_='docIndexEntryType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docIndexEntryType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docIndexEntryType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docIndexEntryType'): + if self.primaryie is not None: + showIndent(outfile, level) + outfile.write('<%sprimaryie>%s\n' % (namespace_, self.format_string(quote_xml(self.primaryie).encode(ExternalEncoding), input_name='primaryie'), namespace_)) + if self.secondaryie is not None: + showIndent(outfile, level) + outfile.write('<%ssecondaryie>%s\n' % (namespace_, self.format_string(quote_xml(self.secondaryie).encode(ExternalEncoding), input_name='secondaryie'), namespace_)) + def hasContent_(self): + if ( + self.primaryie is not None or + self.secondaryie is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'primaryie': + primaryie_ = '' + for text__content_ in child_.childNodes: + primaryie_ += text__content_.nodeValue + self.primaryie = primaryie_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'secondaryie': + secondaryie_ = '' + for text__content_ in child_.childNodes: + secondaryie_ += text__content_.nodeValue + self.secondaryie = secondaryie_ +# end class docIndexEntryType + + +class docListType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, listitem=None): + if listitem is None: + self.listitem = [] + else: + self.listitem = listitem + def factory(*args_, **kwargs_): + if docListType.subclass: + return docListType.subclass(*args_, **kwargs_) + else: + return docListType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_listitem(self): return self.listitem + def set_listitem(self, listitem): self.listitem = listitem + def add_listitem(self, value): self.listitem.append(value) + def insert_listitem(self, index, value): self.listitem[index] = value + def export(self, outfile, level, namespace_='', name_='docListType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docListType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docListType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docListType'): + for listitem_ in self.listitem: + listitem_.export(outfile, level, namespace_, name_='listitem') + def hasContent_(self): + if ( + self.listitem is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'listitem': + obj_ = docListItemType.factory() + obj_.build(child_) + self.listitem.append(obj_) +# end class docListType + + +class docListItemType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None): + if para is None: + self.para = [] + else: + self.para = para + def factory(*args_, **kwargs_): + if docListItemType.subclass: + return docListItemType.subclass(*args_, **kwargs_) + else: + return docListItemType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def export(self, outfile, level, namespace_='', name_='docListItemType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docListItemType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docListItemType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docListItemType'): + for para_ in self.para: + para_.export(outfile, level, namespace_, name_='para') + def hasContent_(self): + if ( + self.para is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = docParaType.factory() + obj_.build(child_) + self.para.append(obj_) +# end class docListItemType + + +class docSimpleSectType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, title=None, para=None): + self.kind = kind + self.title = title + if para is None: + self.para = [] + else: + self.para = para + def factory(*args_, **kwargs_): + if docSimpleSectType.subclass: + return docSimpleSectType.subclass(*args_, **kwargs_) + else: + return docSimpleSectType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def export(self, outfile, level, namespace_='', name_='docSimpleSectType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docSimpleSectType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docSimpleSectType'): + if self.kind is not None: + outfile.write(' kind=%s' % (quote_attrib(self.kind), )) + def exportChildren(self, outfile, level, namespace_='', name_='docSimpleSectType'): + if self.title: + self.title.export(outfile, level, namespace_, name_='title') + for para_ in self.para: + para_.export(outfile, level, namespace_, name_='para') + def hasContent_(self): + if ( + self.title is not None or + self.para is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + obj_ = docTitleType.factory() + obj_.build(child_) + self.set_title(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = docParaType.factory() + obj_.build(child_) + self.para.append(obj_) +# end class docSimpleSectType + + +class docVarListEntryType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, term=None): + self.term = term + def factory(*args_, **kwargs_): + if docVarListEntryType.subclass: + return docVarListEntryType.subclass(*args_, **kwargs_) + else: + return docVarListEntryType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_term(self): return self.term + def set_term(self, term): self.term = term + def export(self, outfile, level, namespace_='', name_='docVarListEntryType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docVarListEntryType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docVarListEntryType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docVarListEntryType'): + if self.term: + self.term.export(outfile, level, namespace_, name_='term', ) + def hasContent_(self): + if ( + self.term is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'term': + obj_ = docTitleType.factory() + obj_.build(child_) + self.set_term(obj_) +# end class docVarListEntryType + + +class docVariableListType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if docVariableListType.subclass: + return docVariableListType.subclass(*args_, **kwargs_) + else: + return docVariableListType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docVariableListType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docVariableListType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docVariableListType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docVariableListType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docVariableListType + + +class docRefTextType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, refid=None, kindref=None, external=None, valueOf_='', mixedclass_=None, content_=None): + self.refid = refid + self.kindref = kindref + self.external = external + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docRefTextType.subclass: + return docRefTextType.subclass(*args_, **kwargs_) + else: + return docRefTextType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def get_kindref(self): return self.kindref + def set_kindref(self, kindref): self.kindref = kindref + def get_external(self): return self.external + def set_external(self, external): self.external = external + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docRefTextType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docRefTextType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docRefTextType'): + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + if self.kindref is not None: + outfile.write(' kindref=%s' % (quote_attrib(self.kindref), )) + if self.external is not None: + outfile.write(' external=%s' % (self.format_string(quote_attrib(self.external).encode(ExternalEncoding), input_name='external'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docRefTextType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('refid'): + self.refid = attrs.get('refid').value + if attrs.get('kindref'): + self.kindref = attrs.get('kindref').value + if attrs.get('external'): + self.external = attrs.get('external').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docRefTextType + + +class docTableType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, rows=None, cols=None, row=None, caption=None): + self.rows = rows + self.cols = cols + if row is None: + self.row = [] + else: + self.row = row + self.caption = caption + def factory(*args_, **kwargs_): + if docTableType.subclass: + return docTableType.subclass(*args_, **kwargs_) + else: + return docTableType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_row(self): return self.row + def set_row(self, row): self.row = row + def add_row(self, value): self.row.append(value) + def insert_row(self, index, value): self.row[index] = value + def get_caption(self): return self.caption + def set_caption(self, caption): self.caption = caption + def get_rows(self): return self.rows + def set_rows(self, rows): self.rows = rows + def get_cols(self): return self.cols + def set_cols(self, cols): self.cols = cols + def export(self, outfile, level, namespace_='', name_='docTableType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docTableType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docTableType'): + if self.rows is not None: + outfile.write(' rows="%s"' % self.format_integer(self.rows, input_name='rows')) + if self.cols is not None: + outfile.write(' cols="%s"' % self.format_integer(self.cols, input_name='cols')) + def exportChildren(self, outfile, level, namespace_='', name_='docTableType'): + for row_ in self.row: + row_.export(outfile, level, namespace_, name_='row') + if self.caption: + self.caption.export(outfile, level, namespace_, name_='caption') + def hasContent_(self): + if ( + self.row is not None or + self.caption is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('rows'): + try: + self.rows = int(attrs.get('rows').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (rows): %s' % exp) + if attrs.get('cols'): + try: + self.cols = int(attrs.get('cols').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (cols): %s' % exp) + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'row': + obj_ = docRowType.factory() + obj_.build(child_) + self.row.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'caption': + obj_ = docCaptionType.factory() + obj_.build(child_) + self.set_caption(obj_) +# end class docTableType + + +class docRowType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, entry=None): + if entry is None: + self.entry = [] + else: + self.entry = entry + def factory(*args_, **kwargs_): + if docRowType.subclass: + return docRowType.subclass(*args_, **kwargs_) + else: + return docRowType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_entry(self): return self.entry + def set_entry(self, entry): self.entry = entry + def add_entry(self, value): self.entry.append(value) + def insert_entry(self, index, value): self.entry[index] = value + def export(self, outfile, level, namespace_='', name_='docRowType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docRowType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docRowType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docRowType'): + for entry_ in self.entry: + entry_.export(outfile, level, namespace_, name_='entry') + def hasContent_(self): + if ( + self.entry is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'entry': + obj_ = docEntryType.factory() + obj_.build(child_) + self.entry.append(obj_) +# end class docRowType + + +class docEntryType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, thead=None, para=None): + self.thead = thead + if para is None: + self.para = [] + else: + self.para = para + def factory(*args_, **kwargs_): + if docEntryType.subclass: + return docEntryType.subclass(*args_, **kwargs_) + else: + return docEntryType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_thead(self): return self.thead + def set_thead(self, thead): self.thead = thead + def export(self, outfile, level, namespace_='', name_='docEntryType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docEntryType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docEntryType'): + if self.thead is not None: + outfile.write(' thead=%s' % (quote_attrib(self.thead), )) + def exportChildren(self, outfile, level, namespace_='', name_='docEntryType'): + for para_ in self.para: + para_.export(outfile, level, namespace_, name_='para') + def hasContent_(self): + if ( + self.para is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('thead'): + self.thead = attrs.get('thead').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = docParaType.factory() + obj_.build(child_) + self.para.append(obj_) +# end class docEntryType + + +class docCaptionType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docCaptionType.subclass: + return docCaptionType.subclass(*args_, **kwargs_) + else: + return docCaptionType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docCaptionType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docCaptionType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docCaptionType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docCaptionType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docCaptionType + + +class docHeadingType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, level=None, valueOf_='', mixedclass_=None, content_=None): + self.level = level + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docHeadingType.subclass: + return docHeadingType.subclass(*args_, **kwargs_) + else: + return docHeadingType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_level(self): return self.level + def set_level(self, level): self.level = level + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docHeadingType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docHeadingType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docHeadingType'): + if self.level is not None: + outfile.write(' level="%s"' % self.format_integer(self.level, input_name='level')) + def exportChildren(self, outfile, level, namespace_='', name_='docHeadingType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('level'): + try: + self.level = int(attrs.get('level').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (level): %s' % exp) + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docHeadingType + + +class docImageType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, width=None, type_=None, name=None, height=None, valueOf_='', mixedclass_=None, content_=None): + self.width = width + self.type_ = type_ + self.name = name + self.height = height + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docImageType.subclass: + return docImageType.subclass(*args_, **kwargs_) + else: + return docImageType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_width(self): return self.width + def set_width(self, width): self.width = width + def get_type(self): return self.type_ + def set_type(self, type_): self.type_ = type_ + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_height(self): return self.height + def set_height(self, height): self.height = height + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docImageType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docImageType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docImageType'): + if self.width is not None: + outfile.write(' width=%s' % (self.format_string(quote_attrib(self.width).encode(ExternalEncoding), input_name='width'), )) + if self.type_ is not None: + outfile.write(' type=%s' % (quote_attrib(self.type_), )) + if self.name is not None: + outfile.write(' name=%s' % (self.format_string(quote_attrib(self.name).encode(ExternalEncoding), input_name='name'), )) + if self.height is not None: + outfile.write(' height=%s' % (self.format_string(quote_attrib(self.height).encode(ExternalEncoding), input_name='height'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docImageType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('width'): + self.width = attrs.get('width').value + if attrs.get('type'): + self.type_ = attrs.get('type').value + if attrs.get('name'): + self.name = attrs.get('name').value + if attrs.get('height'): + self.height = attrs.get('height').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docImageType + + +class docDotFileType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, name=None, valueOf_='', mixedclass_=None, content_=None): + self.name = name + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docDotFileType.subclass: + return docDotFileType.subclass(*args_, **kwargs_) + else: + return docDotFileType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_name(self): return self.name + def set_name(self, name): self.name = name + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docDotFileType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docDotFileType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docDotFileType'): + if self.name is not None: + outfile.write(' name=%s' % (self.format_string(quote_attrib(self.name).encode(ExternalEncoding), input_name='name'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docDotFileType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('name'): + self.name = attrs.get('name').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docDotFileType + + +class docTocItemType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docTocItemType.subclass: + return docTocItemType.subclass(*args_, **kwargs_) + else: + return docTocItemType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_id(self): return self.id + def set_id(self, id): self.id = id + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docTocItemType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docTocItemType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docTocItemType'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docTocItemType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docTocItemType + + +class docTocListType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, tocitem=None): + if tocitem is None: + self.tocitem = [] + else: + self.tocitem = tocitem + def factory(*args_, **kwargs_): + if docTocListType.subclass: + return docTocListType.subclass(*args_, **kwargs_) + else: + return docTocListType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_tocitem(self): return self.tocitem + def set_tocitem(self, tocitem): self.tocitem = tocitem + def add_tocitem(self, value): self.tocitem.append(value) + def insert_tocitem(self, index, value): self.tocitem[index] = value + def export(self, outfile, level, namespace_='', name_='docTocListType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docTocListType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docTocListType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docTocListType'): + for tocitem_ in self.tocitem: + tocitem_.export(outfile, level, namespace_, name_='tocitem') + def hasContent_(self): + if ( + self.tocitem is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'tocitem': + obj_ = docTocItemType.factory() + obj_.build(child_) + self.tocitem.append(obj_) +# end class docTocListType + + +class docLanguageType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, langid=None, para=None): + self.langid = langid + if para is None: + self.para = [] + else: + self.para = para + def factory(*args_, **kwargs_): + if docLanguageType.subclass: + return docLanguageType.subclass(*args_, **kwargs_) + else: + return docLanguageType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_langid(self): return self.langid + def set_langid(self, langid): self.langid = langid + def export(self, outfile, level, namespace_='', name_='docLanguageType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docLanguageType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docLanguageType'): + if self.langid is not None: + outfile.write(' langid=%s' % (self.format_string(quote_attrib(self.langid).encode(ExternalEncoding), input_name='langid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docLanguageType'): + for para_ in self.para: + para_.export(outfile, level, namespace_, name_='para') + def hasContent_(self): + if ( + self.para is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('langid'): + self.langid = attrs.get('langid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = docParaType.factory() + obj_.build(child_) + self.para.append(obj_) +# end class docLanguageType + + +class docParamListType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, parameteritem=None): + self.kind = kind + if parameteritem is None: + self.parameteritem = [] + else: + self.parameteritem = parameteritem + def factory(*args_, **kwargs_): + if docParamListType.subclass: + return docParamListType.subclass(*args_, **kwargs_) + else: + return docParamListType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_parameteritem(self): return self.parameteritem + def set_parameteritem(self, parameteritem): self.parameteritem = parameteritem + def add_parameteritem(self, value): self.parameteritem.append(value) + def insert_parameteritem(self, index, value): self.parameteritem[index] = value + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def export(self, outfile, level, namespace_='', name_='docParamListType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docParamListType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docParamListType'): + if self.kind is not None: + outfile.write(' kind=%s' % (quote_attrib(self.kind), )) + def exportChildren(self, outfile, level, namespace_='', name_='docParamListType'): + for parameteritem_ in self.parameteritem: + parameteritem_.export(outfile, level, namespace_, name_='parameteritem') + def hasContent_(self): + if ( + self.parameteritem is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'parameteritem': + obj_ = docParamListItem.factory() + obj_.build(child_) + self.parameteritem.append(obj_) +# end class docParamListType + + +class docParamListItem(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, parameternamelist=None, parameterdescription=None): + if parameternamelist is None: + self.parameternamelist = [] + else: + self.parameternamelist = parameternamelist + self.parameterdescription = parameterdescription + def factory(*args_, **kwargs_): + if docParamListItem.subclass: + return docParamListItem.subclass(*args_, **kwargs_) + else: + return docParamListItem(*args_, **kwargs_) + factory = staticmethod(factory) + def get_parameternamelist(self): return self.parameternamelist + def set_parameternamelist(self, parameternamelist): self.parameternamelist = parameternamelist + def add_parameternamelist(self, value): self.parameternamelist.append(value) + def insert_parameternamelist(self, index, value): self.parameternamelist[index] = value + def get_parameterdescription(self): return self.parameterdescription + def set_parameterdescription(self, parameterdescription): self.parameterdescription = parameterdescription + def export(self, outfile, level, namespace_='', name_='docParamListItem', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docParamListItem') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docParamListItem'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docParamListItem'): + for parameternamelist_ in self.parameternamelist: + parameternamelist_.export(outfile, level, namespace_, name_='parameternamelist') + if self.parameterdescription: + self.parameterdescription.export(outfile, level, namespace_, name_='parameterdescription', ) + def hasContent_(self): + if ( + self.parameternamelist is not None or + self.parameterdescription is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'parameternamelist': + obj_ = docParamNameList.factory() + obj_.build(child_) + self.parameternamelist.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'parameterdescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_parameterdescription(obj_) +# end class docParamListItem + + +class docParamNameList(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, parametername=None): + if parametername is None: + self.parametername = [] + else: + self.parametername = parametername + def factory(*args_, **kwargs_): + if docParamNameList.subclass: + return docParamNameList.subclass(*args_, **kwargs_) + else: + return docParamNameList(*args_, **kwargs_) + factory = staticmethod(factory) + def get_parametername(self): return self.parametername + def set_parametername(self, parametername): self.parametername = parametername + def add_parametername(self, value): self.parametername.append(value) + def insert_parametername(self, index, value): self.parametername[index] = value + def export(self, outfile, level, namespace_='', name_='docParamNameList', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docParamNameList') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docParamNameList'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docParamNameList'): + for parametername_ in self.parametername: + parametername_.export(outfile, level, namespace_, name_='parametername') + def hasContent_(self): + if ( + self.parametername is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'parametername': + obj_ = docParamName.factory() + obj_.build(child_) + self.parametername.append(obj_) +# end class docParamNameList + + +class docParamName(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, direction=None, ref=None, mixedclass_=None, content_=None): + self.direction = direction + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docParamName.subclass: + return docParamName.subclass(*args_, **kwargs_) + else: + return docParamName(*args_, **kwargs_) + factory = staticmethod(factory) + def get_ref(self): return self.ref + def set_ref(self, ref): self.ref = ref + def get_direction(self): return self.direction + def set_direction(self, direction): self.direction = direction + def export(self, outfile, level, namespace_='', name_='docParamName', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docParamName') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docParamName'): + if self.direction is not None: + outfile.write(' direction=%s' % (quote_attrib(self.direction), )) + def exportChildren(self, outfile, level, namespace_='', name_='docParamName'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.ref is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('direction'): + self.direction = attrs.get('direction').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'ref': + childobj_ = docRefTextType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'ref', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docParamName + + +class docXRefSectType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, xreftitle=None, xrefdescription=None): + self.id = id + if xreftitle is None: + self.xreftitle = [] + else: + self.xreftitle = xreftitle + self.xrefdescription = xrefdescription + def factory(*args_, **kwargs_): + if docXRefSectType.subclass: + return docXRefSectType.subclass(*args_, **kwargs_) + else: + return docXRefSectType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_xreftitle(self): return self.xreftitle + def set_xreftitle(self, xreftitle): self.xreftitle = xreftitle + def add_xreftitle(self, value): self.xreftitle.append(value) + def insert_xreftitle(self, index, value): self.xreftitle[index] = value + def get_xrefdescription(self): return self.xrefdescription + def set_xrefdescription(self, xrefdescription): self.xrefdescription = xrefdescription + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='docXRefSectType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docXRefSectType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docXRefSectType'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docXRefSectType'): + for xreftitle_ in self.xreftitle: + showIndent(outfile, level) + outfile.write('<%sxreftitle>%s\n' % (namespace_, self.format_string(quote_xml(xreftitle_).encode(ExternalEncoding), input_name='xreftitle'), namespace_)) + if self.xrefdescription: + self.xrefdescription.export(outfile, level, namespace_, name_='xrefdescription', ) + def hasContent_(self): + if ( + self.xreftitle is not None or + self.xrefdescription is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'xreftitle': + xreftitle_ = '' + for text__content_ in child_.childNodes: + xreftitle_ += text__content_.nodeValue + self.xreftitle.append(xreftitle_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'xrefdescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_xrefdescription(obj_) +# end class docXRefSectType + + +class docCopyType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, link=None, para=None, sect1=None, internal=None): + self.link = link + if para is None: + self.para = [] + else: + self.para = para + if sect1 is None: + self.sect1 = [] + else: + self.sect1 = sect1 + self.internal = internal + def factory(*args_, **kwargs_): + if docCopyType.subclass: + return docCopyType.subclass(*args_, **kwargs_) + else: + return docCopyType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect1(self): return self.sect1 + def set_sect1(self, sect1): self.sect1 = sect1 + def add_sect1(self, value): self.sect1.append(value) + def insert_sect1(self, index, value): self.sect1[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def get_link(self): return self.link + def set_link(self, link): self.link = link + def export(self, outfile, level, namespace_='', name_='docCopyType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docCopyType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docCopyType'): + if self.link is not None: + outfile.write(' link=%s' % (self.format_string(quote_attrib(self.link).encode(ExternalEncoding), input_name='link'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docCopyType'): + for para_ in self.para: + para_.export(outfile, level, namespace_, name_='para') + for sect1_ in self.sect1: + sect1_.export(outfile, level, namespace_, name_='sect1') + if self.internal: + self.internal.export(outfile, level, namespace_, name_='internal') + def hasContent_(self): + if ( + self.para is not None or + self.sect1 is not None or + self.internal is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('link'): + self.link = attrs.get('link').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = docParaType.factory() + obj_.build(child_) + self.para.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect1': + obj_ = docSect1Type.factory() + obj_.build(child_) + self.sect1.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + obj_ = docInternalType.factory() + obj_.build(child_) + self.set_internal(obj_) +# end class docCopyType + + +class docCharType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, char=None, valueOf_=''): + self.char = char + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if docCharType.subclass: + return docCharType.subclass(*args_, **kwargs_) + else: + return docCharType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_char(self): return self.char + def set_char(self, char): self.char = char + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docCharType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docCharType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docCharType'): + if self.char is not None: + outfile.write(' char=%s' % (quote_attrib(self.char), )) + def exportChildren(self, outfile, level, namespace_='', name_='docCharType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('char'): + self.char = attrs.get('char').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docCharType + + +class docEmptyType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if docEmptyType.subclass: + return docEmptyType.subclass(*args_, **kwargs_) + else: + return docEmptyType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docEmptyType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docEmptyType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docEmptyType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docEmptyType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docEmptyType + + +USAGE_TEXT = """ +Usage: python .py [ -s ] +Options: + -s Use the SAX parser, not the minidom parser. +""" + +def usage(): + print USAGE_TEXT + sys.exit(1) + + +def parse(inFileName): + doc = minidom.parse(inFileName) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('\n') + rootObj.export(sys.stdout, 0, name_="doxygen", + namespacedef_='') + return rootObj + + +def parseString(inString): + doc = minidom.parseString(inString) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('\n') + rootObj.export(sys.stdout, 0, name_="doxygen", + namespacedef_='') + return rootObj + + +def parseLiteral(inFileName): + doc = minidom.parse(inFileName) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('from compound import *\n\n') + sys.stdout.write('rootObj = doxygen(\n') + rootObj.exportLiteral(sys.stdout, 0, name_="doxygen") + sys.stdout.write(')\n') + return rootObj + + +def main(): + args = sys.argv[1:] + if len(args) == 1: + parse(args[0]) + else: + usage() + + +if __name__ == '__main__': + main() + #import pdb + #pdb.run('main()') + diff --git a/foreignlibs/breathe/breathe/parser/doxygen/index.py b/foreignlibs/breathe/breathe/parser/doxygen/index.py new file mode 100644 index 00000000..370ba190 --- /dev/null +++ b/foreignlibs/breathe/breathe/parser/doxygen/index.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +""" +Generated Mon Feb 9 19:08:05 2009 by generateDS.py. +""" + +from xml.dom import minidom + + +import indexsuper as supermod + +class DoxygenTypeSub(supermod.DoxygenType): + + node_type = "doxygen" + + def __init__(self, version=None, compound=None): + supermod.DoxygenType.__init__(self, version, compound) +supermod.DoxygenType.subclass = DoxygenTypeSub +# end class DoxygenTypeSub + + +class CompoundTypeSub(supermod.CompoundType): + + node_type = "compound" + + def __init__(self, kind=None, refid=None, name='', member=None): + supermod.CompoundType.__init__(self, kind, refid, name, member) +supermod.CompoundType.subclass = CompoundTypeSub +# end class CompoundTypeSub + + +class MemberTypeSub(supermod.MemberType): + + node_type = "member" + + def __init__(self, kind=None, refid=None, name=''): + supermod.MemberType.__init__(self, kind, refid, name) +supermod.MemberType.subclass = MemberTypeSub +# end class MemberTypeSub + + +class ParseError(Exception): + pass + +def parse(inFilename): + + try: + doc = minidom.parse(inFilename) + except IOError, e: + raise ParseError(inFilename) + + rootNode = doc.documentElement + rootObj = supermod.DoxygenType.factory() + rootObj.build(rootNode) + + return rootObj + diff --git a/foreignlibs/breathe/breathe/parser/doxygen/indexsuper.py b/foreignlibs/breathe/breathe/parser/doxygen/indexsuper.py new file mode 100644 index 00000000..fad9380d --- /dev/null +++ b/foreignlibs/breathe/breathe/parser/doxygen/indexsuper.py @@ -0,0 +1,363 @@ +#!/usr/bin/env python + +# +# Generated Thu Jun 11 18:43:54 2009 by generateDS.py. +# + +import sys +import getopt +from string import lower as str_lower +from xml.dom import minidom +from xml.dom import Node + +# +# User methods +# +# Calls to the methods in these classes are generated by generateDS.py. +# You can replace these methods by re-implementing the following class +# in a module named generatedssuper.py. + +try: + from generatedssuper import GeneratedsSuper +except ImportError, exp: + + class GeneratedsSuper: + def format_string(self, input_data, input_name=''): + return input_data + def format_integer(self, input_data, input_name=''): + return '%d' % input_data + def format_float(self, input_data, input_name=''): + return '%f' % input_data + def format_double(self, input_data, input_name=''): + return '%e' % input_data + def format_boolean(self, input_data, input_name=''): + return '%s' % input_data + + +# +# If you have installed IPython you can uncomment and use the following. +# IPython is available from http://ipython.scipy.org/. +# + +## from IPython.Shell import IPShellEmbed +## args = '' +## ipshell = IPShellEmbed(args, +## banner = 'Dropping into IPython', +## exit_msg = 'Leaving Interpreter, back to program.') + +# Then use the following line where and when you want to drop into the +# IPython shell: +# ipshell(' -- Entering ipshell.\nHit Ctrl-D to exit') + +# +# Globals +# + +ExternalEncoding = 'ascii' + +# +# Support/utility functions. +# + +def showIndent(outfile, level): + for idx in range(level): + outfile.write(' ') + +def quote_xml(inStr): + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + return s1 + +def quote_attrib(inStr): + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + if '"' in s1: + if "'" in s1: + s1 = '"%s"' % s1.replace('"', """) + else: + s1 = "'%s'" % s1 + else: + s1 = '"%s"' % s1 + return s1 + +def quote_python(inStr): + s1 = inStr + if s1.find("'") == -1: + if s1.find('\n') == -1: + return "'%s'" % s1 + else: + return "'''%s'''" % s1 + else: + if s1.find('"') != -1: + s1 = s1.replace('"', '\\"') + if s1.find('\n') == -1: + return '"%s"' % s1 + else: + return '"""%s"""' % s1 + + +class MixedContainer: + # Constants for category: + CategoryNone = 0 + CategoryText = 1 + CategorySimple = 2 + CategoryComplex = 3 + # Constants for content_type: + TypeNone = 0 + TypeText = 1 + TypeString = 2 + TypeInteger = 3 + TypeFloat = 4 + TypeDecimal = 5 + TypeDouble = 6 + TypeBoolean = 7 + def __init__(self, category, content_type, name, value): + self.category = category + self.content_type = content_type + self.name = name + self.value = value + def getCategory(self): + return self.category + def getContenttype(self, content_type): + return self.content_type + def getValue(self): + return self.value + def getName(self): + return self.name + + +class _MemberSpec(object): + def __init__(self, name='', data_type='', container=0): + self.name = name + self.data_type = data_type + self.container = container + def set_name(self, name): self.name = name + def get_name(self): return self.name + def set_data_type(self, data_type): self.data_type = data_type + def get_data_type(self): return self.data_type + def set_container(self, container): self.container = container + def get_container(self): return self.container + + +# +# Data representation classes. +# + +class DoxygenType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, version=None, compound=None): + self.version = version + if compound is None: + self.compound = [] + else: + self.compound = compound + def factory(*args_, **kwargs_): + if DoxygenType.subclass: + return DoxygenType.subclass(*args_, **kwargs_) + else: + return DoxygenType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_compound(self): return self.compound + def set_compound(self, compound): self.compound = compound + def add_compound(self, value): self.compound.append(value) + def insert_compound(self, index, value): self.compound[index] = value + def get_version(self): return self.version + def set_version(self, version): self.version = version + def hasContent_(self): + if ( + self.compound is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('version'): + self.version = attrs.get('version').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'compound': + obj_ = CompoundType.factory() + obj_.build(child_) + self.compound.append(obj_) +# end class DoxygenType + + +class CompoundType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, refid=None, name=None, member=None): + self.kind = kind + self.refid = refid + self.name = name + if member is None: + self.member = [] + else: + self.member = member + def factory(*args_, **kwargs_): + if CompoundType.subclass: + return CompoundType.subclass(*args_, **kwargs_) + else: + return CompoundType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_member(self): return self.member + def set_member(self, member): self.member = member + def add_member(self, value): self.member.append(value) + def insert_member(self, index, value): self.member[index] = value + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + name_ = '' + for text__content_ in child_.childNodes: + name_ += text__content_.nodeValue + self.name = name_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'member': + obj_ = MemberType.factory() + obj_.build(child_) + self.member.append(obj_) +# end class CompoundType + + +class MemberType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, refid=None, name=None): + self.kind = kind + self.refid = refid + self.name = name + def factory(*args_, **kwargs_): + if MemberType.subclass: + return MemberType.subclass(*args_, **kwargs_) + else: + return MemberType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def hasContent_(self): + if ( + self.name is not None + ): + return True + else: + return False + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + name_ = '' + for text__content_ in child_.childNodes: + name_ += text__content_.nodeValue + self.name = name_ +# end class MemberType + + +USAGE_TEXT = """ +Usage: python .py [ -s ] +Options: + -s Use the SAX parser, not the minidom parser. +""" + +def usage(): + print USAGE_TEXT + sys.exit(1) + + +def parse(inFileName): + doc = minidom.parse(inFileName) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('\n') + rootObj.export(sys.stdout, 0, name_="doxygenindex", + namespacedef_='') + return rootObj + + +def parseString(inString): + doc = minidom.parseString(inString) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('\n') + rootObj.export(sys.stdout, 0, name_="doxygenindex", + namespacedef_='') + return rootObj + + +def parseLiteral(inFileName): + doc = minidom.parse(inFileName) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('from index import *\n\n') + sys.stdout.write('rootObj = doxygenindex(\n') + rootObj.exportLiteral(sys.stdout, 0, name_="doxygenindex") + sys.stdout.write(')\n') + return rootObj + + +def main(): + args = sys.argv[1:] + if len(args) == 1: + parse(args[0]) + else: + usage() + + + + +if __name__ == '__main__': + main() + #import pdb + #pdb.run('main()') + diff --git a/foreignlibs/breathe/breathe/renderer/__init__.py b/foreignlibs/breathe/breathe/renderer/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/foreignlibs/breathe/breathe/renderer/rst/__init__.py b/foreignlibs/breathe/breathe/renderer/rst/__init__.py new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/foreignlibs/breathe/breathe/renderer/rst/__init__.py @@ -0,0 +1,2 @@ + + diff --git a/foreignlibs/breathe/breathe/renderer/rst/doxygen/__init__.py b/foreignlibs/breathe/breathe/renderer/rst/doxygen/__init__.py new file mode 100644 index 00000000..237a6ff9 --- /dev/null +++ b/foreignlibs/breathe/breathe/renderer/rst/doxygen/__init__.py @@ -0,0 +1,406 @@ + +from breathe.renderer.rst.doxygen.base import Renderer +from breathe.renderer.rst.doxygen import index as indexrenderer +from breathe.renderer.rst.doxygen import compound as compoundrenderer + +from breathe.parser.doxygen import index, compound, compoundsuper + +class RstContentCreator(object): + + def __init__(self, list_type, dedent): + + self.list_type = list_type + self.dedent = dedent + + def __call__(self, text): + + # Remove the first line + text = "\n".join(text.split(u"\n")[1:]) + + # Remove starting whitespace + text = self.dedent(text) + + # Inspired by autodoc.py in Sphinx + result = self.list_type() + for line in text.split("\n"): + result.append(line, "") + + return result + +class UnicodeRenderer(Renderer): + + def render(self): + + # Skip any nodes that are pure whitespace + # Probably need a better way to do this as currently we're only doing + # it skip whitespace between higher-level nodes, but this will also + # skip any pure whitespace entries in actual content nodes + # + # We counter that second issue slightly by allowing through single white spaces + # + if self.data_object.strip(): + return [self.node_factory.Text(self.data_object)] + elif self.data_object == unicode(" "): + return [self.node_factory.Text(self.data_object)] + else: + return [] + +class NullRenderer(Renderer): + + def __init__(self): + pass + + def render(self): + return [] + +class DoxygenToRstRendererFactory(object): + + def __init__( + self, + node_type, + type_, + renderers, + renderer_factory_creator, + node_factory, + project_info, + state, + document, + domain_handler_factory, + domain_handler, + rst_content_creator, + filter_, + target_handler + ): + + self.node_type = node_type + self.type_ = type_ + self.node_factory = node_factory + self.project_info = project_info + self.renderers = renderers + self.renderer_factory_creator = renderer_factory_creator + self.state = state + self.document = document + self.domain_handler_factory = domain_handler_factory + self.domain_handler = domain_handler + self.rst_content_creator = rst_content_creator + self.filter_ = filter_ + self.target_handler = target_handler + + def create_renderer( + self, + parent_data_object, + data_object + ): + + if not self.filter_.allow(parent_data_object, data_object): + return NullRenderer() + + child_renderer_factory = self.renderer_factory_creator.create_child_factory( + self.project_info, + data_object, + self + ) + + try: + node_type = data_object.node_type + except AttributeError, e: + + # Horrible hack to silence errors on filtering unicode objects + # until we fix the parsing + if type(data_object) == unicode: + node_type = "unicode" + else: + raise e + + Renderer = self.renderers[node_type] + + common_args = [ + self.project_info, + data_object, + child_renderer_factory, + self.node_factory, + self.state, + self.document, + self.domain_handler, + self.target_handler + ] + + if node_type == "docmarkup": + + creator = self.node_factory.inline + if data_object.type_ == "emphasis": + creator = self.node_factory.emphasis + elif data_object.type_ == "computeroutput": + creator = self.node_factory.literal + elif data_object.type_ == "bold": + creator = self.node_factory.strong + elif data_object.type_ == "superscript": + creator = self.node_factory.superscript + elif data_object.type_ == "subscript": + creator = self.node_factory.subscript + elif data_object.type_ == "center": + print "Warning: does not currently handle 'center' text display" + elif data_object.type_ == "small": + print "Warning: does not currently handle 'small' text display" + + return Renderer( + creator, + *common_args + ) + + if node_type == "verbatim": + + return Renderer( + self.rst_content_creator, + *common_args + ) + + if node_type == "compound": + + class_ = indexrenderer.CompoundTypeSubRenderer + + if data_object.kind == "class": + class_ = indexrenderer.ClassCompoundTypeSubRenderer + + # For compound node types Renderer is CreateCompoundTypeSubRenderer + # as defined below. This could be cleaner + return Renderer( + class_, + *common_args + ) + + if node_type == "memberdef": + + if data_object.kind == "function": + Renderer = compoundrenderer.FuncMemberDefTypeSubRenderer + elif data_object.kind == "enum": + Renderer = compoundrenderer.EnumMemberDefTypeSubRenderer + elif data_object.kind == "typedef": + Renderer = compoundrenderer.TypedefMemberDefTypeSubRenderer + elif data_object.kind == "variable": + Renderer = compoundrenderer.VariableMemberDefTypeSubRenderer + elif data_object.kind == "define": + Renderer = compoundrenderer.DefineMemberDefTypeSubRenderer + + if node_type == "param": + return Renderer( + parent_data_object.node_type != "templateparamlist", + *common_args + ) + + if node_type == "docsimplesect": + if data_object.kind == "par": + Renderer = compoundrenderer.ParDocSimpleSectTypeSubRenderer + + return Renderer( + *common_args + ) + +class CreateCompoundTypeSubRenderer(object): + + def __init__(self, parser_factory): + + self.parser_factory = parser_factory + + def __call__(self, class_, project_info, *args): + + compound_parser = self.parser_factory.create_compound_parser(project_info) + return class_(compound_parser, project_info, *args) + + +class CreateRefTypeSubRenderer(object): + + def __init__(self, parser_factory): + + self.parser_factory = parser_factory + + def __call__(self, project_info, *args): + + compound_parser = self.parser_factory.create_compound_parser(project_info) + return compoundrenderer.RefTypeSubRenderer(compound_parser, project_info, *args) + + +class DoxygenToRstRendererFactoryCreator(object): + + def __init__( + self, + node_factory, + parser_factory, + default_domain_handler, + rst_content_creator, + domain_handler_factory, + project_info + ): + + self.node_factory = node_factory + self.parser_factory = parser_factory + self.default_domain_handler = default_domain_handler + self.rst_content_creator = rst_content_creator + self.domain_handler_factory = domain_handler_factory + self.project_info = project_info + + def create_factory(self, data_object, state, document, filter_, target_handler): + + renderers = { + "doxygen" : indexrenderer.DoxygenTypeSubRenderer, + "compound" : CreateCompoundTypeSubRenderer(self.parser_factory), + "doxygendef" : compoundrenderer.DoxygenTypeSubRenderer, + "compounddef" : compoundrenderer.CompoundDefTypeSubRenderer, + "sectiondef" : compoundrenderer.SectionDefTypeSubRenderer, + "memberdef" : compoundrenderer.MemberDefTypeSubRenderer, + "enumvalue" : compoundrenderer.EnumvalueTypeSubRenderer, + "linkedtext" : compoundrenderer.LinkedTextTypeSubRenderer, + "description" : compoundrenderer.DescriptionTypeSubRenderer, + "param" : compoundrenderer.ParamTypeSubRenderer, + "docreftext" : compoundrenderer.DocRefTextTypeSubRenderer, + "docpara" : compoundrenderer.DocParaTypeSubRenderer, + "docmarkup" : compoundrenderer.DocMarkupTypeSubRenderer, + "docparamlist" : compoundrenderer.DocParamListTypeSubRenderer, + "docparamlistitem" : compoundrenderer.DocParamListItemSubRenderer, + "docparamnamelist" : compoundrenderer.DocParamNameListSubRenderer, + "docparamname" : compoundrenderer.DocParamNameSubRenderer, + "docsect1" : compoundrenderer.DocSect1TypeSubRenderer, + "docsimplesect" : compoundrenderer.DocSimpleSectTypeSubRenderer, + "doctitle" : compoundrenderer.DocTitleTypeSubRenderer, + "templateparamlist" : compoundrenderer.TemplateParamListRenderer, + "inc" : compoundrenderer.IncTypeSubRenderer, + "ref" : CreateRefTypeSubRenderer(self.parser_factory), + "verbatim" : compoundrenderer.VerbatimTypeSubRenderer, + "mixedcontainer" : compoundrenderer.MixedContainerRenderer, + "unicode" : UnicodeRenderer, + } + + try: + node_type = data_object.node_type + except AttributeError, e: + + # Horrible hack to silence errors on filtering unicode objects + # until we fix the parsing + if type(data_object) == unicode: + node_type = "unicode" + else: + raise e + + success, domain_handler, type_ = self.get_domain(data_object, self.default_domain_handler) + + if not success and node_type == "compound": + + compound_parser = self.parser_factory.create_compound_parser(self.project_info) + file_data = compound_parser.parse(data_object.refid) + + success, domain_handler, type_ = self.get_domain( + file_data.compounddef, + domain_handler + ) + + return DoxygenToRstRendererFactory( + "root", + type_, + renderers, + self, + self.node_factory, + self.project_info, + state, + document, + self.domain_handler_factory, + domain_handler, + self.rst_content_creator, + filter_, + target_handler + ) + + def create_child_factory( self, project_info, data_object, parent_renderer_factory ): + + domain_handler = parent_renderer_factory.domain_handler + + try: + node_type = data_object.node_type + except AttributeError, e: + + # Horrible hack to silence errors on filtering unicode objects + # until we fix the parsing + if type(data_object) == unicode: + node_type = "unicode" + else: + raise e + + if parent_renderer_factory.type_ == "basic": + + success, domain_handler, type_ = self.get_domain(data_object, domain_handler) + + if not success and node_type == "compound": + + compound_parser = self.parser_factory.create_compound_parser(project_info) + file_data = compound_parser.parse(data_object.refid) + + success, domain_handler, type_ = self.get_domain( + file_data.compounddef, + domain_handler + ) + + else: + type_ = "domain" + + return DoxygenToRstRendererFactory( + node_type, + type_, + parent_renderer_factory.renderers, + self, + self.node_factory, + parent_renderer_factory.project_info, + parent_renderer_factory.state, + parent_renderer_factory.document, + parent_renderer_factory.domain_handler_factory, + domain_handler, + self.rst_content_creator, + parent_renderer_factory.filter_, + parent_renderer_factory.target_handler + ) + + + def get_domain(self, data_object, default_domain_handler): + + try: + location = data_object.location.file + except AttributeError: + return False, default_domain_handler, "basic" + + return True, self.domain_handler_factory.create_domain_handler( location ), "domain" + + +# FactoryFactoryFactory. Ridiculous but necessary. +class DoxygenToRstRendererFactoryCreatorConstructor(object): + + def __init__( + self, + node_factory, + parser_factory, + default_domain_handler, + domain_handler_factory_creator, + rst_content_creator + ): + + self.node_factory = node_factory + self.parser_factory = parser_factory + self.default_domain_handler = default_domain_handler + self.domain_handler_factory_creator = domain_handler_factory_creator + self.rst_content_creator = rst_content_creator + + def create_factory_creator(self, project_info, document, options): + + domain_handler_factory = self.domain_handler_factory_creator.create_domain_handler_factory( + project_info, + document, + document.settings.env, + options, + ) + + return DoxygenToRstRendererFactoryCreator( + self.node_factory, + self.parser_factory, + self.default_domain_handler, + self.rst_content_creator, + domain_handler_factory, + project_info, + ) + diff --git a/foreignlibs/breathe/breathe/renderer/rst/doxygen/base.py b/foreignlibs/breathe/breathe/renderer/rst/doxygen/base.py new file mode 100644 index 00000000..6858d083 --- /dev/null +++ b/foreignlibs/breathe/breathe/renderer/rst/doxygen/base.py @@ -0,0 +1,24 @@ + +class Renderer(object): + + def __init__(self, + project_info, + data_object, + renderer_factory, + node_factory, + state, + document, + domain_handler, + target_handler + ): + + self.project_info = project_info + self.data_object = data_object + self.renderer_factory = renderer_factory + self.node_factory = node_factory + self.state = state + self.document = document + self.domain_handler = domain_handler + self.target_handler = target_handler + + diff --git a/foreignlibs/breathe/breathe/renderer/rst/doxygen/compound.py b/foreignlibs/breathe/breathe/renderer/rst/doxygen/compound.py new file mode 100644 index 00000000..724ca05d --- /dev/null +++ b/foreignlibs/breathe/breathe/renderer/rst/doxygen/compound.py @@ -0,0 +1,778 @@ + +from breathe.renderer.rst.doxygen.base import Renderer + +class DoxygenTypeSubRenderer(Renderer): + + def render(self): + + compound_renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.compounddef) + nodelist = compound_renderer.render() + + return [self.node_factory.block_quote("", *nodelist)] + + + +class CompoundDefTypeSubRenderer(Renderer): + + section_titles = [ + "user-defined", + "public-type", + "public-func", + "public-attrib", + "public-slot", + "signal", + "dcop-func", + "property", + "event", + "public-static-func", + "public-static-attrib", + "protected-type", + "protected-func", + "protected-attrib", + "protected-slot", + "protected-static-func", + "protected-static-attrib", + "package-type", + "package-attrib", + "package-static-func", + "package-static-attrib", + "private-type", + "private-func", + "private-attrib", + "private-slot", + "private-static-func", + "private-static-attrib", + "friend", + "related", + "define", + "prototype", + "typedef", + "enum", + "func", + "var" + ] + + def render(self): + + nodelist = [] + + if self.data_object.briefdescription: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.briefdescription) + nodelist.append(self.node_factory.paragraph("", "", *renderer.render())) + + if self.data_object.detaileddescription: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.detaileddescription) + nodelist.append(self.node_factory.paragraph("", "", *renderer.render())) + + section_nodelists = {} + + # Get all sub sections + for sectiondef in self.data_object.sectiondef: + kind = sectiondef.kind + renderer = self.renderer_factory.create_renderer(self.data_object, sectiondef) + subnodes = renderer.render() + try: + # As "user-defined" can repeat + section_nodelists[kind] += subnodes + except KeyError: + section_nodelists[kind] = subnodes + + # Order the results in an appropriate manner + for kind in self.section_titles: + nodelist.extend(section_nodelists.get(kind, [])) + + # Take care of innerclasses + for innerclass in self.data_object.innerclass: + renderer = self.renderer_factory.create_renderer(self.data_object, innerclass) + class_nodes = renderer.render() + if class_nodes: + nodelist.append(self.node_factory.paragraph("", "", *class_nodes)) + + for innernamespace in self.data_object.innernamespace: + renderer = self.renderer_factory.create_renderer(self.data_object, innernamespace) + namespace_nodes = renderer.render() + if namespace_nodes: + nodelist.append(self.node_factory.paragraph("", "", *namespace_nodes)) + + return nodelist + + +class SectionDefTypeSubRenderer(Renderer): + + section_titles = { + "user-defined": "User Defined", + "public-type": "Public Type", + "public-func": "Public Functions", + "public-attrib": "Public Members", + "public-slot": "Public Slot", + "signal": "Signal", + "dcop-func": "DCOP Function", + "property": "Property", + "event": "Event", + "public-static-func": "Public Static Functons", + "public-static-attrib": "Public Static Attributes", + "protected-type": "Protected Types", + "protected-func": "Protected Functions", + "protected-attrib": "Protected Attributes", + "protected-slot": "Protected Slots", + "protected-static-func": "Protected Static Functions", + "protected-static-attrib": "Protected Static Attributes", + "package-type": "Package Types", + "package-attrib": "Package Attributes", + "package-static-func": "Package Static Functions", + "package-static-attrib": "Package Static Attributes", + "private-type": "Private Types", + "private-func": "Private Functions", + "private-attrib": "Private Members", + "private-slot": "Private Slots", + "private-static-func": "Private Static Functions", + "private-static-attrib": "Private Static Attributes", + "friend": "Friends", + "related": "Related", + "define": "Defines", + "prototype": "Prototypes", + "typedef": "Typedefs", + "enum": "Enums", + "func": "Functions", + "var": "Variables", + } + + def render(self): + + node_list = [] + + if self.data_object.description: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.description) + node_list.append(self.node_factory.paragraph( "", "", *renderer.render())) + + # Get all the memberdef info + for memberdef in self.data_object.memberdef: + renderer = self.renderer_factory.create_renderer(self.data_object, memberdef) + node_list.extend(renderer.render()) + + if node_list: + + text = self.section_titles[self.data_object.kind] + + # Override default name for user-defined sections. Use "Unnamed + # Group" if the user didn't name the section + # This is different to Doxygen which will track the groups and name + # them Group1, Group2, Group3, etc. + if self.data_object.kind == "user-defined": + if self.data_object.header: + text = self.data_object.header + else: + text = "Unnamed Group" + title = self.node_factory.emphasis(text=text) + return [title, self.node_factory.block_quote("", *node_list)] + + return [] + + +class MemberDefTypeSubRenderer(Renderer): + + def create_target(self, refid): + + return self.target_handler.create_target(refid) + + def create_domain_id(self): + + return "" + + def title(self): + + kind = [] + + # Variable type or function return type + if self.data_object.type_: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.type_) + kind = renderer.render() + + name = self.node_factory.strong(text=self.data_object.name) + + args = [] + args.extend(kind) + args.extend([self.node_factory.Text(" "), name]) + + return args + + + def description(self): + + description_nodes = [] + + if self.data_object.briefdescription: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.briefdescription) + description_nodes.append(self.node_factory.paragraph("", "", *renderer.render())) + + if self.data_object.detaileddescription: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.detaileddescription) + description_nodes.append(self.node_factory.paragraph( "", "", *renderer.render())) + + return description_nodes + + + def render(self): + + refid = "%s%s" % (self.project_info.name(), self.data_object.id) + + domain_id = self.create_domain_id() + + title = self.title() + target = self.create_target(refid) + target.extend(title) + term = self.node_factory.paragraph("", "", ids=[domain_id,refid], *target ) + definition = self.node_factory.paragraph("", "", *self.description()) + return [term, self.node_factory.block_quote("", definition)] + + +class FuncMemberDefTypeSubRenderer(MemberDefTypeSubRenderer): + + def create_target(self, refid): + + self.domain_handler.create_function_target(self.data_object) + + return MemberDefTypeSubRenderer.create_target(self, refid) + + + def create_domain_id(self): + + return self.domain_handler.create_function_id(self.data_object) + + + def title(self): + + lines = [] + + # Handle any template information + if self.data_object.templateparamlist: + renderer = self.renderer_factory.create_renderer( + self.data_object, + self.data_object.templateparamlist + ) + template = [ + self.node_factory.Text("template < ") + ] + template.extend(renderer.render()) + template.append(self.node_factory.Text(" >")) + + # Add blank string at the start otherwise for some reason it renders + # the emphasis tags around the kind in plain text (same below) + lines.append( + self.node_factory.line( + "", + self.node_factory.Text(""), + *template + ) + ) + + # Get the function type and name + args = MemberDefTypeSubRenderer.title(self) + + # Get the function arguments + args.append(self.node_factory.Text("(")) + for i, parameter in enumerate(self.data_object.param): + if i: args.append(self.node_factory.Text(", ")) + renderer = self.renderer_factory.create_renderer(self.data_object, parameter) + args.extend(renderer.render()) + args.append(self.node_factory.Text(")")) + + lines.append( + self.node_factory.line( + "", + self.node_factory.Text(""), + *args + ) + ) + + # Setup the line block with gathered informationo + block = self.node_factory.line_block( + "", + *lines + ) + + return [block] + + +class DefineMemberDefTypeSubRenderer(MemberDefTypeSubRenderer): + + def title(self): + + name = self.node_factory.strong(text=self.data_object.name) + return [name] + + def description(self): + + return MemberDefTypeSubRenderer.description(self) + + +class EnumMemberDefTypeSubRenderer(MemberDefTypeSubRenderer): + + def title(self): + + if self.data_object.name.startswith("@"): + # Assume anonymous enum + return [self.node_factory.strong(text="Anonymous enum")] + + name = self.node_factory.strong(text="%s enum" % self.data_object.name) + return [name] + + def description(self): + + description_nodes = MemberDefTypeSubRenderer.description(self) + + name = self.node_factory.emphasis("", self.node_factory.Text("Values:")) + title = self.node_factory.paragraph("", "", name) + description_nodes.append(title) + + enums = [] + for item in self.data_object.enumvalue: + renderer = self.renderer_factory.create_renderer(self.data_object, item) + enums.extend(renderer.render()) + + description_nodes.append(self.node_factory.bullet_list("", classes=["breatheenumvalues"], *enums)) + + return description_nodes + + +class TypedefMemberDefTypeSubRenderer(MemberDefTypeSubRenderer): + + def title(self): + + args = [self.node_factory.Text("typedef ")] + args.extend(MemberDefTypeSubRenderer.title(self)) + + if self.data_object.argsstring: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.argsstring) + args.extend(renderer.render()) + + return args + + +class VariableMemberDefTypeSubRenderer(MemberDefTypeSubRenderer): + + def title(self): + + args = MemberDefTypeSubRenderer.title(self) + + if self.data_object.argsstring: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.argsstring) + args.extend(renderer.render()) + + return args + + +class EnumvalueTypeSubRenderer(Renderer): + + def render(self): + + name = self.node_factory.literal(text=self.data_object.name) + description_nodes = [name] + + if self.data_object.initializer: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.initializer) + nodelist = [self.node_factory.Text(" = ")] + nodelist.extend(renderer.render()) + description_nodes.append(self.node_factory.literal("", "", *nodelist)) + + separator = self.node_factory.Text(" - ") + description_nodes.append(separator) + + if self.data_object.briefdescription: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.briefdescription) + description_nodes.extend(renderer.render()) + + if self.data_object.detaileddescription: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.detaileddescription) + description_nodes.extend(renderer.render()) + + # Build the list item + return [self.node_factory.list_item("", *description_nodes)] + +class DescriptionTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + + # Get description in rst_nodes if possible + for item in self.data_object.content_: + renderer = self.renderer_factory.create_renderer(self.data_object, item) + nodelist.extend(renderer.render()) + + return nodelist + + +class LinkedTextTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + + # Recursively process where possible + for i, entry in enumerate(self.data_object.content_): + if i: + nodelist.append(self.node_factory.Text(" ")) + renderer = self.renderer_factory.create_renderer(self.data_object, entry) + nodelist.extend(renderer.render()) + + return nodelist + + +class ParamTypeSubRenderer(Renderer): + + def __init__( + self, + output_defname, + *args + ): + + Renderer.__init__( self, *args ) + + self.output_defname = output_defname + + def render(self): + + nodelist = [] + + # Parameter type + if self.data_object.type_: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.type_) + nodelist.extend(renderer.render()) + + # Parameter name + if self.data_object.declname: + nodelist.append(self.node_factory.Text(" ")) + nodelist.append(self.node_factory.Text(self.data_object.declname)) + + if self.output_defname and self.data_object.defname: + nodelist.append(self.node_factory.Text(" ")) + nodelist.append(self.node_factory.Text(self.data_object.defname)) + + # Default value + if self.data_object.defval: + nodelist.append(self.node_factory.Text(" = ")) + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.defval) + nodelist.extend(renderer.render()) + + return nodelist + + + +class DocRefTextTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + + for item in self.data_object.content_: + renderer = self.renderer_factory.create_renderer(self.data_object, item) + nodelist.extend(renderer.render()) + + for item in self.data_object.para: + renderer = self.renderer_factory.create_renderer(self.data_object, item) + nodelist.extend(renderer.render()) + + refid = "%s%s" % (self.project_info.name(), self.data_object.refid) + nodelist = [ + self.node_factory.pending_xref( + "", + reftype="ref", + refdomain="std", + refexplicit=True, + refid=refid, + reftarget=refid, + *nodelist + ) + ] + + return nodelist + + +class DocParaTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + for item in self.data_object.content: # Description + renderer = self.renderer_factory.create_renderer(self.data_object, item) + nodelist.extend(renderer.render()) + + field_nodes = [] + for entry in self.data_object.parameterlist: # Parameters/Exceptions + renderer = self.renderer_factory.create_renderer(self.data_object, entry) + field_nodes.extend(renderer.render()) + + for item in self.data_object.simplesects: # Returns + renderer = self.renderer_factory.create_renderer(self.data_object, item) + field_nodes.extend(renderer.render()) + + if field_nodes: + field_list = self.node_factory.field_list("", *field_nodes) + nodelist.append(field_list) + + return [self.node_factory.paragraph("", "", *nodelist)] + + +class DocMarkupTypeSubRenderer(Renderer): + + def __init__( + self, + creator, + *args + ): + + Renderer.__init__( self, *args ) + + self.creator = creator + + def render(self): + + nodelist = [] + + for item in self.data_object.content_: + renderer = self.renderer_factory.create_renderer(self.data_object, item) + nodelist.extend(renderer.render()) + + return [self.creator("", "", *nodelist)] + + +class DocParamListTypeSubRenderer(Renderer): + """ Parameter/Exectpion documentation """ + + lookup = { + "param" : "Parameters", + "exception" : "Exceptions", + "templateparam" : "Templates", + "retval" : "Return Value", + } + + def render(self): + + nodelist = [] + for entry in self.data_object.parameteritem: + renderer = self.renderer_factory.create_renderer(self.data_object, entry) + nodelist.extend(renderer.render()) + + # Fild list entry + nodelist_list = self.node_factory.bullet_list("", classes=["breatheparameterlist"], *nodelist) + + field_name = self.lookup[self.data_object.kind] + field_name = self.node_factory.field_name("", field_name) + field_body = self.node_factory.field_body('', nodelist_list) + + return [self.node_factory.field('', field_name, field_body)] + + + +class DocParamListItemSubRenderer(Renderer): + """ Paramter Description Renderer """ + + def render(self): + + nodelist = [] + for entry in self.data_object.parameternamelist: + renderer = self.renderer_factory.create_renderer(self.data_object, entry) + nodelist.extend(renderer.render()) + + term = self.node_factory.literal("","", *nodelist) + + separator = self.node_factory.Text(" - ") + + nodelist = [] + + if self.data_object.parameterdescription: + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.parameterdescription) + nodelist.extend(renderer.render()) + + return [self.node_factory.list_item("", term, separator, *nodelist)] + +class DocParamNameListSubRenderer(Renderer): + """ Parameter Name Renderer """ + + def render(self): + + nodelist = [] + for entry in self.data_object.parametername: + renderer = self.renderer_factory.create_renderer(self.data_object, entry) + nodelist.extend(renderer.render()) + + return nodelist + +class DocParamNameSubRenderer(Renderer): + + def render(self): + + nodelist = [] + for item in self.data_object.content_: + renderer = self.renderer_factory.create_renderer(self.data_object, item) + nodelist.extend(renderer.render()) + + return nodelist + +class DocSect1TypeSubRenderer(Renderer): + + def render(self): + + return [] + + +class DocSimpleSectTypeSubRenderer(Renderer): + "Other Type documentation such as Warning, Note, Returns, etc" + + def title(self): + + text = self.node_factory.Text(self.data_object.kind.capitalize()) + + return [text] + + def render(self): + + nodelist = [] + for item in self.data_object.para: + renderer = self.renderer_factory.create_renderer(self.data_object, item) + nodelist.append(self.node_factory.paragraph("", "", *renderer.render())) + + field_name = self.node_factory.field_name("", *self.title()) + field_body = self.node_factory.field_body("", *nodelist) + + return [self.node_factory.field("", field_name, field_body)] + + +class ParDocSimpleSectTypeSubRenderer(DocSimpleSectTypeSubRenderer): + + def title(self): + + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.title) + + return renderer.render() + + +class DocTitleTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + + for item in self.data_object.content_: + renderer = self.renderer_factory.create_renderer(self.data_object, item) + nodelist.extend(renderer.render()) + + return nodelist + +class TemplateParamListRenderer(Renderer): + + def render(self): + + nodelist = [] + + for i, param in enumerate(self.data_object.param): + if i: + nodelist.append(self.node_factory.Text(", ")) + renderer = self.renderer_factory.create_renderer(self.data_object, param) + nodelist.extend(renderer.render()) + + return nodelist + +class IncTypeSubRenderer(Renderer): + + def render(self): + + if self.data_object.local == u"yes": + text = '#include "%s"' % self.data_object.content_[0].getValue() + else: + text = '#include <%s>' % self.data_object.content_[0].getValue() + + return [self.node_factory.emphasis(text=text)] + +class RefTypeSubRenderer(Renderer): + + ref_types = { + "innerclass" : "class", + "innernamespace" : "namespace", + } + + def __init__(self, compound_parser, *args): + Renderer.__init__(self, *args) + + self.compound_parser = compound_parser + + def render(self): + + # Read in the corresponding xml file and process + file_data = self.compound_parser.parse(self.data_object.refid) + data_renderer = self.renderer_factory.create_renderer(self.data_object, file_data) + + child_nodes = data_renderer.render() + + # Only render the header with refs if we've definitely got content to + # put underneath it. Otherwise return an empty list + if child_nodes: + + refid = "%s%s" % (self.project_info.name(), self.data_object.refid) + nodelist = self.target_handler.create_target(refid) + + # Set up the title and a reference for it (refid) + type_ = self.ref_types[self.data_object.node_name] + kind = self.node_factory.emphasis(text=type_) + + name_text = self.data_object.content_[0].getValue() + name_text = name_text.rsplit("::", 1)[-1] + name = self.node_factory.strong(text=name_text) + + nodelist = [] + + nodelist.append( + self.node_factory.paragraph( + "", + "", + kind, + self.node_factory.Text(" "), + name, + ids=[refid] + ) + ) + + nodelist.extend(child_nodes) + + return nodelist + + return [] + +class VerbatimTypeSubRenderer(Renderer): + + def __init__(self, content_creator, *args): + Renderer.__init__(self, *args) + + self.content_creator = content_creator + + def render(self): + + if not self.data_object.text.strip().startswith("embed:rst"): + + # Remove trailing new lines. Purely subjective call from viewing results + text = self.data_object.text.rstrip() + + # Handle has a preformatted text + return [self.node_factory.literal_block(text, text)] + + rst = self.content_creator(self.data_object.text) + + # Parent node for the generated node subtree + node = self.node_factory.paragraph() + node.document = self.state.document + + # Generate node subtree + self.state.nested_parse(rst, 0, node) + + return node + + +class MixedContainerRenderer(Renderer): + + def render(self): + + renderer = self.renderer_factory.create_renderer(self.data_object, self.data_object.getValue()) + return renderer.render() + + diff --git a/foreignlibs/breathe/breathe/renderer/rst/doxygen/domain.py b/foreignlibs/breathe/breathe/renderer/rst/doxygen/domain.py new file mode 100644 index 00000000..4de811b3 --- /dev/null +++ b/foreignlibs/breathe/breathe/renderer/rst/doxygen/domain.py @@ -0,0 +1,240 @@ + + +class DomainHelper(object): + pass + +class NullDomainHelper(DomainHelper): + pass + +class CppDomainHelper(DomainHelper): + + def __init__(self, definition_parser, substitute): + + self.definition_parser = definition_parser + self.substitute = substitute + + self.duplicates = {} + + def check_cache(self, _id): + try: + return True, self.duplicates[_id] + except KeyError: + return False, "" + + def cache(self, _id, project_info): + self.duplicates[_id] = project_info + + def remove_word(self, word, definition): + return self.substitute(r"(\s*\b|^)%s\b\s*" % word, "", definition) + + +class CDomainHelper(DomainHelper): + + def __init__(self): + + self.duplicates = set() + + def is_duplicate(self, name): + return name in self.duplicates + + def remember(self, name): + self.duplicates.add(name) + + + +class DomainHandler(object): + + def __init__(self, node_factory, document, env, helper, project_info): + + self.node_factory = node_factory + self.document = document + self.env = env + self.helper = helper + self.project_info = project_info + +class NullDomainHandler(DomainHandler): + + def __init__(self): + pass + + def create_function_id(self, data_object): + return "" + + def create_function_target(self, data_object): + pass + + def create_class_id(self, data_object): + return "" + + def create_class_target(self, data_object): + pass + +class CDomainHandler(DomainHandler): + + def create_function_id(self, data_object): + + name = data_object.definition.split()[-1] + + return name + + def create_function_target(self, data_object): + + name = data_object.definition.split()[-1] + + if self.helper.is_duplicate(name): + print ( "Warning: Ignoring duplicate '%s'. As C does not support overloaded " + "functions. Perhaps you should be using the cpp domain?" % name ) + return + + self.helper.remember(name) + + signode = self.node_factory.desc_signature() + + signode["names"].append(name) + signode["ids"].append(name) + + self.document.note_explicit_target(signode) + + inv = self.env.domaindata['c']['objects'] + if name in inv: + self.env.warn( + self.env.docname, + 'duplicate C object description of %s, ' % name + + 'other instance in ' + self.env.doc2path(inv[name][0]), + self.lineno) + inv[name] = (self.env.docname, "function") + + +class CppDomainHandler(DomainHandler): + + def create_class_id(self, data_object): + + def_ = data_object.name + + parser = self.helper.definition_parser(def_) + sigobj = parser.parse_class() + + return sigobj.get_id() + + def create_class_target(self, data_object): + + _id = self.create_class_id(data_object) + + in_cache, project = self.helper.check_cache(_id) + if in_cache: + print "Warning: Ignoring duplicate domain reference '%s'. " \ + "First found in project '%s'" % (_id, project.reference()) + return + + self.helper.cache(_id, self.project_info) + + signode = self.node_factory.desc_signature() + + signode["names"].append(_id) + signode["ids"].append(_id) + + name = data_object.name + self.document.settings.env.domaindata['cpp']['objects'].setdefault(name, + (self.document.settings.env.docname, "class", _id)) + + self.document.note_explicit_target(signode) + + def create_function_id(self, data_object): + + definition = self.helper.remove_word("virtual", data_object.definition) + argstring = data_object.argsstring + + explicit = "explicit " if data_object.explicit == "yes" else "" + + def_ = "%(explicit)s%(definition)s%(argstring)s" % { + "explicit" : explicit, + "definition" : definition, + "argstring" : argstring, + } + + parser = self.helper.definition_parser(def_) + sigobj = parser.parse_function() + + return sigobj.get_id() + + def create_function_target(self, data_object): + + _id = self.create_function_id(data_object) + + in_cache, project = self.helper.check_cache(_id) + if in_cache: + print "Warning: Ignoring duplicate domain reference '%s'. " \ + "First found in project '%s'" % (_id, project.reference()) + return + + self.helper.cache(_id, self.project_info) + + signode = self.node_factory.desc_signature() + + signode["names"].append(_id) + signode["ids"].append(_id) + + name = data_object.definition.split()[-1] + self.document.settings.env.domaindata['cpp']['objects'].setdefault(name, + (self.document.settings.env.docname, "function", _id)) + + self.document.note_explicit_target(signode) + + +class DomainHandlerFactory(object): + + def __init__(self, project_info, node_factory, document, env, helpers): + + self.project_info = project_info + self.node_factory = node_factory + self.document = document + self.env = env + self.domain_helpers = helpers + + def create_null_domain_handler(self): + + return NullDomainHandler() + + def create_domain_handler(self, file_): + + domains_handlers = { + "c" : CDomainHandler, + "cpp" : CppDomainHandler, + } + + domain = self.project_info.domain_for_file(file_) + + try: + helper = self.domain_helpers[domain] + except KeyError: + helper = NullDomainHelper() + + try: + return domains_handlers[domain](self.node_factory, self.document, self.env, helper, self.project_info) + except KeyError: + return NullDomainHandler() + +class NullDomainHandlerFactory(object): + + def create_null_domain_handler(self): + + return NullDomainHandler() + + def create_domain_handler(self, file_): + + return NullDomainHandler() + +class DomainHandlerFactoryCreator(object): + + def __init__(self, node_factory, helpers): + + self.node_factory = node_factory + self.helpers = helpers + + def create_domain_handler_factory(self, project_info, document, env, options): + + if "no-link" in options: + return NullDomainHandlerFactory() + + return DomainHandlerFactory(project_info, self.node_factory, document, env, self.helpers) + diff --git a/foreignlibs/breathe/breathe/renderer/rst/doxygen/filter.py b/foreignlibs/breathe/breathe/renderer/rst/doxygen/filter.py new file mode 100644 index 00000000..dddb49cc --- /dev/null +++ b/foreignlibs/breathe/breathe/renderer/rst/doxygen/filter.py @@ -0,0 +1,454 @@ + +class Selecter(object): + pass + +class Parent(Selecter): + + def __call__(self, parent_data_object, child_data_object): + return parent_data_object + +class Child(Selecter): + + def __call__(self, parent_data_object, child_data_object): + return child_data_object + + +class Accessor(object): + + def __init__(self, selecter): + self.selecter = selecter + +class NameAccessor(Accessor): + + def __call__(self, parent_data_object, child_data_object): + return self.selecter(parent_data_object, child_data_object).name + +class NodeNameAccessor(Accessor): + + def __call__(self, parent_data_object, child_data_object): + return self.selecter(parent_data_object, child_data_object).node_name + +class NodeTypeAccessor(Accessor): + + def __call__(self, parent_data_object, child_data_object): + + data_object = self.selecter(parent_data_object, child_data_object) + try: + return data_object.node_type + except AttributeError, e: + + # Horrible hack to silence errors on filtering unicode objects + # until we fix the parsing + if type(data_object) == unicode: + return "unicode" + else: + raise e + +class KindAccessor(Accessor): + + def __call__(self, parent_data_object, child_data_object): + return self.selecter(parent_data_object, child_data_object).kind + +class LambdaAccessor(Accessor): + + def __init__(self, selecter, func): + Accessor.__init__(self, selecter) + + self.func = func + + def __call__(self, parent_data_object, child_data_object): + return self.func(self.selecter(parent_data_object, child_data_object)) + +class NamespaceAccessor(Accessor): + + def __call__(self, parent_data_object, child_data_object): + return self.selecter(parent_data_object, child_data_object).namespaces + +class NameFilter(object): + + def __init__(self, accessor, members): + + self.accessor = accessor + self.members = members + + def allow(self, parent_data_object, child_data_object): + + name = self.accessor(parent_data_object, child_data_object) + + return name in self.members + +class GlobFilter(object): + + def __init__(self, accessor, glob): + + self.accessor = accessor + self.glob = glob + + def allow(self, parent_data_object, child_data_object): + + text = self.accessor(parent_data_object, child_data_object) + return self.glob.match(text) + + +class FilePathFilter(object): + + def __init__(self, accessor, target_file, path_handler): + + self.accessor = accessor + self.target_file = target_file + self.path_handler = path_handler + + def allow(self, parent_data_object, child_data_object): + + location = self.accessor(parent_data_object, child_data_object).file + + if self.path_handler.includes_directory(self.target_file): + # If the target_file contains directory separators then + # match against the same length at the ned of the location + # + location_match = location[-len(self.target_file):] + return location_match == self.target_file + + else: + # If there are not separators, match against the whole filename + # at the end of the location + # + # This is to prevent "Util.cpp" matching "PathUtil.cpp" + # + location_basename = self.path_handler.basename(location) + return location_basename == self.target_file + +class NamespaceFilter(object): + + def __init__(self, namespace_accessor, name_accessor): + + self.namespace_accessor = namespace_accessor + self.name_accessor = name_accessor + + def allow(self, parent_data_object, child_data_object): + + namespaces = self.namespace_accessor(parent_data_object, child_data_object) + name = self.name_accessor(parent_data_object, child_data_object) + + try: + namespace, name = name.rsplit("::", 1) + except ValueError: + namespace, name = "", name + + return namespace in namespaces + +class OpenFilter(object): + + def allow(self, parent_data_object, child_data_object): + + return True + +class ClosedFilter(object): + + def allow(self, parent_data_object, child_data_object): + + return False + +class NotFilter(object): + + def __init__(self, child_filter): + self.child_filter = child_filter + + def allow(self, parent_data_object, child_data_object): + + return not self.child_filter.allow(parent_data_object, child_data_object) + +class AndFilter(object): + + def __init__(self, first_filter, second_filter): + + self.first_filter = first_filter + self.second_filter = second_filter + + def allow(self, parent_data_object, child_data_object): + + return self.first_filter.allow(parent_data_object, child_data_object) \ + and self.second_filter.allow(parent_data_object, child_data_object) + +class OrFilter(object): + + def __init__(self, first_filter, second_filter): + + self.first_filter = first_filter + self.second_filter = second_filter + + def allow(self, parent_data_object, child_data_object): + + return self.first_filter.allow(parent_data_object, child_data_object) \ + or self.second_filter.allow(parent_data_object, child_data_object) + +class Glob(object): + + def __init__(self, method, pattern): + + self.method = method + self.pattern = pattern + + def match(self, name): + + return self.method(name, self.pattern) + +class GlobFactory(object): + + def __init__(self, method): + + self.method = method + + def create(self, pattern): + + return Glob(self.method, pattern) + +class Gather(object): + + def __init__(self, accessor, names): + + self.accessor = accessor + self.names = names + + def allow(self, parent_data_object, child_data_object): + + self.names.extend( self.accessor(parent_data_object, child_data_object) ) + + return False + + + +class FilterFactory(object): + + def __init__(self, globber_factory, path_handler): + + self.globber_factory = globber_factory + self.path_handler = path_handler + + def create_class_filter(self, options): + + return AndFilter( + self.create_members_filter(options), + AndFilter( + self.create_outline_filter(options), + self.create_show_filter(options), + ) + ) + + def create_show_filter(self, options): + """ + Currently only handles the header-file entry + """ + + try: + text = options["show"] + except KeyError: + # Allow through everything except the header-file includes nodes + return OrFilter( + NotFilter(NameFilter(NodeTypeAccessor(Parent()), ["compounddef"])), + NotFilter(NameFilter(NodeTypeAccessor(Child()), ["inc"])) + ) + + if text == "header-file": + # Allow through everything, including header-file includes + return OpenFilter() + + # Allow through everything except the header-file includes nodes + return OrFilter( + NotFilter(NameFilter(NodeTypeAccessor(Parent()), ["compounddef"])), + NotFilter(NameFilter(NodeTypeAccessor(Child()), ["inc"])) + ) + + + def create_members_filter(self, options): + + try: + text = options["members"] + except KeyError: + return OrFilter( + NotFilter(NameFilter(NodeTypeAccessor(Parent()), ["sectiondef"])), + NotFilter(NameFilter(NodeTypeAccessor(Child()), ["memberdef"])) + ) + + if not text.strip(): + return OrFilter( + NotFilter(NameFilter(NodeTypeAccessor(Child()), ["sectiondef"])), + OrFilter( + GlobFilter(KindAccessor(Child()), self.globber_factory.create("public*")), + NameFilter(KindAccessor(Child()), ["user-defined"]) + ) + ) + + # Matches sphinx-autodoc behaviour of comma separated values + members = set([x.strip() for x in text.split(",")]) + + return OrFilter( + NotFilter(NameFilter(NodeTypeAccessor(Parent()),["sectiondef"])), + NameFilter(NameAccessor(Child()), members) + ) + + def create_outline_filter(self, options): + + if options.has_key("outline"): + return NotFilter(NameFilter(NodeTypeAccessor(Child()), ["description"])) + else: + return OpenFilter() + + def create_file_filter(self, filename, options): + + valid_names = [] + + filter_ = AndFilter( + AndFilter( + AndFilter( + NotFilter( + # Gather the "namespaces" attribute from the + # compounddef for the file we're rendering and + # store the information in the "valid_names" list + # + # Gather always returns false, so, combined with + # the NotFilter this chunk always returns true and + # so does not affect the result of the filtering + AndFilter( + AndFilter( + AndFilter( + NameFilter(NodeTypeAccessor(Child()), ["compounddef"]), + NameFilter(KindAccessor(Child()), ["file"]) + ), + FilePathFilter( + LambdaAccessor(Child(), lambda x: x.location), filename, self.path_handler + ) + ), + Gather(LambdaAccessor(Child(), lambda x: x.namespaces), valid_names) + ) + ), + NotFilter( + # Take the valid_names and everytime we handle an + # innerclass or innernamespace, check that its name + # was one of those initial valid names so that we + # never end up rendering a namespace or class that + # wasn't in the initial file. Notably this is + # required as the location attribute for the + # namespace in the xml is unreliable. + AndFilter( + NameFilter(NodeTypeAccessor(Parent()), ["compounddef"]), + AndFilter( + AndFilter( + NameFilter(NodeTypeAccessor(Child()),["ref"]), + NameFilter(NodeNameAccessor(Child()),["innerclass", "innernamespace"]) + ), + NotFilter(NameFilter( + LambdaAccessor(Child(), lambda x: x.content_[0].getValue()), + valid_names + )) + ) + ) + ) + ), + NotFilter( + # Ignore innerclasses and innernamespaces that are inside a + # namespace that is going to be rendered as they will be + # rendered with that namespace and we don't want them twice + AndFilter( + NameFilter(NodeTypeAccessor(Parent()), ["compounddef"]), + AndFilter( + AndFilter( + NameFilter(NodeTypeAccessor(Child()),["ref"]), + NameFilter(NodeNameAccessor(Child()),["innerclass", "innernamespace"]) + ), + NamespaceFilter( + NamespaceAccessor(Parent()), + LambdaAccessor(Child(), lambda x: x.content_[0].getValue()) + ) + ) + ) + ), + ), + AndFilter( + NotFilter( + # Ignore memberdefs from files which are different to + # the one we're rendering. This happens when we have to + # cross into a namespace xml file which has entries + # from multiple files in it + AndFilter( + NameFilter(NodeTypeAccessor(Child()), ["memberdef"]), + NotFilter( + FilePathFilter(LambdaAccessor(Child(), lambda x: x.location), filename, self.path_handler) + ) + ) + ), + NotFilter( + # Ignore compounddefs which are from another file + # (normally means classes and structs which are in a + # namespace that we have other interests in) but only + # check it if the compounddef is not a namespace + # itself, as for some reason compounddefs for + # namespaces are registered with just a single file + # location even if they namespace is spread over + # multiple files + AndFilter( + AndFilter( + NameFilter(NodeTypeAccessor(Child()), ["compounddef"]), + NotFilter(NameFilter(KindAccessor(Child()), ["namespace"])) + ), + NotFilter( + FilePathFilter(LambdaAccessor(Child(), lambda x: x.location), filename, self.path_handler) + ) + ) + ) + ) + ) + + return AndFilter( + self.create_outline_filter(options), + filter_ + ) + + def create_index_filter(self, options): + + filter_ = AndFilter( + NotFilter( + AndFilter( + NameFilter(NodeTypeAccessor(Parent()), ["compounddef"]), + AndFilter( + NameFilter(NodeTypeAccessor(Child()),["ref"]), + NameFilter(NodeNameAccessor(Child()),["innerclass", "innernamespace"]) + ) + ) + ), + NotFilter( + AndFilter( + AndFilter( + NameFilter(NodeTypeAccessor(Parent()), ["compounddef"]), + NameFilter(KindAccessor(Parent()), ["group"]) + ), + AndFilter( + NameFilter(NodeTypeAccessor(Child()),["sectiondef"]), + NameFilter(KindAccessor(Child()),["func"]) + ) + ) + ) + ) + + + return AndFilter( + self.create_outline_filter(options), + filter_ + ) + + def create_open_filter(self): + + return OpenFilter() + + def create_file_finder_filter(self, filename): + + filter_ = AndFilter( + AndFilter( + NameFilter(NodeTypeAccessor(Child()), ["compounddef"]), + NameFilter(KindAccessor(Child()), ["file"]), + ), + FilePathFilter(LambdaAccessor(Child(), lambda x: x.location), filename, self.path_handler) + ) + + return filter_ + diff --git a/foreignlibs/breathe/breathe/renderer/rst/doxygen/index.py b/foreignlibs/breathe/breathe/renderer/rst/doxygen/index.py new file mode 100644 index 00000000..d1af39c5 --- /dev/null +++ b/foreignlibs/breathe/breathe/renderer/rst/doxygen/index.py @@ -0,0 +1,115 @@ + +from breathe.renderer.rst.doxygen.base import Renderer + +class DoxygenTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + + # Process all the compound children + for compound in self.data_object.get_compound(): + compound_renderer = self.renderer_factory.create_renderer(self.data_object, compound) + nodelist.extend(compound_renderer.render()) + + return nodelist + + +class CompoundTypeSubRenderer(Renderer): + + def __init__(self, compound_parser, *args): + Renderer.__init__(self, *args) + + self.compound_parser = compound_parser + + def create_target(self, refid): + + return self.target_handler.create_target(refid) + + def create_domain_id(self): + + return "" + + def render(self): + + refid = "%s%s" % (self.project_info.name(), self.data_object.refid) + nodelist = self.create_target(refid) + + domain_id = self.create_domain_id() + + + # Read in the corresponding xml file and process + file_data = self.compound_parser.parse(self.data_object.refid) + + lines = [] + + # Check if there is template information and format it as desired + if file_data.compounddef.templateparamlist: + renderer = self.renderer_factory.create_renderer( + file_data.compounddef, + file_data.compounddef.templateparamlist + ) + template = [ + self.node_factory.Text("template < ") + ] + template.extend(renderer.render()) + template.append(self.node_factory.Text(" >")) + lines.append(self.node_factory.line("", *template)) + + # Set up the title and a reference for it (refid) + kind = self.node_factory.emphasis(text=self.data_object.kind) + name = self.node_factory.strong(text=self.data_object.name) + + # Add blank string at the start otherwise for some reason it renders + # the emphasis tags around the kind in plain text + lines.append( + self.node_factory.line( + "", + self.node_factory.Text(""), + kind, + self.node_factory.Text(" "), + name + ) + ) + + + if file_data.compounddef.includes: + for include in file_data.compounddef.includes: + renderer = self.renderer_factory.create_renderer( + file_data.compounddef, + include + ) + result = renderer.render() + if result: + lines.append( + self.node_factory.line( + "", + self.node_factory.Text(""), + *result + ) + ) + + nodelist.append( + self.node_factory.line_block( + "", + *lines + ) + ) + + data_renderer = self.renderer_factory.create_renderer(self.data_object, file_data) + nodelist.extend(data_renderer.render()) + + return nodelist + + +class ClassCompoundTypeSubRenderer(CompoundTypeSubRenderer): + + def create_target(self, refid): + + self.domain_handler.create_class_target(self.data_object) + return CompoundTypeSubRenderer.create_target(self, refid) + + def create_domain_id(self): + + return self.domain_handler.create_class_id(self.data_object) + diff --git a/foreignlibs/breathe/breathe/renderer/rst/doxygen/target.py b/foreignlibs/breathe/breathe/renderer/rst/doxygen/target.py new file mode 100644 index 00000000..2ddb43a6 --- /dev/null +++ b/foreignlibs/breathe/breathe/renderer/rst/doxygen/target.py @@ -0,0 +1,40 @@ + +class TargetHandler(object): + + def __init__(self, project_info, node_factory, document): + + self.project_info = project_info + self.node_factory = node_factory + self.document = document + + def create_target(self, refid): + + target = self.node_factory.target(refid=refid, ids=[refid], names=[refid]) + + # Tell the document about our target + try: + self.document.note_explicit_target(target) + except Exception, e: + print "Failed to register id: %s. This is a seemingly harmless bug." % refid + + return [target] + +class NullTargetHandler(object): + + def create_target(self, refid): + return [] + + +class TargetHandlerFactory(object): + + def __init__(self, node_factory): + + self.node_factory = node_factory + + def create(self, options, project_info, document): + + if options.has_key("no-link"): + return NullTargetHandler() + + return TargetHandler(project_info, self.node_factory, document) + diff --git a/foreignlibs/doxylink/__init__.py b/foreignlibs/doxylink/__init__.py new file mode 100644 index 00000000..8414033b --- /dev/null +++ b/foreignlibs/doxylink/__init__.py @@ -0,0 +1,2 @@ +from doxylink import * + diff --git a/foreignlibs/doxylink/doxylink.py b/foreignlibs/doxylink/doxylink.py new file mode 100644 index 00000000..7104af40 --- /dev/null +++ b/foreignlibs/doxylink/doxylink.py @@ -0,0 +1,454 @@ +# -*- coding: utf-8 -*- + +import os +import xml.etree.ElementTree as ET +import urlparse +import re +import itertools + +from docutils import nodes, utils +from sphinx.util.nodes import split_explicit_title +from sphinx.util.console import bold, standout + +from parsing import normalise, ParseException + +def find_url(doc, symbol): + """ + Return the URL for a given symbol. + + This is where the magic happens. + This function could be a lot more clever. At present it required the passed symbol to be almost exactly the same as the entries in the Doxygen tag file. + + .. todo:: + + Maybe print a list of all possible matches as a warning (but still only return the first) + + :Parameters: + doc : xml.etree.ElementTree + The XML DOM object + symbol : string + The symbol to lookup in the file. E.g. something like 'PolyVox::Array' or 'tidyUpMemory' + + :return: String representing the filename part of the URL + """ + + #First check for an exact match with a top-level object (namespaces, objects etc.) + + #env = inliner.document.settings.env + + matches = [] + for compound in doc.findall('.//compound'): + if compound.find('name').text == symbol: + matches += [{'file':compound.find('filename').text, 'kind':compound.get('kind')}] + + if len(matches) > 1: + pass + #env.warn(env.docname, 'There were multiple matches for `%s`: %s' % (symbol, matches)) + if len(matches) == 1: + return matches[0] + + + #Strip off first namespace bit of the compound name so that 'ArraySizes' can match 'PolyVox::ArraySizes' + for compound in doc.findall('.//compound'): + symbol_list = compound.find('name').text.split('::', 1) + if len(symbol_list) == 2: + reducedsymbol = symbol_list[1] + if reducedsymbol == symbol: + return {'file':compound.find('filename').text, 'kind':compound.get('kind')} + + #Now split the symbol by '::'. Find an exact match for the first part and then a member match for the second + #So PolyVox::Array::operator[] becomes like {namespace: "PolyVox::Array", endsymbol: "operator[]"} + symbol_list = symbol.rsplit('::', 1) + if len(symbol_list) == 2: + namespace = symbol_list[0] + endsymbol = symbol_list[1] + for compound in doc.findall('.//compound'): + if compound.find('name').text == namespace: + for member in compound.findall('member'): + #If this compound object contains the matching member then return it + if member.find('name').text == endsymbol: + return {'file':(member.findtext('anchorfile') or compound.findtext('filename')) + '#' + member.find('anchor').text, 'kind':member.get('kind')} + + #Then we'll look at unqualified members + for member in doc.findall('.//member'): + if member.find('name').text == symbol: + return {'file':(member.findtext('anchorfile') or compound.findtext('filename')) + '#' + member.find('anchor').text, 'kind':member.get('kind')} + + return None + +def parse_tag_file(doc): + """ + Takes in an XML tree from a Doxygen tag file and returns a dictionary that looks something like: + + .. code-block:: python + + {'PolyVox': {'file': 'namespace_poly_vox.html', + 'kind': 'namespace'}, + 'PolyVox::Array': {'file': 'class_poly_vox_1_1_array.html', + 'kind': 'class'}, + 'PolyVox::Array1DDouble': {'file': 'namespace_poly_vox.html#a7a1f5fd5c4f7fbb4258a495d707b5c13', + 'kind': 'typedef'}, + 'PolyVox::Array1DFloat': {'file': 'namespace_poly_vox.html#a879a120e49733eba1905c33f8a7f131b', + 'kind': 'typedef'}, + 'PolyVox::Array1DInt16': {'file': 'namespace_poly_vox.html#aa1463ece448c6ebed55ab429d6ae3e43', + 'kind': 'typedef'}, + 'QScriptContext::throwError': {'arglist': {'( Error error, const QString & text )': 'qscriptcontext.html#throwError', + '( const QString & text )': 'qscriptcontext.html#throwError-2'}, + 'kind': 'function'}, + 'QScriptContext::toString': {'arglist': {'()': 'qscriptcontext.html#toString'}, + 'kind': 'function'}} + + Note the different form for functions. This is required to allow for 'overloading by argument type'. + + To access a filename for a symbol you do: + + .. code-block:: python + + symbol_mapping = mapping[symbol] + if symbol_mapping['kind'] == 'function': + url = symbol_mapping['arglist'][argument_string] + else: + url = symbol_mapping['file'] + + :Parameters: + doc : xml.etree.ElementTree + The XML DOM object + + :return: a dictionary mapping fully qualified symbols to files + """ + + mapping = {} + function_list = [] #This is a list of function to be parsed and inserted into mapping at the end of the function. + for compound in doc.findall("./compound"): + compound_kind = compound.get('kind') + if compound_kind != 'namespace' and compound_kind != 'class' and compound_kind!= 'struct' and compound_kind != 'file': + continue #Skip everything that isn't a namespace, class, struct or file + + compound_name = compound.findtext('name') + compound_filename = compound.findtext('filename') + + #TODO The following is a hack bug fix I think + #Doxygen doesn't seem to include the file extension to entries + #If it's a 'file' type, check if it _does_ have an extension, if not append '.html' + if compound_kind == 'file' and not os.path.splitext(compound_filename)[1]: + compound_filename = join(compound_filename, '.html') + + #If it's a compound we can simply add it + mapping[compound_name] = {'kind' : compound_kind, 'file' : compound_filename} + + for member in compound.findall('member'): + + #If the member doesn't have an element, use the parent compounds instead + #This is the way it is in the qt.tag and is perhaps an artefact of old Doxygen + anchorfile = member.findtext('anchorfile') or compound_filename + member_symbol = join(compound_name, '::', member.findtext('name')) + member_kind = member.get('kind') + arglist_text = member.findtext('./arglist') #If it has an then we assume it's a function. Empty returns '', not None. Things like typedefs and enums can have empty arglists + + if arglist_text and member_kind != 'variable' and member_kind != 'typedef' and member_kind != 'enumeration': + function_list.append((member_symbol, arglist_text, member_kind, join(anchorfile,'#',member.findtext('anchor')))) + else: + mapping[member_symbol] = {'kind' : member.get('kind'), 'file' : join(anchorfile,'#',member.findtext('anchor'))} + + for old_tuple, normalised_tuple in zip(function_list, itertools.imap(normalise, (member_tuple[1] for member_tuple in function_list))): + member_symbol = old_tuple[0] + original_arglist = old_tuple[1] + kind = old_tuple[2] + anchor_link = old_tuple[3] + normalised_arglist = normalised_tuple[1] + if normalised_tuple[1] is not None: #This is a 'flag' for a ParseException having happened + if mapping.get(member_symbol): + mapping[member_symbol]['arglist'][normalised_arglist] = anchor_link + else: + mapping[member_symbol] = {'kind' : kind, 'arglist' : {normalised_arglist : anchor_link}} + else: + print 'Skipping %s %s%s. Error reported from parser was: %s' % (old_tuple[2], old_tuple[0], old_tuple[1], normalised_tuple[0]) + + #from pprint import pprint; pprint(mapping) + return mapping + +def find_url2(mapping, symbol): + """ + Return the URL for a given symbol. + + This is where the magic happens. + + .. todo:: + + Maybe print a list of all possible matches as a warning (but still only return the first) + + :Parameters: + mapping : dictionary + A dictionary of the form returned by :py:func:`parse_tag_file` + symbol : string + The symbol to lookup in the file. E.g. something like 'PolyVox::Array' or 'tidyUpMemory' + + :return: String representing the filename part of the URL + + :raises: + LookupError + Raised if the symbol could not be matched in the file + """ + #print "\n\nSearching for", symbol + try: + symbol, normalised_arglist = normalise(symbol) + except ParseException as error: + raise LookupError(error) + #print symbol, normalised_arglist + + #If we have an exact match then return it. + if mapping.get(symbol): + #print ('Exact match') + return return_from_mapping(mapping[symbol], normalised_arglist) + + #If the user didn't pass in any arguments, i.e. `arguments == ''` then they don't care which version of the overloaded funtion they get. + + #First we check for any mapping entries which even slightly match the requested symbol + #endswith_list = {} + #for item, data in mapping.items(): + # if item.endswith(symbol): + #print symbol + ' : ' + item + # endswith_list[item] = data + # mapping[item]['file'] + + #If we only find one then we return it. + #if len(endswith_list) is 1: + # return endswith_list.values()[0]['file'] + + #print("Still", len(endswith_list), 'possible matches') + + piecewise_list = find_url_piecewise(mapping, symbol) + + #If there is only one match, return it. + if len(piecewise_list) is 1: + return return_from_mapping(piecewise_list.values()[0], normalised_arglist) + + #print("Still", len(piecewise_list), 'possible matches') + + #If there is more than one item in piecewise_list then there is an ambiguity + #Often this is due to the symbol matching the name of the constructor as well as the class name itself + classes_list = find_url_classes(piecewise_list, symbol) + + #If there is only one by here we return it. + if len(classes_list) is 1: + return classes_list.values()[0] + + #print("Still", len(classes_list), 'possible matches') + + #If we exhaused the list by requiring classes, use the list from before the filter. + if len(classes_list) == 0: + classes_list = piecewise_list + + no_templates_list = find_url_remove_templates(classes_list, symbol) + + if len(no_templates_list) is 1: + return return_from_mapping(no_templates_list.values()[0], normalised_arglist) + + #print("Still", len(no_templates_list), 'possible matches') + + #If not found by now, just return the first one in the list + if len(no_templates_list) != 0: + #TODO return a warning here? + return return_from_mapping(no_templates_list.values()[0], normalised_arglist) + #Else return None if the list is empty + else: + LookupError('Could not find a match') + +def return_from_mapping(mapping_entry, normalised_arglist=''): + """ + Return a mapping to a single URL in the form. This is needed since mapping entries for functions are more complicated due to function overriding. + + If the mapping to be returned is not a function, this will simply return the mapping entry intact. If the entry is a function it will attempt to get the right version based on the function signature. + + :Parameters: + mapping_entry : dict + should be a single entry from the large mapping file corresponding to a single symbol. If the symbol is a function, then ``mappingentry['arglist']`` will be a dictionary mapping normalised signatures to URLs + normalised_arglist : string + the normalised form of the arglist that the user has requested. This can be empty in which case the function will return just the first element of ``mappingentry['arglist']``. This parameter is ignored if ``mappingentry['kind'] != 'function'`` + + :return: dictionary something like: + + .. code-block:: python + + {'kind' : 'function', 'file' : 'something.html#foo'} + + """ + #If it's a function we need to grab the right signature from the arglist. + if mapping_entry['kind'] == 'function': + #If the user has requested a specific function through specifying an arglist then get the right anchor + if normalised_arglist: + filename = mapping_entry['arglist'].get(normalised_arglist) + if not filename: #If we didn't get the filename because it's not in the mapping then we will just return a random one? + #TODO return a warning here! + filename = mapping_entry['arglist'].values()[0] + else: + #Otherwise just return the first entry (if they don't care they get whatever comes first) + filename = mapping_entry['arglist'].values()[0] + + return {'kind' : 'function', 'file' : filename} + elif mapping_entry.get('arglist'): + #This arglist should only be one entry long and that entry should have '' as its key + return {'kind' : mapping_entry['kind'], 'file' : mapping_entry['arglist']['']} + + #If it's not a function, then return it raw + return mapping_entry + +def find_url_piecewise(mapping, symbol): + """ + Match the requested symbol reverse piecewise (split on ``::``) against the tag names to ensure they match exactly (modulo ambiguity) + So, if in the mapping there is ``PolyVox::Volume::FloatVolume`` and ``PolyVox::Volume`` they would be split into: + + .. code-block:: python + + ['PolyVox', 'Volume', 'FloatVolume'] and ['PolyVox', 'Volume'] + + and reversed: + + .. code-block:: python + + ['FloatVolume', 'Volume', 'PolyVox'] and ['Volume', 'PolyVox'] + + and truncated to the shorter of the two: + + .. code-block:: python + + ['FloatVolume', 'Volume'] and ['Volume', 'PolyVox'] + + If we're searching for the ``PolyVox::Volume`` symbol we would compare: + + .. code-block:: python + + ['Volume', 'PolyVox'] to ['FloatVolume', 'Volume', 'PolyVox']. + + That doesn't match so we look at the next in the mapping: + + .. code-block:: python + + ['Volume', 'PolyVox'] to ['Volume', 'PolyVox']. + + Good, so we add it to the list + + """ + piecewise_list = {} + for item, data in mapping.items(): + split_symbol = symbol.split('::') + split_item = item.split('::') + + split_symbol.reverse() + split_item.reverse() + + min_length = min(len(split_symbol), len(split_item)) + + split_symbol = split_symbol[:min_length] + split_item = split_item[:min_length] + + #print split_symbol, split_item + + if split_symbol == split_item: + #print symbol + ' : ' + item + piecewise_list[item] = data + + return piecewise_list + +def find_url_classes(mapping, symbol): + """Prefer classes over names of constructors""" + classes_list = {} + for item, data in mapping.items(): + if data['kind'] == 'class': + #print symbol + ' : ' + item + classes_list[item] = data + + return classes_list + +def find_url_remove_templates(mapping, symbol): + """Now, to disambiguate between ``PolyVox::Array< 1, ElementType >::operator[]`` and ``PolyVox::Array::operator[]`` matching ``operator[]``, we will ignore templated (as in C++ templates) tag names by removing names containing ``<``""" + no_templates_list = {} + for item, data in mapping.items(): + if '<' not in item: + #print symbol + ' : ' + item + no_templates_list[item] = data + + return no_templates_list + +def join(*args): + return ''.join(args) + +def create_role(app, tag_filename, rootdir): + #Tidy up the root directory path + if not rootdir.endswith(('/', '\\')): + rootdir = join(rootdir, os.sep) + + try: + tag_file = ET.parse(tag_filename) + + cache_name = os.path.basename(tag_filename) + + app.info(bold('Checking tag file cache for %s: ' % cache_name), nonl=True) + if not hasattr(app.env, 'doxylink_cache'): + # no cache present at all, initialise it + app.info('No cache at all, rebuilding...') + mapping = parse_tag_file(tag_file) + app.env.doxylink_cache = { cache_name : {'mapping' : mapping, 'mtime' : os.path.getmtime(tag_filename)}} + elif not app.env.doxylink_cache.get(cache_name): + # Main cache is there but the specific sub-cache for this tag file is not + app.info('Sub cache is missing, rebuilding...') + mapping = parse_tag_file(tag_file) + app.env.doxylink_cache[cache_name] = {'mapping' : mapping, 'mtime' : os.path.getmtime(tag_filename)} + elif app.env.doxylink_cache[cache_name]['mtime'] < os.path.getmtime(tag_filename): + # tag file has been modified since sub-cache creation + app.info('Sub-cache is out of date, rebuilding...') + mapping = parse_tag_file(tag_file) + app.env.doxylink_cache[cache_name] = {'mapping' : mapping, 'mtime' : os.path.getmtime(tag_filename)} + else: + #The cache is up to date + app.info('Sub-cache is up-to-date') + except IOError: + tag_file = None + app.warn(standout('Could not open tag file %s. Make sure your `doxylink` config variable is set correctly.' % tag_filename)) + + def find_doxygen_link(name, rawtext, text, lineno, inliner, options={}, content=[]): + text = utils.unescape(text) + # from :name:`title ` + has_explicit_title, title, part = split_explicit_title(text) + warning_messages = [] + if tag_file: + url = find_url(tag_file, part) + # If there are several doxy projects within the same sphinx instance then the cache is always OK + # and one cannot regenerate a new cache for a new project... So I comment these 4 lines... + #try: + # url = find_url2(app.env.doxylink_cache[cache_name]['mapping'], part) + #except LookupError as error: + # warning_messages.append('Error while parsing `%s`. Is not a well-formed C++ function call or symbol. If this is not the case, it is a doxylink bug so please report it. Error reported was: %s' % (part, error)) + if url: + + #If it's an absolute path then the link will work regardless of the document directory + #Also check if it is a URL (i.e. it has a 'scheme' like 'http' or 'file') + if os.path.isabs(rootdir) or urlparse.urlparse(rootdir).scheme: + full_url = join(rootdir, url['file']) + #But otherwise we need to add the relative path of the current document to the root source directory to the link + else: + relative_path_to_docsrc = os.path.relpath(app.env.srcdir, os.path.dirname(inliner.document.current_source)) + full_url = join(relative_path_to_docsrc, '/', rootdir, url['file']) #We always use the '/' here rather than os.sep since this is a web link avoids problems like documentation/.\../library/doc/ (mixed slashes) + + if url['kind'] == 'function' and app.config.add_function_parentheses and not normalise(title)[1]: + title = join(title, '()') + + pnode = nodes.reference(title, title, internal=False, refuri=full_url) + return [pnode], [] + #By here, no match was found + warning_messages.append('Could not find match for `%s` in `%s` tag file' % (part, tag_filename)) + else: + warning_messages.append('Could not find match for `%s` because tag file not found' % (part)) + + pnode = nodes.inline(rawsource=title, text=title) + return [pnode], [inliner.reporter.warning(message, line=lineno) for message in warning_messages] + + return find_doxygen_link + +def setup_doxylink_roles(app): + for name, [tag_filename, rootdir] in app.config.doxylink.iteritems(): + app.add_role(name, create_role(app, tag_filename, rootdir)) + +def setup(app): + app.add_config_value('doxylink', {}, 'env') + app.connect('builder-inited', setup_doxylink_roles) diff --git a/foreignlibs/doxylink/parsing.py b/foreignlibs/doxylink/parsing.py new file mode 100644 index 00000000..4e42f44b --- /dev/null +++ b/foreignlibs/doxylink/parsing.py @@ -0,0 +1,153 @@ +#import multiprocessing +import itertools + +from pyparsing import Word, Literal, alphas, nums, alphanums, OneOrMore, Optional, SkipTo, ParseException, Group, ZeroOrMore, Suppress, Combine, delimitedList, quotedString, nestedExpr, ParseResults, oneOf + +# define punctuation - reuse of expressions helps packratting work better +LPAR,RPAR,LBRACK,RBRACK,COMMA,EQ = map(Literal,"()[],=") + +#Qualifier to go in front of type in the argument list (unsigned const int foo) +qualifier = OneOrMore(oneOf('const unsigned typename struct enum')) + +def turn_parseresults_to_list(s, loc, toks): + return ParseResults(normalise_templates(toks[0].asList())) + +def normalise_templates(toks, isinstance=isinstance, basestring=basestring): + s_list = ['<'] + s_list_append = s_list.append #lookup append func once, instead of many times + for tok in toks: + if isinstance(tok, basestring): #See if it's a string + s_list_append(' ' + tok) + else: + #If it's not a string + s_list_append(normalise_templates(tok)) + s_list_append(' >') + return ''.join(s_list) + +#Skip pairs of brackets. +angle_bracket_pair = nestedExpr(opener='<',closer='>').setParseAction(turn_parseresults_to_list) +#TODO Fix for nesting brackets +parentheses_pair = LPAR + SkipTo(RPAR) + RPAR +square_bracket_pair = LBRACK + SkipTo(RBRACK) + RBRACK + +#The raw type of the input, i.e. 'int' in (unsigned const int * foo) +#TODO I guess this should be a delimited list (by '::') of name and angle brackets +input_type = Combine(Word(alphanums + ':_') + Optional(angle_bracket_pair + Optional(Word(alphanums + ':_')))) + +#A number. e.g. -1, 3.6 or 5 +number = Word('-.' + nums) + +#The name of the argument. We will ignore this but it must be matched anyway. +input_name = OneOrMore(Word(alphanums + '_') | angle_bracket_pair | parentheses_pair | square_bracket_pair) + +#Grab the '&', '*' or '**' type bit in (const QString & foo, int ** bar) +pointer_or_reference = oneOf('* &') + +#The '=QString()' or '=false' bit in (int foo = 4, bool bar = false) +default_value = Literal('=') + OneOrMore(number | quotedString | input_type | parentheses_pair | angle_bracket_pair | square_bracket_pair | Word('|&^')) + +#A combination building up the interesting bit -- the argument type, e.g. 'const QString &', 'int' or 'char*' +argument_type = Optional(qualifier, default='')("qualifier") + \ + input_type("input_type") + \ + Optional(pointer_or_reference, default='')("pointer_or_reference1") + \ + Optional('const')('const_pointer_or_reference') + \ + Optional(pointer_or_reference, default='')("pointer_or_reference2") + +#Argument + variable name + default +argument = Group(argument_type('argument_type') + Optional(input_name) + Optional(default_value)) + +#List of arguments in parentheses with an optional 'const' on the end +arglist = LPAR + delimitedList(argument)('arg_list') + Optional(COMMA + '...')('var_args') + RPAR + +def normalise(symbol): + """ + Takes a c++ symbol or funtion and splits it into symbol and a normalised argument list. + + :Parameters: + symbol : string + A C++ symbol or function definition like ``PolyVox::Volume``, ``Volume::printAll() const`` + + :return: + a tuple consisting of two strings: ``(qualified function name or symbol, normalised argument list)`` + """ + + try: + bracket_location = symbol.index('(') + #Split the input string into everything before the opening bracket and everything else + function_name = symbol[:bracket_location] + arglist_input_string = symbol[bracket_location:] + except ValueError: + #If there's no brackets, then there's no function signature. This means the passed in symbol is just a type name + return symbol, '' + + #This is a very common signature so we'll make a special case for it. It requires no parsing anyway + if arglist_input_string.startswith('()'): + if arglist_input_string in ('()', '()=0'): + return function_name, arglist_input_string + elif arglist_input_string in ('() const ', '() const', '() const =0'): + return function_name, '() const' + + #By now we're left with something like "(blah, blah)", "(blah, blah) const" or "(blah, blah) const =0" + try: + closing_bracket_location = arglist_input_string.rindex(')') + arglist_suffix = arglist_input_string[closing_bracket_location+1:] + arglist_input_string = arglist_input_string[:closing_bracket_location+1] + except ValueError: + #This shouldn't happen. + print 'Could not find closing bracket in %s' % arglist_input_string + raise + + try: + result = arglist.parseString(arglist_input_string) + except ParseException as error: + #print symbol + #print pe + return str(error), None + else: + #Will be a list or normalised string arguments + #e.g. ['OBMol&', 'vector< int >&', 'OBBitVec&', 'OBBitVec&', 'int', 'int'] + normalised_arg_list = [] + + #Cycle through all the matched arguments + for arg in result.arg_list: + #Here is where we build up our normalised form of the argument + argument_string_list = [''] + if arg.qualifier: + argument_string_list.append(''.join((arg.qualifier,' '))) + argument_string_list.append(arg.input_type) + + #Functions can have a funny combination of *, & and const between the type and the name so build up a list of theose here: + const_pointer_ref_list = [] + const_pointer_ref_list.append(arg.pointer_or_reference1) + if arg.const_pointer_or_reference: + const_pointer_ref_list.append(''.join((' ', arg.const_pointer_or_reference, ' '))) + # same here + const_pointer_ref_list.append(arg.pointer_or_reference2) + #And combine them into a single normalised string and add them to the argument list + argument_string_list.extend(const_pointer_ref_list) + + #Finally we join our argument string and add it to our list + normalised_arg_list.append(''.join(argument_string_list)) + + #If the function contains a variable number of arguments (int foo, ...) then add them on. + if result.var_args: + normalised_arg_list.append('...') + + #Combine all the arguments and put parentheses around it + normalised_arg_list_string = ''.join(['(', ', '.join(normalised_arg_list), ')']) + + #Add a const onto the end + if 'const' in arglist_suffix: + normalised_arg_list_string += ' const' + + return function_name, normalised_arg_list_string + + #TODO Maybe this should raise an exception? + return None + +def normalise_list(list_of_symbols): + #normalise_pool = multiprocessing.Pool(multiprocessing.cpu_count() * 2) + #results = normalise_pool.map(normalise, list_of_symbols) + #normalise_pool.terminate() + results = itertools.imap(normalise, list_of_symbols) + return results diff --git a/foreignlibs/mpl/apigen.py b/foreignlibs/mpl/apigen.py new file mode 100644 index 00000000..12374096 --- /dev/null +++ b/foreignlibs/mpl/apigen.py @@ -0,0 +1,427 @@ +"""Attempt to generate templates for module reference with Sphinx + +XXX - we exclude extension modules + +To include extension modules, first identify them as valid in the +``_uri2path`` method, then handle them in the ``_parse_module`` script. + +We get functions and classes by parsing the text of .py files. +Alternatively we could import the modules for discovery, and we'd have +to do that for extension modules. This would involve changing the +``_parse_module`` method to work via import and introspection, and +might involve changing ``discover_modules`` (which determines which +files are modules, and therefore which module URIs will be passed to +``_parse_module``). + +NOTE: this is a modified version of a script originally shipped with the +PyMVPA project, which we've adapted for NIPY use. PyMVPA is an MIT-licensed +project.""" + +# Stdlib imports +import os +import re + +# Functions and classes +class ApiDocWriter(object): + ''' Class for automatic detection and parsing of API docs + to Sphinx-parsable reST format''' + + # only separating first two levels + rst_section_levels = ['*', '=', '-', '~', '^'] + + def __init__(self, + package_name, + rst_extension='.rst', + package_skip_patterns=None, + module_skip_patterns=None, + ): + ''' Initialize package for parsing + + Parameters + ---------- + package_name : string + Name of the top-level package. *package_name* must be the + name of an importable package + rst_extension : string, optional + Extension for reST files, default '.rst' + package_skip_patterns : None or sequence of {strings, regexps} + Sequence of strings giving URIs of packages to be excluded + Operates on the package path, starting at (including) the + first dot in the package path, after *package_name* - so, + if *package_name* is ``sphinx``, then ``sphinx.util`` will + result in ``.util`` being passed for earching by these + regexps. If is None, gives default. Default is: + ['\.tests$'] + module_skip_patterns : None or sequence + Sequence of strings giving URIs of modules to be excluded + Operates on the module name including preceding URI path, + back to the first dot after *package_name*. For example + ``sphinx.util.console`` results in the string to search of + ``.util.console`` + If is None, gives default. Default is: + ['\.setup$', '\._'] + ''' + if package_skip_patterns is None: + package_skip_patterns = ['\\.tests$'] + if module_skip_patterns is None: + module_skip_patterns = ['\\.setup$', '\\._'] + self.package_name = package_name + self.rst_extension = rst_extension + self.package_skip_patterns = package_skip_patterns + self.module_skip_patterns = module_skip_patterns + + def get_package_name(self): + return self._package_name + + def set_package_name(self, package_name): + ''' Set package_name + + >>> docwriter = ApiDocWriter('sphinx') + >>> import sphinx + >>> docwriter.root_path == sphinx.__path__[0] + True + >>> docwriter.package_name = 'docutils' + >>> import docutils + >>> docwriter.root_path == docutils.__path__[0] + True + ''' + # It's also possible to imagine caching the module parsing here + self._package_name = package_name + self.root_module = __import__(package_name) + self.root_path = self.root_module.__path__[0] + self.written_modules = None + + package_name = property(get_package_name, set_package_name, None, + 'get/set package_name') + + def _get_object_name(self, line): + ''' Get second token in line + >>> docwriter = ApiDocWriter('sphinx') + >>> docwriter._get_object_name(" def func(): ") + 'func' + >>> docwriter._get_object_name(" class Klass(object): ") + 'Klass' + >>> docwriter._get_object_name(" class Klass: ") + 'Klass' + ''' + name = line.split()[1].split('(')[0].strip() + # in case we have classes which are not derived from object + # ie. old style classes + return name.rstrip(':') + + def _uri2path(self, uri): + ''' Convert uri to absolute filepath + + Parameters + ---------- + uri : string + URI of python module to return path for + + Returns + ------- + path : None or string + Returns None if there is no valid path for this URI + Otherwise returns absolute file system path for URI + + Examples + -------- + >>> docwriter = ApiDocWriter('sphinx') + >>> import sphinx + >>> modpath = sphinx.__path__[0] + >>> res = docwriter._uri2path('sphinx.builder') + >>> res == os.path.join(modpath, 'builder.py') + True + >>> res = docwriter._uri2path('sphinx') + >>> res == os.path.join(modpath, '__init__.py') + True + >>> docwriter._uri2path('sphinx.does_not_exist') + + ''' + if uri == self.package_name: + return os.path.join(self.root_path, '__init__.py') + path = uri.replace('.', os.path.sep) + path = path.replace(self.package_name + os.path.sep, '') + path = os.path.join(self.root_path, path) + # XXX maybe check for extensions as well? + if os.path.exists(path + '.py'): # file + path += '.py' + elif os.path.exists(os.path.join(path, '__init__.py')): + path = os.path.join(path, '__init__.py') + else: + return None + return path + + def _path2uri(self, dirpath): + ''' Convert directory path to uri ''' + relpath = dirpath.replace(self.root_path, self.package_name) + if relpath.startswith(os.path.sep): + relpath = relpath[1:] + return relpath.replace(os.path.sep, '.') + + def _parse_module(self, uri): + ''' Parse module defined in *uri* ''' + filename = self._uri2path(uri) + if filename is None: + # nothing that we could handle here. + return ([],[]) + f = open(filename, 'rt') + functions, classes = self._parse_lines(f) + f.close() + return functions, classes + + def _parse_lines(self, linesource): + ''' Parse lines of text for functions and classes ''' + functions = [] + classes = [] + for line in linesource: + if line.startswith('def ') and line.count('('): + # exclude private stuff + name = self._get_object_name(line) + if not name.startswith('_'): + functions.append(name) + elif line.startswith('class '): + # exclude private stuff + name = self._get_object_name(line) + if not name.startswith('_'): + classes.append(name) + else: + pass + functions.sort() + classes.sort() + return functions, classes + + def generate_api_doc(self, uri): + '''Make autodoc documentation template string for a module + + Parameters + ---------- + uri : string + python location of module - e.g 'sphinx.builder' + + Returns + ------- + S : string + Contents of API doc + ''' + # get the names of all classes and functions + functions, classes = self._parse_module(uri) + if not len(functions) and not len(classes): + print 'WARNING: Empty -',uri # dbg + return '' + + # Make a shorter version of the uri that omits the package name for + # titles + uri_short = re.sub(r'^%s\.' % self.package_name,'',uri) + + ad = '.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n' + + chap_title = uri_short + ad += (chap_title+'\n'+ self.rst_section_levels[1] * len(chap_title) + + '\n\n') + + # Set the chapter title to read 'module' for all modules except for the + # main packages + if '.' in uri: + title = 'Module: :mod:`' + uri_short + '`' + else: + title = ':mod:`' + uri_short + '`' + ad += title + '\n' + self.rst_section_levels[2] * len(title) + + if len(classes): + ad += '\nInheritance diagram for ``%s``:\n\n' % uri + ad += '.. inheritance-diagram:: %s \n' % uri + ad += ' :parts: 3\n' + + ad += '\n.. automodule:: ' + uri + '\n' + ad += '\n.. currentmodule:: ' + uri + '\n' + multi_class = len(classes) > 1 + multi_fx = len(functions) > 1 + if multi_class: + ad += '\n' + 'Classes' + '\n' + \ + self.rst_section_levels[2] * 7 + '\n' + elif len(classes) and multi_fx: + ad += '\n' + 'Class' + '\n' + \ + self.rst_section_levels[2] * 5 + '\n' + for c in classes: + ad += '\n:class:`' + c + '`\n' \ + + self.rst_section_levels[multi_class + 2 ] * \ + (len(c)+9) + '\n\n' + ad += '\n.. autoclass:: ' + c + '\n' + # must NOT exclude from index to keep cross-refs working + ad += ' :members:\n' \ + ' :undoc-members:\n' \ + ' :show-inheritance:\n' \ + ' :inherited-members:\n' \ + '\n' \ + ' .. automethod:: __init__\n' + if multi_fx: + ad += '\n' + 'Functions' + '\n' + \ + self.rst_section_levels[2] * 9 + '\n\n' + elif len(functions) and multi_class: + ad += '\n' + 'Function' + '\n' + \ + self.rst_section_levels[2] * 8 + '\n\n' + for f in functions: + # must NOT exclude from index to keep cross-refs working + ad += '\n.. autofunction:: ' + uri + '.' + f + '\n\n' + return ad + + def _survives_exclude(self, matchstr, match_type): + ''' Returns True if *matchstr* does not match patterns + + ``self.package_name`` removed from front of string if present + + Examples + -------- + >>> dw = ApiDocWriter('sphinx') + >>> dw._survives_exclude('sphinx.okpkg', 'package') + True + >>> dw.package_skip_patterns.append('^\\.badpkg$') + >>> dw._survives_exclude('sphinx.badpkg', 'package') + False + >>> dw._survives_exclude('sphinx.badpkg', 'module') + True + >>> dw._survives_exclude('sphinx.badmod', 'module') + True + >>> dw.module_skip_patterns.append('^\\.badmod$') + >>> dw._survives_exclude('sphinx.badmod', 'module') + False + ''' + if match_type == 'module': + patterns = self.module_skip_patterns + elif match_type == 'package': + patterns = self.package_skip_patterns + else: + raise ValueError('Cannot interpret match type "%s"' + % match_type) + # Match to URI without package name + L = len(self.package_name) + if matchstr[:L] == self.package_name: + matchstr = matchstr[L:] + for pat in patterns: + try: + pat.search + except AttributeError: + pat = re.compile(pat) + if pat.search(matchstr): + return False + return True + + def discover_modules(self): + ''' Return module sequence discovered from ``self.package_name`` + + + Parameters + ---------- + None + + Returns + ------- + mods : sequence + Sequence of module names within ``self.package_name`` + + Examples + -------- + >>> dw = ApiDocWriter('sphinx') + >>> mods = dw.discover_modules() + >>> 'sphinx.util' in mods + True + >>> dw.package_skip_patterns.append('\.util$') + >>> 'sphinx.util' in dw.discover_modules() + False + >>> + ''' + modules = [self.package_name] + # raw directory parsing + for dirpath, dirnames, filenames in os.walk(self.root_path): + # Check directory names for packages + root_uri = self._path2uri(os.path.join(self.root_path, + dirpath)) + for dirname in dirnames[:]: # copy list - we modify inplace + package_uri = '.'.join((root_uri, dirname)) + if (self._uri2path(package_uri) and + self._survives_exclude(package_uri, 'package')): + modules.append(package_uri) + else: + dirnames.remove(dirname) + # Check filenames for modules + for filename in filenames: + module_name = filename[:-3] + module_uri = '.'.join((root_uri, module_name)) + if (self._uri2path(module_uri) and + self._survives_exclude(module_uri, 'module')): + modules.append(module_uri) + return sorted(modules) + + def write_modules_api(self, modules,outdir): + # write the list + written_modules = [] + for m in modules: + api_str = self.generate_api_doc(m) + if not api_str: + continue + # write out to file + outfile = os.path.join(outdir, + m + self.rst_extension) + fileobj = open(outfile, 'wt') + fileobj.write(api_str) + fileobj.close() + written_modules.append(m) + self.written_modules = written_modules + + def write_api_docs(self, outdir): + """Generate API reST files. + + Parameters + ---------- + outdir : string + Directory name in which to store files + We create automatic filenames for each module + + Returns + ------- + None + + Notes + ----- + Sets self.written_modules to list of written modules + """ + if not os.path.exists(outdir): + os.mkdir(outdir) + # compose list of modules + modules = self.discover_modules() + self.write_modules_api(modules,outdir) + + def write_index(self, outdir, froot='gen', relative_to=None): + """Make a reST API index file from written files + + Parameters + ---------- + path : string + Filename to write index to + outdir : string + Directory to which to write generated index file + froot : string, optional + root (filename without extension) of filename to write to + Defaults to 'gen'. We add ``self.rst_extension``. + relative_to : string + path to which written filenames are relative. This + component of the written file path will be removed from + outdir, in the generated index. Default is None, meaning, + leave path as it is. + """ + if self.written_modules is None: + raise ValueError('No modules written') + # Get full filename path + path = os.path.join(outdir, froot+self.rst_extension) + # Path written into index is relative to rootpath + if relative_to is not None: + relpath = outdir.replace(relative_to + os.path.sep, '') + else: + relpath = outdir + idx = open(path,'wt') + w = idx.write + w('.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n') + w('.. toctree::\n\n') + for f in self.written_modules: + w(' %s\n' % os.path.join(relpath,f)) + idx.close() diff --git a/foreignlibs/mpl/docscrape.py b/foreignlibs/mpl/docscrape.py new file mode 100644 index 00000000..f374b3dd --- /dev/null +++ b/foreignlibs/mpl/docscrape.py @@ -0,0 +1,497 @@ +"""Extract reference documentation from the NumPy source tree. + +""" + +import inspect +import textwrap +import re +import pydoc +from StringIO import StringIO +from warnings import warn +4 +class Reader(object): + """A line-based string reader. + + """ + def __init__(self, data): + """ + Parameters + ---------- + data : str + String with lines separated by '\n'. + + """ + if isinstance(data,list): + self._str = data + else: + self._str = data.split('\n') # store string as list of lines + + self.reset() + + def __getitem__(self, n): + return self._str[n] + + def reset(self): + self._l = 0 # current line nr + + def read(self): + if not self.eof(): + out = self[self._l] + self._l += 1 + return out + else: + return '' + + def seek_next_non_empty_line(self): + for l in self[self._l:]: + if l.strip(): + break + else: + self._l += 1 + + def eof(self): + return self._l >= len(self._str) + + def read_to_condition(self, condition_func): + start = self._l + for line in self[start:]: + if condition_func(line): + return self[start:self._l] + self._l += 1 + if self.eof(): + return self[start:self._l+1] + return [] + + def read_to_next_empty_line(self): + self.seek_next_non_empty_line() + def is_empty(line): + return not line.strip() + return self.read_to_condition(is_empty) + + def read_to_next_unindented_line(self): + def is_unindented(line): + return (line.strip() and (len(line.lstrip()) == len(line))) + return self.read_to_condition(is_unindented) + + def peek(self,n=0): + if self._l + n < len(self._str): + return self[self._l + n] + else: + return '' + + def is_empty(self): + return not ''.join(self._str).strip() + + +class NumpyDocString(object): + def __init__(self,docstring): + docstring = textwrap.dedent(docstring).split('\n') + + self._doc = Reader(docstring) + self._parsed_data = { + 'Signature': '', + 'Summary': [''], + 'Extended Summary': [], + 'Parameters': [], + 'Returns': [], + 'Raises': [], + 'Warns': [], + 'Other Parameters': [], + 'Attributes': [], + 'Methods': [], + 'See Also': [], + 'Notes': [], + 'Warnings': [], + 'References': '', + 'Examples': '', + 'index': {} + } + + self._parse() + + def __getitem__(self,key): + return self._parsed_data[key] + + def __setitem__(self,key,val): + if not self._parsed_data.has_key(key): + warn("Unknown section %s" % key) + else: + self._parsed_data[key] = val + + def _is_at_section(self): + self._doc.seek_next_non_empty_line() + + if self._doc.eof(): + return False + + l1 = self._doc.peek().strip() # e.g. Parameters + + if l1.startswith('.. index::'): + return True + + l2 = self._doc.peek(1).strip() # ---------- or ========== + return l2.startswith('-'*len(l1)) or l2.startswith('='*len(l1)) + + def _strip(self,doc): + i = 0 + j = 0 + for i,line in enumerate(doc): + if line.strip(): break + + for j,line in enumerate(doc[::-1]): + if line.strip(): break + + return doc[i:len(doc)-j] + + def _read_to_next_section(self): + section = self._doc.read_to_next_empty_line() + + while not self._is_at_section() and not self._doc.eof(): + if not self._doc.peek(-1).strip(): # previous line was empty + section += [''] + + section += self._doc.read_to_next_empty_line() + + return section + + def _read_sections(self): + while not self._doc.eof(): + data = self._read_to_next_section() + name = data[0].strip() + + if name.startswith('..'): # index section + yield name, data[1:] + elif len(data) < 2: + yield StopIteration + else: + yield name, self._strip(data[2:]) + + def _parse_param_list(self,content): + r = Reader(content) + params = [] + while not r.eof(): + header = r.read().strip() + if ' : ' in header: + arg_name, arg_type = header.split(' : ')[:2] + else: + arg_name, arg_type = header, '' + + desc = r.read_to_next_unindented_line() + desc = dedent_lines(desc) + + params.append((arg_name,arg_type,desc)) + + return params + + + _name_rgx = re.compile(r"^\s*(:(?P\w+):`(?P[a-zA-Z0-9_.-]+)`|" + r" (?P[a-zA-Z0-9_.-]+))\s*", re.X) + def _parse_see_also(self, content): + """ + func_name : Descriptive text + continued text + another_func_name : Descriptive text + func_name1, func_name2, :meth:`func_name`, func_name3 + + """ + items = [] + + def parse_item_name(text): + """Match ':role:`name`' or 'name'""" + m = self._name_rgx.match(text) + if m: + g = m.groups() + if g[1] is None: + return g[3], None + else: + return g[2], g[1] + raise ValueError("%s is not a item name" % text) + + def push_item(name, rest): + if not name: + return + name, role = parse_item_name(name) + items.append((name, list(rest), role)) + del rest[:] + + current_func = None + rest = [] + + for line in content: + if not line.strip(): continue + + m = self._name_rgx.match(line) + if m and line[m.end():].strip().startswith(':'): + push_item(current_func, rest) + current_func, line = line[:m.end()], line[m.end():] + rest = [line.split(':', 1)[1].strip()] + if not rest[0]: + rest = [] + elif not line.startswith(' '): + push_item(current_func, rest) + current_func = None + if ',' in line: + for func in line.split(','): + push_item(func, []) + elif line.strip(): + current_func = line + elif current_func is not None: + rest.append(line.strip()) + push_item(current_func, rest) + return items + + def _parse_index(self, section, content): + """ + .. index: default + :refguide: something, else, and more + + """ + def strip_each_in(lst): + return [s.strip() for s in lst] + + out = {} + section = section.split('::') + if len(section) > 1: + out['default'] = strip_each_in(section[1].split(','))[0] + for line in content: + line = line.split(':') + if len(line) > 2: + out[line[1]] = strip_each_in(line[2].split(',')) + return out + + def _parse_summary(self): + """Grab signature (if given) and summary""" + if self._is_at_section(): + return + + summary = self._doc.read_to_next_empty_line() + summary_str = " ".join([s.strip() for s in summary]).strip() + if re.compile('^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str): + self['Signature'] = summary_str + if not self._is_at_section(): + self['Summary'] = self._doc.read_to_next_empty_line() + else: + self['Summary'] = summary + + if not self._is_at_section(): + self['Extended Summary'] = self._read_to_next_section() + + def _parse(self): + self._doc.reset() + self._parse_summary() + + for (section,content) in self._read_sections(): + if not section.startswith('..'): + section = ' '.join([s.capitalize() for s in section.split(' ')]) + if section in ('Parameters', 'Attributes', 'Methods', + 'Returns', 'Raises', 'Warns'): + self[section] = self._parse_param_list(content) + elif section.startswith('.. index::'): + self['index'] = self._parse_index(section, content) + elif section == 'See Also': + self['See Also'] = self._parse_see_also(content) + else: + self[section] = content + + # string conversion routines + + def _str_header(self, name, symbol='-'): + return [name, len(name)*symbol] + + def _str_indent(self, doc, indent=4): + out = [] + for line in doc: + out += [' '*indent + line] + return out + + def _str_signature(self): + if self['Signature']: + return [self['Signature'].replace('*','\*')] + [''] + else: + return [''] + + def _str_summary(self): + if self['Summary']: + return self['Summary'] + [''] + else: + return [] + + def _str_extended_summary(self): + if self['Extended Summary']: + return self['Extended Summary'] + [''] + else: + return [] + + def _str_param_list(self, name): + out = [] + if self[name]: + out += self._str_header(name) + for param,param_type,desc in self[name]: + out += ['%s : %s' % (param, param_type)] + out += self._str_indent(desc) + out += [''] + return out + + def _str_section(self, name): + out = [] + if self[name]: + out += self._str_header(name) + out += self[name] + out += [''] + return out + + def _str_see_also(self, func_role): + if not self['See Also']: return [] + out = [] + out += self._str_header("See Also") + last_had_desc = True + for func, desc, role in self['See Also']: + if role: + link = ':%s:`%s`' % (role, func) + elif func_role: + link = ':%s:`%s`' % (func_role, func) + else: + link = "`%s`_" % func + if desc or last_had_desc: + out += [''] + out += [link] + else: + out[-1] += ", %s" % link + if desc: + out += self._str_indent([' '.join(desc)]) + last_had_desc = True + else: + last_had_desc = False + out += [''] + return out + + def _str_index(self): + idx = self['index'] + out = [] + out += ['.. index:: %s' % idx.get('default','')] + for section, references in idx.iteritems(): + if section == 'default': + continue + out += [' :%s: %s' % (section, ', '.join(references))] + return out + + def __str__(self, func_role=''): + out = [] + out += self._str_signature() + out += self._str_summary() + out += self._str_extended_summary() + for param_list in ('Parameters','Returns','Raises'): + out += self._str_param_list(param_list) + out += self._str_section('Warnings') + out += self._str_see_also(func_role) + for s in ('Notes','References','Examples'): + out += self._str_section(s) + out += self._str_index() + return '\n'.join(out) + + +def indent(str,indent=4): + indent_str = ' '*indent + if str is None: + return indent_str + lines = str.split('\n') + return '\n'.join(indent_str + l for l in lines) + +def dedent_lines(lines): + """Deindent a list of lines maximally""" + return textwrap.dedent("\n".join(lines)).split("\n") + +def header(text, style='-'): + return text + '\n' + style*len(text) + '\n' + + +class FunctionDoc(NumpyDocString): + def __init__(self, func, role='func', doc=None): + self._f = func + self._role = role # e.g. "func" or "meth" + if doc is None: + doc = inspect.getdoc(func) or '' + try: + NumpyDocString.__init__(self, doc) + except ValueError, e: + print '*'*78 + print "ERROR: '%s' while parsing `%s`" % (e, self._f) + print '*'*78 + #print "Docstring follows:" + #print doclines + #print '='*78 + + if not self['Signature']: + func, func_name = self.get_func() + try: + # try to read signature + argspec = inspect.getargspec(func) + argspec = inspect.formatargspec(*argspec) + argspec = argspec.replace('*','\*') + signature = '%s%s' % (func_name, argspec) + except TypeError, e: + signature = '%s()' % func_name + self['Signature'] = signature + + def get_func(self): + func_name = getattr(self._f, '__name__', self.__class__.__name__) + if inspect.isclass(self._f): + func = getattr(self._f, '__call__', self._f.__init__) + else: + func = self._f + return func, func_name + + def __str__(self): + out = '' + + func, func_name = self.get_func() + signature = self['Signature'].replace('*', '\*') + + roles = {'func': 'function', + 'meth': 'method'} + + if self._role: + if not roles.has_key(self._role): + print "Warning: invalid role %s" % self._role + out += '.. %s:: %s\n \n\n' % (roles.get(self._role,''), + func_name) + + out += super(FunctionDoc, self).__str__(func_role=self._role) + return out + + +class ClassDoc(NumpyDocString): + def __init__(self,cls,modulename='',func_doc=FunctionDoc,doc=None): + if not inspect.isclass(cls): + raise ValueError("Initialise using a class. Got %r" % cls) + self._cls = cls + + if modulename and not modulename.endswith('.'): + modulename += '.' + self._mod = modulename + self._name = cls.__name__ + self._func_doc = func_doc + + if doc is None: + doc = pydoc.getdoc(cls) + + NumpyDocString.__init__(self, doc) + + @property + def methods(self): + return [name for name,func in inspect.getmembers(self._cls) + if not name.startswith('_') and callable(func)] + + def __str__(self): + out = '' + out += super(ClassDoc, self).__str__() + out += "\n\n" + + #for m in self.methods: + # print "Parsing `%s`" % m + # out += str(self._func_doc(getattr(self._cls,m), 'meth')) + '\n\n' + # out += '.. index::\n single: %s; %s\n\n' % (self._name, m) + + return out + + diff --git a/foreignlibs/mpl/docscrape_sphinx.py b/foreignlibs/mpl/docscrape_sphinx.py new file mode 100644 index 00000000..77ed271b --- /dev/null +++ b/foreignlibs/mpl/docscrape_sphinx.py @@ -0,0 +1,136 @@ +import re, inspect, textwrap, pydoc +from docscrape import NumpyDocString, FunctionDoc, ClassDoc + +class SphinxDocString(NumpyDocString): + # string conversion routines + def _str_header(self, name, symbol='`'): + return ['.. rubric:: ' + name, ''] + + def _str_field_list(self, name): + return [':' + name + ':'] + + def _str_indent(self, doc, indent=4): + out = [] + for line in doc: + out += [' '*indent + line] + return out + + def _str_signature(self): + return [''] + if self['Signature']: + return ['``%s``' % self['Signature']] + [''] + else: + return [''] + + def _str_summary(self): + return self['Summary'] + [''] + + def _str_extended_summary(self): + return self['Extended Summary'] + [''] + + def _str_param_list(self, name): + out = [] + if self[name]: + out += self._str_field_list(name) + out += [''] + for param,param_type,desc in self[name]: + out += self._str_indent(['**%s** : %s' % (param.strip(), + param_type)]) + out += [''] + out += self._str_indent(desc,8) + out += [''] + return out + + def _str_section(self, name): + out = [] + if self[name]: + out += self._str_header(name) + out += [''] + content = textwrap.dedent("\n".join(self[name])).split("\n") + out += content + out += [''] + return out + + def _str_see_also(self, func_role): + out = [] + if self['See Also']: + see_also = super(SphinxDocString, self)._str_see_also(func_role) + out = ['.. seealso::', ''] + out += self._str_indent(see_also[2:]) + return out + + def _str_warnings(self): + out = [] + if self['Warnings']: + out = ['.. warning::', ''] + out += self._str_indent(self['Warnings']) + return out + + def _str_index(self): + idx = self['index'] + out = [] + if len(idx) == 0: + return out + + out += ['.. index:: %s' % idx.get('default','')] + for section, references in idx.iteritems(): + if section == 'default': + continue + elif section == 'refguide': + out += [' single: %s' % (', '.join(references))] + else: + out += [' %s: %s' % (section, ','.join(references))] + return out + + def _str_references(self): + out = [] + if self['References']: + out += self._str_header('References') + if isinstance(self['References'], str): + self['References'] = [self['References']] + out.extend(self['References']) + out += [''] + return out + + def __str__(self, indent=0, func_role="obj"): + out = [] + out += self._str_signature() + out += self._str_index() + [''] + out += self._str_summary() + out += self._str_extended_summary() + for param_list in ('Parameters', 'Attributes', 'Methods', + 'Returns','Raises'): + out += self._str_param_list(param_list) + out += self._str_warnings() + out += self._str_see_also(func_role) + out += self._str_section('Notes') + out += self._str_references() + out += self._str_section('Examples') + out = self._str_indent(out,indent) + return '\n'.join(out) + +class SphinxFunctionDoc(SphinxDocString, FunctionDoc): + pass + +class SphinxClassDoc(SphinxDocString, ClassDoc): + pass + +def get_doc_object(obj, what=None, doc=None): + if what is None: + if inspect.isclass(obj): + what = 'class' + elif inspect.ismodule(obj): + what = 'module' + elif callable(obj): + what = 'function' + else: + what = 'object' + if what == 'class': + return SphinxClassDoc(obj, '', func_doc=SphinxFunctionDoc, doc=doc) + elif what in ('function', 'method'): + return SphinxFunctionDoc(obj, '', doc=doc) + else: + if doc is None: + doc = pydoc.getdoc(obj) + return SphinxDocString(doc) + diff --git a/foreignlibs/mpl/inheritance_diagram.py b/foreignlibs/mpl/inheritance_diagram.py new file mode 100644 index 00000000..407fc13f --- /dev/null +++ b/foreignlibs/mpl/inheritance_diagram.py @@ -0,0 +1,407 @@ +""" +Defines a docutils directive for inserting inheritance diagrams. + +Provide the directive with one or more classes or modules (separated +by whitespace). For modules, all of the classes in that module will +be used. + +Example:: + + Given the following classes: + + class A: pass + class B(A): pass + class C(A): pass + class D(B, C): pass + class E(B): pass + + .. inheritance-diagram: D E + + Produces a graph like the following: + + A + / \ + B C + / \ / + E D + +The graph is inserted as a PNG+image map into HTML and a PDF in +LaTeX. +""" + +import inspect +import os +import re +import subprocess +try: + from hashlib import md5 +except ImportError: + from md5 import md5 + +from docutils.nodes import Body, Element +from docutils.parsers.rst import directives +from sphinx.roles import xfileref_role + +def my_import(name): + """Module importer - taken from the python documentation. + + This function allows importing names with dots in them.""" + + mod = __import__(name) + components = name.split('.') + for comp in components[1:]: + mod = getattr(mod, comp) + return mod + +class DotException(Exception): + pass + +class InheritanceGraph(object): + """ + Given a list of classes, determines the set of classes that + they inherit from all the way to the root "object", and then + is able to generate a graphviz dot graph from them. + """ + def __init__(self, class_names, show_builtins=False): + """ + *class_names* is a list of child classes to show bases from. + + If *show_builtins* is True, then Python builtins will be shown + in the graph. + """ + self.class_names = class_names + self.classes = self._import_classes(class_names) + self.all_classes = self._all_classes(self.classes) + if len(self.all_classes) == 0: + raise ValueError("No classes found for inheritance diagram") + self.show_builtins = show_builtins + + py_sig_re = re.compile(r'''^([\w.]*\.)? # class names + (\w+) \s* $ # optionally arguments + ''', re.VERBOSE) + + def _import_class_or_module(self, name): + """ + Import a class using its fully-qualified *name*. + """ + try: + path, base = self.py_sig_re.match(name).groups() + except: + raise ValueError( + "Invalid class or module '%s' specified for inheritance diagram" % name) + fullname = (path or '') + base + path = (path and path.rstrip('.')) + if not path: + path = base + try: + module = __import__(path, None, None, []) + # We must do an import of the fully qualified name. Otherwise if a + # subpackage 'a.b' is requested where 'import a' does NOT provide + # 'a.b' automatically, then 'a.b' will not be found below. This + # second call will force the equivalent of 'import a.b' to happen + # after the top-level import above. + my_import(fullname) + + except ImportError: + raise ValueError( + "Could not import class or module '%s' specified for inheritance diagram" % name) + + try: + todoc = module + for comp in fullname.split('.')[1:]: + todoc = getattr(todoc, comp) + except AttributeError: + raise ValueError( + "Could not find class or module '%s' specified for inheritance diagram" % name) + + # If a class, just return it + if inspect.isclass(todoc): + return [todoc] + elif inspect.ismodule(todoc): + classes = [] + for cls in todoc.__dict__.values(): + if inspect.isclass(cls) and cls.__module__ == todoc.__name__: + classes.append(cls) + return classes + raise ValueError( + "'%s' does not resolve to a class or module" % name) + + def _import_classes(self, class_names): + """ + Import a list of classes. + """ + classes = [] + for name in class_names: + classes.extend(self._import_class_or_module(name)) + return classes + + def _all_classes(self, classes): + """ + Return a list of all classes that are ancestors of *classes*. + """ + all_classes = {} + + def recurse(cls): + all_classes[cls] = None + for c in cls.__bases__: + if c not in all_classes: + recurse(c) + + for cls in classes: + recurse(cls) + + return all_classes.keys() + + def class_name(self, cls, parts=0): + """ + Given a class object, return a fully-qualified name. This + works for things I've tested in matplotlib so far, but may not + be completely general. + """ + module = cls.__module__ + if module == '__builtin__': + fullname = cls.__name__ + else: + fullname = "%s.%s" % (module, cls.__name__) + if parts == 0: + return fullname + name_parts = fullname.split('.') + return '.'.join(name_parts[-parts:]) + + def get_all_class_names(self): + """ + Get all of the class names involved in the graph. + """ + return [self.class_name(x) for x in self.all_classes] + + # These are the default options for graphviz + default_graph_options = { + "rankdir": "LR", + "size": '"8.0, 12.0"' + } + default_node_options = { + "shape": "box", + "fontsize": 10, + "height": 0.25, + "fontname": "Vera Sans, DejaVu Sans, Liberation Sans, Arial, Helvetica, sans", + "style": '"setlinewidth(0.5)"' + } + default_edge_options = { + "arrowsize": 0.5, + "style": '"setlinewidth(0.5)"' + } + + def _format_node_options(self, options): + return ','.join(["%s=%s" % x for x in options.items()]) + def _format_graph_options(self, options): + return ''.join(["%s=%s;\n" % x for x in options.items()]) + + def generate_dot(self, fd, name, parts=0, urls={}, + graph_options={}, node_options={}, + edge_options={}): + """ + Generate a graphviz dot graph from the classes that + were passed in to __init__. + + *fd* is a Python file-like object to write to. + + *name* is the name of the graph + + *urls* is a dictionary mapping class names to http urls + + *graph_options*, *node_options*, *edge_options* are + dictionaries containing key/value pairs to pass on as graphviz + properties. + """ + g_options = self.default_graph_options.copy() + g_options.update(graph_options) + n_options = self.default_node_options.copy() + n_options.update(node_options) + e_options = self.default_edge_options.copy() + e_options.update(edge_options) + + fd.write('digraph %s {\n' % name) + fd.write(self._format_graph_options(g_options)) + + for cls in self.all_classes: + if not self.show_builtins and cls in __builtins__.values(): + continue + + name = self.class_name(cls, parts) + + # Write the node + this_node_options = n_options.copy() + url = urls.get(self.class_name(cls)) + if url is not None: + this_node_options['URL'] = '"%s"' % url + fd.write(' "%s" [%s];\n' % + (name, self._format_node_options(this_node_options))) + + # Write the edges + for base in cls.__bases__: + if not self.show_builtins and base in __builtins__.values(): + continue + + base_name = self.class_name(base, parts) + fd.write(' "%s" -> "%s" [%s];\n' % + (base_name, name, + self._format_node_options(e_options))) + fd.write('}\n') + + def run_dot(self, args, name, parts=0, urls={}, + graph_options={}, node_options={}, edge_options={}): + """ + Run graphviz 'dot' over this graph, returning whatever 'dot' + writes to stdout. + + *args* will be passed along as commandline arguments. + + *name* is the name of the graph + + *urls* is a dictionary mapping class names to http urls + + Raises DotException for any of the many os and + installation-related errors that may occur. + """ + try: + dot = subprocess.Popen(['dot'] + list(args), + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + close_fds=True) + except OSError: + raise DotException("Could not execute 'dot'. Are you sure you have 'graphviz' installed?") + except ValueError: + raise DotException("'dot' called with invalid arguments") + except: + raise DotException("Unexpected error calling 'dot'") + + self.generate_dot(dot.stdin, name, parts, urls, graph_options, + node_options, edge_options) + dot.stdin.close() + result = dot.stdout.read() + returncode = dot.wait() + if returncode != 0: + raise DotException("'dot' returned the errorcode %d" % returncode) + return result + +class inheritance_diagram(Body, Element): + """ + A docutils node to use as a placeholder for the inheritance + diagram. + """ + pass + +def inheritance_diagram_directive(name, arguments, options, content, lineno, + content_offset, block_text, state, + state_machine): + """ + Run when the inheritance_diagram directive is first encountered. + """ + node = inheritance_diagram() + + class_names = arguments + + # Create a graph starting with the list of classes + graph = InheritanceGraph(class_names) + + # Create xref nodes for each target of the graph's image map and + # add them to the doc tree so that Sphinx can resolve the + # references to real URLs later. These nodes will eventually be + # removed from the doctree after we're done with them. + for name in graph.get_all_class_names(): + refnodes, x = xfileref_role( + 'class', ':class:`%s`' % name, name, 0, state) + node.extend(refnodes) + # Store the graph object so we can use it to generate the + # dot file later + node['graph'] = graph + # Store the original content for use as a hash + node['parts'] = options.get('parts', 0) + node['content'] = " ".join(class_names) + return [node] + +def get_graph_hash(node): + return md5(node['content'] + str(node['parts'])).hexdigest()[-10:] + +def html_output_graph(self, node): + """ + Output the graph for HTML. This will insert a PNG with clickable + image map. + """ + graph = node['graph'] + parts = node['parts'] + + graph_hash = get_graph_hash(node) + name = "inheritance%s" % graph_hash + path = '_images' + dest_path = os.path.join(setup.app.builder.outdir, path) + if not os.path.exists(dest_path): + os.makedirs(dest_path) + png_path = os.path.join(dest_path, name + ".png") + path = setup.app.builder.imgpath + + # Create a mapping from fully-qualified class names to URLs. + urls = {} + for child in node: + if child.get('refuri') is not None: + urls[child['reftitle']] = child.get('refuri') + elif child.get('refid') is not None: + urls[child['reftitle']] = '#' + child.get('refid') + + # These arguments to dot will save a PNG file to disk and write + # an HTML image map to stdout. + image_map = graph.run_dot(['-Tpng', '-o%s' % png_path, '-Tcmapx'], + name, parts, urls) + return ('%s' % + (path, name, name, image_map)) + +def latex_output_graph(self, node): + """ + Output the graph for LaTeX. This will insert a PDF. + """ + graph = node['graph'] + parts = node['parts'] + + graph_hash = get_graph_hash(node) + name = "inheritance%s" % graph_hash + dest_path = os.path.abspath(os.path.join(setup.app.builder.outdir, '_images')) + if not os.path.exists(dest_path): + os.makedirs(dest_path) + pdf_path = os.path.abspath(os.path.join(dest_path, name + ".pdf")) + + graph.run_dot(['-Tpdf', '-o%s' % pdf_path], + name, parts, graph_options={'size': '"6.0,6.0"'}) + return '\n\\includegraphics{%s}\n\n' % pdf_path + +def visit_inheritance_diagram(inner_func): + """ + This is just a wrapper around html/latex_output_graph to make it + easier to handle errors and insert warnings. + """ + def visitor(self, node): + try: + content = inner_func(self, node) + except DotException, e: + # Insert the exception as a warning in the document + warning = self.document.reporter.warning(str(e), line=node.line) + warning.parent = node + node.children = [warning] + else: + source = self.document.attributes['source'] + self.body.append(content) + node.children = [] + return visitor + +def do_nothing(self, node): + pass + +def setup(app): + setup.app = app + setup.confdir = app.confdir + + app.add_node( + inheritance_diagram, + latex=(visit_inheritance_diagram(latex_output_graph), do_nothing), + html=(visit_inheritance_diagram(html_output_graph), do_nothing)) + app.add_directive( + 'inheritance-diagram', inheritance_diagram_directive, + False, (1, 100, 0), parts = directives.nonnegative_int) diff --git a/foreignlibs/mpl/ipython_console_highlighting.py b/foreignlibs/mpl/ipython_console_highlighting.py new file mode 100644 index 00000000..217b779d --- /dev/null +++ b/foreignlibs/mpl/ipython_console_highlighting.py @@ -0,0 +1,114 @@ +"""reST directive for syntax-highlighting ipython interactive sessions. + +XXX - See what improvements can be made based on the new (as of Sept 2009) +'pycon' lexer for the python console. At the very least it will give better +highlighted tracebacks. +""" + +#----------------------------------------------------------------------------- +# Needed modules + +# Standard library +import re + +# Third party +from pygments.lexer import Lexer, do_insertions +from pygments.lexers.agile import (PythonConsoleLexer, PythonLexer, + PythonTracebackLexer) +from pygments.token import Comment, Generic + +from sphinx import highlighting + +#----------------------------------------------------------------------------- +# Global constants +line_re = re.compile('.*?\n') + +#----------------------------------------------------------------------------- +# Code begins - classes and functions + +class IPythonConsoleLexer(Lexer): + """ + For IPython console output or doctests, such as: + + .. sourcecode:: ipython + + In [1]: a = 'foo' + + In [2]: a + Out[2]: 'foo' + + In [3]: print a + foo + + In [4]: 1 / 0 + + Notes: + + - Tracebacks are not currently supported. + + - It assumes the default IPython prompts, not customized ones. + """ + + name = 'IPython console session' + aliases = ['ipython'] + mimetypes = ['text/x-ipython-console'] + input_prompt = re.compile("(In \[[0-9]+\]: )|( \.\.\.+:)") + output_prompt = re.compile("(Out\[[0-9]+\]: )|( \.\.\.+:)") + continue_prompt = re.compile(" \.\.\.+:") + tb_start = re.compile("\-+") + + def get_tokens_unprocessed(self, text): + pylexer = PythonLexer(**self.options) + tblexer = PythonTracebackLexer(**self.options) + + curcode = '' + insertions = [] + for match in line_re.finditer(text): + line = match.group() + input_prompt = self.input_prompt.match(line) + continue_prompt = self.continue_prompt.match(line.rstrip()) + output_prompt = self.output_prompt.match(line) + if line.startswith("#"): + insertions.append((len(curcode), + [(0, Comment, line)])) + elif input_prompt is not None: + insertions.append((len(curcode), + [(0, Generic.Prompt, input_prompt.group())])) + curcode += line[input_prompt.end():] + elif continue_prompt is not None: + insertions.append((len(curcode), + [(0, Generic.Prompt, continue_prompt.group())])) + curcode += line[continue_prompt.end():] + elif output_prompt is not None: + # Use the 'error' token for output. We should probably make + # our own token, but error is typicaly in a bright color like + # red, so it works fine for our output prompts. + insertions.append((len(curcode), + [(0, Generic.Error, output_prompt.group())])) + curcode += line[output_prompt.end():] + else: + if curcode: + for item in do_insertions(insertions, + pylexer.get_tokens_unprocessed(curcode)): + yield item + curcode = '' + insertions = [] + yield match.start(), Generic.Output, line + if curcode: + for item in do_insertions(insertions, + pylexer.get_tokens_unprocessed(curcode)): + yield item + + +def setup(app): + """Setup as a sphinx extension.""" + + # This is only a lexer, so adding it below to pygments appears sufficient. + # But if somebody knows that the right API usage should be to do that via + # sphinx, by all means fix it here. At least having this setup.py + # suppresses the sphinx warning we'd get without it. + pass + +#----------------------------------------------------------------------------- +# Register the extension as a valid pygments lexer +highlighting.lexers['ipython'] = IPythonConsoleLexer() diff --git a/foreignlibs/mpl/numpydoc.py b/foreignlibs/mpl/numpydoc.py new file mode 100644 index 00000000..ff6c44c5 --- /dev/null +++ b/foreignlibs/mpl/numpydoc.py @@ -0,0 +1,116 @@ +""" +======== +numpydoc +======== + +Sphinx extension that handles docstrings in the Numpy standard format. [1] + +It will: + +- Convert Parameters etc. sections to field lists. +- Convert See Also section to a See also entry. +- Renumber references. +- Extract the signature from the docstring, if it can't be determined otherwise. + +.. [1] http://projects.scipy.org/scipy/numpy/wiki/CodingStyleGuidelines#docstring-standard + +""" + +import os, re, pydoc +from docscrape_sphinx import get_doc_object, SphinxDocString +import inspect + +def mangle_docstrings(app, what, name, obj, options, lines, + reference_offset=[0]): + if what == 'module': + # Strip top title + title_re = re.compile(r'^\s*[#*=]{4,}\n[a-z0-9 -]+\n[#*=]{4,}\s*', + re.I|re.S) + lines[:] = title_re.sub('', "\n".join(lines)).split("\n") + else: + doc = get_doc_object(obj, what, "\n".join(lines)) + lines[:] = str(doc).split("\n") + + if app.config.numpydoc_edit_link and hasattr(obj, '__name__') and \ + obj.__name__: + if hasattr(obj, '__module__'): + v = dict(full_name="%s.%s" % (obj.__module__, obj.__name__)) + else: + v = dict(full_name=obj.__name__) + lines += ['', '.. htmlonly::', ''] + lines += [' %s' % x for x in + (app.config.numpydoc_edit_link % v).split("\n")] + + # replace reference numbers so that there are no duplicates + references = [] + for l in lines: + l = l.strip() + if l.startswith('.. ['): + try: + references.append(int(l[len('.. ['):l.index(']')])) + except ValueError: + print "WARNING: invalid reference in %s docstring" % name + + # Start renaming from the biggest number, otherwise we may + # overwrite references. + references.sort() + if references: + for i, line in enumerate(lines): + for r in references: + new_r = reference_offset[0] + r + lines[i] = lines[i].replace('[%d]_' % r, + '[%d]_' % new_r) + lines[i] = lines[i].replace('.. [%d]' % r, + '.. [%d]' % new_r) + + reference_offset[0] += len(references) + +def mangle_signature(app, what, name, obj, options, sig, retann): + # Do not try to inspect classes that don't define `__init__` + if (inspect.isclass(obj) and + 'initializes x; see ' in pydoc.getdoc(obj.__init__)): + return '', '' + + if not (callable(obj) or hasattr(obj, '__argspec_is_invalid_')): return + if not hasattr(obj, '__doc__'): return + + doc = SphinxDocString(pydoc.getdoc(obj)) + if doc['Signature']: + sig = re.sub("^[^(]*", "", doc['Signature']) + return sig, '' + +def initialize(app): + try: + app.connect('autodoc-process-signature', mangle_signature) + except: + monkeypatch_sphinx_ext_autodoc() + +def setup(app, get_doc_object_=get_doc_object): + global get_doc_object + get_doc_object = get_doc_object_ + + app.connect('autodoc-process-docstring', mangle_docstrings) + app.connect('builder-inited', initialize) + app.add_config_value('numpydoc_edit_link', None, True) + +#------------------------------------------------------------------------------ +# Monkeypatch sphinx.ext.autodoc to accept argspecless autodocs (Sphinx < 0.5) +#------------------------------------------------------------------------------ + +def monkeypatch_sphinx_ext_autodoc(): + global _original_format_signature + import sphinx.ext.autodoc + + if sphinx.ext.autodoc.format_signature is our_format_signature: + return + + print "[numpydoc] Monkeypatching sphinx.ext.autodoc ..." + _original_format_signature = sphinx.ext.autodoc.format_signature + sphinx.ext.autodoc.format_signature = our_format_signature + +def our_format_signature(what, obj): + r = mangle_signature(None, what, None, obj, None, None, None) + if r is not None: + return r[0] + else: + return _original_format_signature(what, obj) diff --git a/foreignlibs/mpl/plot_directive.py b/foreignlibs/mpl/plot_directive.py new file mode 100644 index 00000000..86c65b5e --- /dev/null +++ b/foreignlibs/mpl/plot_directive.py @@ -0,0 +1,773 @@ +""" +A directive for including a matplotlib plot in a Sphinx document. + +By default, in HTML output, `plot` will include a .png file with a +link to a high-res .png and .pdf. In LaTeX output, it will include a +.pdf. + +The source code for the plot may be included in one of three ways: + + 1. **A path to a source file** as the argument to the directive:: + + .. plot:: path/to/plot.py + + When a path to a source file is given, the content of the + directive may optionally contain a caption for the plot:: + + .. plot:: path/to/plot.py + + This is the caption for the plot + + Additionally, one my specify the name of a function to call (with + no arguments) immediately after importing the module:: + + .. plot:: path/to/plot.py plot_function1 + + 2. Included as **inline content** to the directive:: + + .. plot:: + + import matplotlib.pyplot as plt + import matplotlib.image as mpimg + import numpy as np + img = mpimg.imread('_static/stinkbug.png') + imgplot = plt.imshow(img) + + 3. Using **doctest** syntax:: + + .. plot:: + A plotting example: + >>> import matplotlib.pyplot as plt + >>> plt.plot([1,2,3], [4,5,6]) + +Options +------- + +The ``plot`` directive supports the following options: + + format : {'python', 'doctest'} + Specify the format of the input + + include-source : bool + Whether to display the source code. The default can be changed + using the `plot_include_source` variable in conf.py + + encoding : str + If this source file is in a non-UTF8 or non-ASCII encoding, + the encoding must be specified using the `:encoding:` option. + The encoding will not be inferred using the ``-*- coding -*-`` + metacomment. + + context : bool + If provided, the code will be run in the context of all + previous plot directives for which the `:context:` option was + specified. This only applies to inline code plot directives, + not those run from files. + + nofigs : bool + If specified, the code block will be run, but no figures will + be inserted. This is usually useful with the ``:context:`` + option. + +Additionally, this directive supports all of the options of the +`image` directive, except for `target` (since plot will add its own +target). These include `alt`, `height`, `width`, `scale`, `align` and +`class`. + +Configuration options +--------------------- + +The plot directive has the following configuration options: + + plot_include_source + Default value for the include-source option + + plot_pre_code + Code that should be executed before each plot. + + plot_basedir + Base directory, to which ``plot::`` file names are relative + to. (If None or empty, file names are relative to the + directoly where the file containing the directive is.) + + plot_formats + File formats to generate. List of tuples or strings:: + + [(suffix, dpi), suffix, ...] + + that determine the file format and the DPI. For entries whose + DPI was omitted, sensible defaults are chosen. + + plot_html_show_formats + Whether to show links to the files in HTML. + + plot_rcparams + A dictionary containing any non-standard rcParams that should + be applied before each plot. + +""" + +import sys, os, glob, shutil, imp, warnings, cStringIO, re, textwrap, \ + traceback, exceptions + +from docutils.parsers.rst import directives +from docutils import nodes +from docutils.parsers.rst.directives.images import Image +align = Image.align +import sphinx + +sphinx_version = sphinx.__version__.split(".") +# The split is necessary for sphinx beta versions where the string is +# '6b1' +sphinx_version = tuple([int(re.split('[a-z]', x)[0]) + for x in sphinx_version[:2]]) + +try: + # Sphinx depends on either Jinja or Jinja2 + import jinja2 + def format_template(template, **kw): + return jinja2.Template(template).render(**kw) +except ImportError: + import jinja + def format_template(template, **kw): + return jinja.from_string(template, **kw) + +import matplotlib +import matplotlib.cbook as cbook +matplotlib.use('Agg') +import matplotlib.pyplot as plt +from matplotlib import _pylab_helpers + +__version__ = 2 + +#------------------------------------------------------------------------------ +# Relative pathnames +#------------------------------------------------------------------------------ + +# os.path.relpath is new in Python 2.6 +try: + from os.path import relpath +except ImportError: + # Copied from Python 2.7 + if 'posix' in sys.builtin_module_names: + def relpath(path, start=os.path.curdir): + """Return a relative version of a path""" + from os.path import sep, curdir, join, abspath, commonprefix, \ + pardir + + if not path: + raise ValueError("no path specified") + + start_list = abspath(start).split(sep) + path_list = abspath(path).split(sep) + + # Work out how much of the filepath is shared by start and path. + i = len(commonprefix([start_list, path_list])) + + rel_list = [pardir] * (len(start_list)-i) + path_list[i:] + if not rel_list: + return curdir + return join(*rel_list) + elif 'nt' in sys.builtin_module_names: + def relpath(path, start=os.path.curdir): + """Return a relative version of a path""" + from os.path import sep, curdir, join, abspath, commonprefix, \ + pardir, splitunc + + if not path: + raise ValueError("no path specified") + start_list = abspath(start).split(sep) + path_list = abspath(path).split(sep) + if start_list[0].lower() != path_list[0].lower(): + unc_path, rest = splitunc(path) + unc_start, rest = splitunc(start) + if bool(unc_path) ^ bool(unc_start): + raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)" + % (path, start)) + else: + raise ValueError("path is on drive %s, start on drive %s" + % (path_list[0], start_list[0])) + # Work out how much of the filepath is shared by start and path. + for i in range(min(len(start_list), len(path_list))): + if start_list[i].lower() != path_list[i].lower(): + break + else: + i += 1 + + rel_list = [pardir] * (len(start_list)-i) + path_list[i:] + if not rel_list: + return curdir + return join(*rel_list) + else: + raise RuntimeError("Unsupported platform (no relpath available!)") + +#------------------------------------------------------------------------------ +# Registration hook +#------------------------------------------------------------------------------ + +def plot_directive(name, arguments, options, content, lineno, + content_offset, block_text, state, state_machine): + return run(arguments, content, options, state_machine, state, lineno) +plot_directive.__doc__ = __doc__ + +def _option_boolean(arg): + if not arg or not arg.strip(): + # no argument given, assume used as a flag + return True + elif arg.strip().lower() in ('no', '0', 'false'): + return False + elif arg.strip().lower() in ('yes', '1', 'true'): + return True + else: + raise ValueError('"%s" unknown boolean' % arg) + +def _option_format(arg): + return directives.choice(arg, ('python', 'doctest')) + +def _option_align(arg): + return directives.choice(arg, ("top", "middle", "bottom", "left", "center", + "right")) + +def mark_plot_labels(app, document): + """ + To make plots referenceable, we need to move the reference from + the "htmlonly" (or "latexonly") node to the actual figure node + itself. + """ + for name, explicit in document.nametypes.iteritems(): + if not explicit: + continue + labelid = document.nameids[name] + if labelid is None: + continue + node = document.ids[labelid] + if node.tagname in ('html_only', 'latex_only'): + for n in node: + if n.tagname == 'figure': + sectname = name + for c in n: + if c.tagname == 'caption': + sectname = c.astext() + break + + node['ids'].remove(labelid) + node['names'].remove(name) + n['ids'].append(labelid) + n['names'].append(name) + document.settings.env.labels[name] = \ + document.settings.env.docname, labelid, sectname + break + +def setup(app): + setup.app = app + setup.config = app.config + setup.confdir = app.confdir + + options = {'alt': directives.unchanged, + 'height': directives.length_or_unitless, + 'width': directives.length_or_percentage_or_unitless, + 'scale': directives.nonnegative_int, + 'align': _option_align, + 'class': directives.class_option, + 'include-source': _option_boolean, + 'format': _option_format, + 'context': directives.flag, + 'nofigs': directives.flag, + 'encoding': directives.encoding + } + + app.add_directive('plot', plot_directive, True, (0, 2, False), **options) + app.add_config_value('plot_pre_code', None, True) + app.add_config_value('plot_include_source', False, True) + app.add_config_value('plot_formats', ['png', 'hires.png', 'pdf'], True) + app.add_config_value('plot_basedir', None, True) + app.add_config_value('plot_html_show_formats', True, True) + app.add_config_value('plot_rcparams', {}, True) + + app.connect('doctree-read', mark_plot_labels) + +#------------------------------------------------------------------------------ +# Doctest handling +#------------------------------------------------------------------------------ + +def contains_doctest(text): + try: + # check if it's valid Python as-is + compile(text, '', 'exec') + return False + except SyntaxError: + pass + r = re.compile(r'^\s*>>>', re.M) + m = r.search(text) + return bool(m) + +def unescape_doctest(text): + """ + Extract code from a piece of text, which contains either Python code + or doctests. + + """ + if not contains_doctest(text): + return text + + code = "" + for line in text.split("\n"): + m = re.match(r'^\s*(>>>|\.\.\.) (.*)$', line) + if m: + code += m.group(2) + "\n" + elif line.strip(): + code += "# " + line.strip() + "\n" + else: + code += "\n" + return code + +def split_code_at_show(text): + """ + Split code at plt.show() + + """ + + parts = [] + is_doctest = contains_doctest(text) + + part = [] + for line in text.split("\n"): + if (not is_doctest and line.strip() == 'plt.show()') or \ + (is_doctest and line.strip() == '>>> plt.show()'): + part.append(line) + parts.append("\n".join(part)) + part = [] + else: + part.append(line) + if "\n".join(part).strip(): + parts.append("\n".join(part)) + return parts + +#------------------------------------------------------------------------------ +# Template +#------------------------------------------------------------------------------ + + +TEMPLATE = """ +{{ source_code }} + +{{ only_html }} + + {% if source_link or (html_show_formats and not multi_image) %} + ( + {%- if source_link -%} + `Source code <{{ source_link }}>`__ + {%- endif -%} + {%- if html_show_formats and not multi_image -%} + {%- for img in images -%} + {%- for fmt in img.formats -%} + {%- if source_link or not loop.first -%}, {% endif -%} + `{{ fmt }} <{{ dest_dir }}/{{ img.basename }}.{{ fmt }}>`__ + {%- endfor -%} + {%- endfor -%} + {%- endif -%} + ) + {% endif %} + + {% for img in images %} + .. figure:: {{ build_dir }}/{{ img.basename }}.png + {%- for option in options %} + {{ option }} + {% endfor %} + + {% if html_show_formats and multi_image -%} + ( + {%- for fmt in img.formats -%} + {%- if not loop.first -%}, {% endif -%} + `{{ fmt }} <{{ dest_dir }}/{{ img.basename }}.{{ fmt }}>`__ + {%- endfor -%} + ) + {%- endif -%} + + {{ caption }} + {% endfor %} + +{{ only_latex }} + + {% for img in images %} + .. image:: {{ build_dir }}/{{ img.basename }}.pdf + {% endfor %} + +""" + +exception_template = """ +.. htmlonly:: + + [`source code <%(linkdir)s/%(basename)s.py>`__] + +Exception occurred rendering plot. + +""" + +# the context of the plot for all directives specified with the +# :context: option +plot_context = dict() + +class ImageFile(object): + def __init__(self, basename, dirname): + self.basename = basename + self.dirname = dirname + self.formats = [] + + def filename(self, format): + return os.path.join(self.dirname, "%s.%s" % (self.basename, format)) + + def filenames(self): + return [self.filename(fmt) for fmt in self.formats] + +def out_of_date(original, derived): + """ + Returns True if derivative is out-of-date wrt original, + both of which are full file paths. + """ + return (not os.path.exists(derived) or + (os.path.exists(original) and + os.stat(derived).st_mtime < os.stat(original).st_mtime)) + +class PlotError(RuntimeError): + pass + +def run_code(code, code_path, ns=None, function_name=None): + """ + Import a Python module from a path, and run the function given by + name, if function_name is not None. + """ + + # Change the working directory to the directory of the example, so + # it can get at its data files, if any. Add its path to sys.path + # so it can import any helper modules sitting beside it. + + pwd = os.getcwd() + old_sys_path = list(sys.path) + if code_path is not None: + dirname = os.path.abspath(os.path.dirname(code_path)) + os.chdir(dirname) + sys.path.insert(0, dirname) + + # Redirect stdout + stdout = sys.stdout + sys.stdout = cStringIO.StringIO() + + # Reset sys.argv + old_sys_argv = sys.argv + sys.argv = [code_path] + + try: + try: + code = unescape_doctest(code) + if ns is None: + ns = {} + if not ns: + if setup.config.plot_pre_code is None: + exec "import numpy as np\nfrom matplotlib import pyplot as plt\n" in ns + else: + exec setup.config.plot_pre_code in ns + if "__main__" in code: + exec "__name__ = '__main__'" in ns + exec code in ns + if function_name is not None: + exec function_name + "()" in ns + except (Exception, SystemExit), err: + raise PlotError(traceback.format_exc()) + finally: + os.chdir(pwd) + sys.argv = old_sys_argv + sys.path[:] = old_sys_path + sys.stdout = stdout + return ns + +def clear_state(plot_rcparams): + plt.close('all') + matplotlib.rc_file_defaults() + matplotlib.rcParams.update(plot_rcparams) + +def render_figures(code, code_path, output_dir, output_base, context, + function_name, config): + """ + Run a pyplot script and save the low and high res PNGs and a PDF + in outdir. + + Save the images under *output_dir* with file names derived from + *output_base* + """ + # -- Parse format list + default_dpi = {'png': 80, 'hires.png': 200, 'pdf': 200} + formats = [] + plot_formats = config.plot_formats + if isinstance(plot_formats, (str, unicode)): + plot_formats = eval(plot_formats) + for fmt in plot_formats: + if isinstance(fmt, str): + formats.append((fmt, default_dpi.get(fmt, 80))) + elif type(fmt) in (tuple, list) and len(fmt)==2: + formats.append((str(fmt[0]), int(fmt[1]))) + else: + raise PlotError('invalid image format "%r" in plot_formats' % fmt) + + # -- Try to determine if all images already exist + + code_pieces = split_code_at_show(code) + + # Look for single-figure output files first + # Look for single-figure output files first + all_exists = True + img = ImageFile(output_base, output_dir) + for format, dpi in formats: + if out_of_date(code_path, img.filename(format)): + all_exists = False + break + img.formats.append(format) + + if all_exists: + return [(code, [img])] + + # Then look for multi-figure output files + results = [] + all_exists = True + for i, code_piece in enumerate(code_pieces): + images = [] + for j in xrange(1000): + if len(code_pieces) > 1: + img = ImageFile('%s_%02d_%02d' % (output_base, i, j), output_dir) + else: + img = ImageFile('%s_%02d' % (output_base, j), output_dir) + for format, dpi in formats: + if out_of_date(code_path, img.filename(format)): + all_exists = False + break + img.formats.append(format) + + # assume that if we have one, we have them all + if not all_exists: + all_exists = (j > 0) + break + images.append(img) + if not all_exists: + break + results.append((code_piece, images)) + + if all_exists: + return results + + # We didn't find the files, so build them + + results = [] + if context: + ns = plot_context + else: + ns = {} + + for i, code_piece in enumerate(code_pieces): + if not context: + clear_state(config.plot_rcparams) + run_code(code_piece, code_path, ns, function_name) + + images = [] + fig_managers = _pylab_helpers.Gcf.get_all_fig_managers() + for j, figman in enumerate(fig_managers): + if len(fig_managers) == 1 and len(code_pieces) == 1: + img = ImageFile(output_base, output_dir) + elif len(code_pieces) == 1: + img = ImageFile("%s_%02d" % (output_base, j), output_dir) + else: + img = ImageFile("%s_%02d_%02d" % (output_base, i, j), + output_dir) + images.append(img) + for format, dpi in formats: + try: + figman.canvas.figure.savefig(img.filename(format), dpi=dpi) + except Exception,err: + raise PlotError(traceback.format_exc()) + img.formats.append(format) + + results.append((code_piece, images)) + + if not context: + clear_state(config.plot_rcparams) + + return results + +def run(arguments, content, options, state_machine, state, lineno): + # The user may provide a filename *or* Python code content, but not both + if arguments and content: + raise RuntimeError("plot:: directive can't have both args and content") + + document = state_machine.document + config = document.settings.env.config + nofigs = options.has_key('nofigs') + + options.setdefault('include-source', config.plot_include_source) + context = options.has_key('context') + + rst_file = document.attributes['source'] + rst_dir = os.path.dirname(rst_file) + + if len(arguments): + if not config.plot_basedir: + source_file_name = os.path.join(setup.app.builder.srcdir, + directives.uri(arguments[0])) + else: + source_file_name = os.path.join(setup.app.builder.srcdir, config.plot_basedir, + directives.uri(arguments[0])) + + # If there is content, it will be passed as a caption. + caption = '\n'.join(content) + + # If the optional function name is provided, use it + if len(arguments) == 2: + function_name = arguments[1] + else: + function_name = None + + fd = open(source_file_name, 'r') + code = fd.read() + fd.close() + output_base = os.path.basename(source_file_name) + else: + source_file_name = rst_file + code = textwrap.dedent("\n".join(map(str, content))) + counter = document.attributes.get('_plot_counter', 0) + 1 + document.attributes['_plot_counter'] = counter + base, ext = os.path.splitext(os.path.basename(source_file_name)) + output_base = '%s-%d.py' % (base, counter) + function_name = None + caption = '' + + base, source_ext = os.path.splitext(output_base) + if source_ext in ('.py', '.rst', '.txt'): + output_base = base + else: + source_ext = '' + + # ensure that LaTeX includegraphics doesn't choke in foo.bar.pdf filenames + output_base = output_base.replace('.', '-') + + # is it in doctest format? + is_doctest = contains_doctest(code) + if options.has_key('format'): + if options['format'] == 'python': + is_doctest = False + else: + is_doctest = True + + # determine output directory name fragment + source_rel_name = relpath(source_file_name, setup.app.srcdir) + source_rel_dir = os.path.dirname(source_rel_name) + while source_rel_dir.startswith(os.path.sep): + source_rel_dir = source_rel_dir[1:] + + # build_dir: where to place output files (temporarily) + build_dir = os.path.join(os.path.dirname(setup.app.doctreedir), + 'plot_directive', + source_rel_dir) + # get rid of .. in paths, also changes pathsep + # see note in Python docs for warning about symbolic links on Windows. + # need to compare source and dest paths at end + build_dir = os.path.normpath(build_dir) + + if not os.path.exists(build_dir): + os.makedirs(build_dir) + + # output_dir: final location in the builder's directory + dest_dir = os.path.abspath(os.path.join(setup.app.builder.outdir, + source_rel_dir)) + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) # no problem here for me, but just use built-ins + + # how to link to files from the RST file + dest_dir_link = os.path.join(relpath(setup.app.srcdir, rst_dir), + source_rel_dir).replace(os.path.sep, '/') + build_dir_link = relpath(build_dir, rst_dir).replace(os.path.sep, '/') + source_link = dest_dir_link + '/' + output_base + source_ext + + # make figures + try: + results = render_figures(code, source_file_name, build_dir, output_base, + context, function_name, config) + errors = [] + except PlotError, err: + reporter = state.memo.reporter + sm = reporter.system_message( + 2, "Exception occurred in plotting %s\n from %s:\n%s" % (output_base, + source_file_name, err), + line=lineno) + results = [(code, [])] + errors = [sm] + + # Properly indent the caption + caption = '\n'.join(' ' + line.strip() + for line in caption.split('\n')) + + # generate output restructuredtext + total_lines = [] + for j, (code_piece, images) in enumerate(results): + if options['include-source']: + if is_doctest: + lines = [''] + lines += [row.rstrip() for row in code_piece.split('\n')] + else: + lines = ['.. code-block:: python', ''] + lines += [' %s' % row.rstrip() + for row in code_piece.split('\n')] + source_code = "\n".join(lines) + else: + source_code = "" + + if nofigs: + images = [] + + opts = [':%s: %s' % (key, val) for key, val in options.items() + if key in ('alt', 'height', 'width', 'scale', 'align', 'class')] + + only_html = ".. only:: html" + only_latex = ".. only:: latex" + + if j == 0: + src_link = source_link + else: + src_link = None + + result = format_template( + TEMPLATE, + dest_dir=dest_dir_link, + build_dir=build_dir_link, + source_link=src_link, + multi_image=len(images) > 1, + only_html=only_html, + only_latex=only_latex, + options=opts, + images=images, + source_code=source_code, + html_show_formats=config.plot_html_show_formats, + caption=caption) + + total_lines.extend(result.split("\n")) + total_lines.extend("\n") + + if total_lines: + state_machine.insert_input(total_lines, source=source_file_name) + + # copy image files to builder's output directory, if necessary + if not os.path.exists(dest_dir): + cbook.mkdirs(dest_dir) + + for code_piece, images in results: + for img in images: + for fn in img.filenames(): + destimg = os.path.join(dest_dir, os.path.basename(fn)) + if fn != destimg: + shutil.copyfile(fn, destimg) + + # copy script (if necessary) + #if source_file_name == rst_file: + target_name = os.path.join(dest_dir, output_base + source_ext) + f = open(target_name, 'w') + f.write(unescape_doctest(code)) + f.close() + + return errors diff --git a/pytriqs/CMakeLists.txt b/pytriqs/CMakeLists.txt new file mode 100644 index 00000000..6fbcbd46 --- /dev/null +++ b/pytriqs/CMakeLists.txt @@ -0,0 +1,24 @@ +# Create a temporary copy of the python modules so that we can run before installation with the test +FILE(GLOB_RECURSE all_py_files RELATIVE ${CMAKE_SOURCE_DIR}/pytriqs *.py ) +SET(py_copy_tar ${CMAKE_BINARY_DIR}/py_copy.tar) +add_custom_command (OUTPUT ${py_copy_tar} DEPENDS ${all_py_files} + COMMAND cd ${CMAKE_SOURCE_DIR}/pytriqs && tar cf ${py_copy_tar} ${all_py_files} && cd ${CMAKE_BINARY_DIR}/pytriqs && tar xf ${py_copy_tar} ) +add_custom_target(py_copy ALL DEPENDS ${py_copy_tar}) + +find_package(CythonModuleMacro) + +# Add C11 flag +# Put this up when boost python will be removed (or fixed for C++11). +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ${CMAKE_CURRENT_BINARY_DIR}/version.py + ) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.py.in ${CMAKE_CURRENT_BINARY_DIR}/version.py) + +install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}) + +add_all_subdirectories_with_cmakelist() + diff --git a/pytriqs/__init__.py b/pytriqs/__init__.py new file mode 100644 index 00000000..215a4f70 --- /dev/null +++ b/pytriqs/__init__.py @@ -0,0 +1,32 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +__all__ = ['archive', 'dmft', 'dos', 'fit', 'gf', 'lattice', 'plot', 'sumk', 'utility', 'parameters'] + +import sys +if 'additional_builtin_modules' in dir(sys) : + + from version import greeting + import utility.mpi as mpi + if (mpi.world.rank == 0) : sys.stderr.write(greeting) + + diff --git a/pytriqs/__init__.py.template b/pytriqs/__init__.py.template new file mode 100644 index 00000000..86c2db43 --- /dev/null +++ b/pytriqs/__init__.py.template @@ -0,0 +1,3 @@ +# just used in installing pxd files +__all__=[] + diff --git a/pytriqs/archive/CMakeLists.txt b/pytriqs/archive/CMakeLists.txt new file mode 100644 index 00000000..641a8636 --- /dev/null +++ b/pytriqs/archive/CMakeLists.txt @@ -0,0 +1,10 @@ + +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/hdf_archive_basic_layer_h5py.py + ${CMAKE_CURRENT_SOURCE_DIR}/hdf_archive.py + ${CMAKE_CURRENT_SOURCE_DIR}/hdf_archive_schemes.py +) + +install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/archive) + diff --git a/pytriqs/archive/__init__.py b/pytriqs/archive/__init__.py new file mode 100644 index 00000000..4eac6a59 --- /dev/null +++ b/pytriqs/archive/__init__.py @@ -0,0 +1,24 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +from hdf_archive import HDFArchive +__all__ = ['HDFArchive'] diff --git a/pytriqs/archive/hdf_archive.py b/pytriqs/archive/hdf_archive.py new file mode 100644 index 00000000..5a7d41bc --- /dev/null +++ b/pytriqs/archive/hdf_archive.py @@ -0,0 +1,410 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +import sys,numpy,string +from hdf_archive_basic_layer_h5py import HDFArchiveGroupBasicLayer + +from pytriqs.archive.hdf_archive_schemes import hdf_scheme_access, register_class + +# ------------------------------------------- +# +# Various wrappers for basic python types. +# +# -------------------------------------------- +def _my_str(ll, digs = 10) : + ns = str(ll) + for ii in xrange(digs-len(ns)): ns = '0'+ns + return ns + +class PythonListWrap: + def __init__(self,ob) : + self.ob = ob + def __reduce_to_dict__(self) : + return dict( [ (_my_str(n),v) for (n,v) in enumerate (self.ob)]) + @classmethod + def __factory_from_dict__(cls,D) : + return [x for (n,x) in sorted(D.items())] + +class PythonTupleWrap: + def __init__(self,ob) : + self.ob = ob + def __reduce_to_dict__(self) : + return dict( [ (_my_str(n),v) for (n,v) in enumerate (self.ob)]) + @classmethod + def __factory_from_dict__(cls,D) : + return tuple([x for (n,x) in sorted(D.items())]) + +class PythonDictWrap: + def __init__(self,ob) : + self.ob = ob + def __reduce_to_dict__(self) : + return dict( [ (str(n),v) for (n,v) in self.ob.items()]) + @classmethod + def __factory_from_dict__(cls,D) : + return dict([(n,x) for (n,x) in D.items()]) + +register_class (PythonListWrap) +register_class (PythonTupleWrap) +register_class (PythonDictWrap) + +# ------------------------------------------- +# +# A view of a subgroup of the archive +# +# -------------------------------------------- + +class HDFArchiveGroup (HDFArchiveGroupBasicLayer) : + """ + """ + _wrappedType = { type([]) : PythonListWrap, type(()) : PythonTupleWrap, type({}) : PythonDictWrap} + _MaxLengthKey = 500 + + def __init__(self, parent, subpath) : + self.options = parent.options + HDFArchiveGroupBasicLayer.__init__(self, parent, subpath) + self.options = parent.options + self.key_as_string_only = self.options['key_as_string_only'] + self._reconstruct_python_objects = self.options['reconstruct_python_object'] + self.is_top_level = False + + #------------------------------------------------------------------------- + def _key_cipher(self,key) : + if key in self.ignored_keys : + raise KeyError, "key %s is reserved"%key + if self.key_as_string_only : # for bacward compatibility + if type(key) not in [ type('') , type(u'a')] : + raise KeyError, "Key must be string only !" + return key + r = repr(key) + if len (r)> self._MaxLengthKey : + raise KeyError, "The Key is too large !" + # check that the key is ok (it can be reconstructed) + try : + ok = eval(r) == key + except : + ok =False + if not ok : raise KeyError, "The Key *%s*can not be serialized properly by repr !"%key + return r + + #------------------------------------------------------------------------- + def _key_decipher(self,key) : + return key if self.key_as_string_only else eval(key) + + #------------------------------------------------------------------------- + def __contains__(self,key) : + key= self._key_cipher(key) + return key in self.keys() + + #------------------------------------------------------------------------- + def values(self) : + """ + Generator returning the values in the group + """ + def res() : + for name in self.keys() : + yield self[name] + return res() + + #------------------------------------------------------------------------- + def items(self) : + """ + Generator returning couples (key, values) in the group. + """ + def res() : + for name in self.keys(): + yield name, self[name] + return res() + + #------------------------------------------------------------------------- + def __iter__(self) : + """Returns the keys, like a dictionary""" + def res() : + for name in self.keys() : + yield name + return res() + + #------------------------------------------------------------------------- + def __len__(self) : + """Returns the length of the keys list """ + return len(self.keys()) + + #------------------------------------------------------------------------- + def update(self,object_with_dict_protocol): + for k,v in object_with_dict_protocol.items() : self[k] = v + + #------------------------------------------------------------------------- + def __delitem__(self,key) : + key= self._key_cipher(key) + self._clean_key(key,True) + + #------------------------------------------------------------------------- + def __setitem__(self,key,val) : + key= self._key_cipher(key)# first look if key is a string or key + + if key in self.keys() : + if self.options['do_not_overwrite_entries'] : raise KeyError, "key %s already exists"%key + self._clean_key(key) # clean things + + # Transform list, dict, etc... into a wrapped type that will allow HDF reduction + if type(val) in self._wrappedType: val = self._wrappedType[type(val)](val) + + # write the attributes + def write_attributes(g) : + """Use the _hdf5_data_scheme_ if it exists otherwise the class name""" + ds = val._hdf5_data_scheme_ if hasattr(val,"_hdf5_data_scheme_") else val.__class__.__name__ + try : + sch = hdf_scheme_access(ds) + except : + err = """ + You are trying to store an object of type "%s", with the TRIQS_HDF5_data_scheme "%s". + But that data_scheme is not registered, so you will not be able to reread the class. + Didn't you forget to register your class in pytriqs.archive.hdf_archive_schemes? + """ %(val.__class__.__name__,ds) + raise IOError,err + g.write_attr("TRIQS_HDF5_data_scheme", ds) + + if '__write_hdf5__' in dir(val) : # simplest protocol + val.__write_hdf5__(self._group,key) + SUB = HDFArchiveGroup(self,key) + write_attributes(SUB) + elif '__reduce_to_dict__' in dir(val) : # Is it a HDF_compliant object + self.create_group(key) # create a new group + d = val.__reduce_to_dict__() if '__reduce_to_dict__' in dir(val) else dict( [(x,getattr(val,x)) for x in val.__HDF_reduction__]) + if type(d) != type({}) : raise ValueError, " __reduce_to_dict__ method does not return a dict. See the doc !" + if (d=={}) : raise ValueError, "__reduce_to_dict__ returns an empty dict" + SUB = HDFArchiveGroup(self,key) + for n,v in d.items() : SUB[n] = v + write_attributes(SUB) + elif type(val)== numpy.ndarray : # it is a numpy + try : + self._write_array( key, numpy.array(val,copy=1,order='C') ) + except RuntimeError: + print "HDFArchive is in trouble with the array %s"%val + raise + elif isinstance(val, HDFArchiveGroup) : # will copy the group recursively + # we could add this for any object that has .items() in fact... + SUB = HDFArchiveGroup(self, key) + for k,v in val.items() : SUB[k]=v + else : # anything else... expected to be a scalar + try : + self._write_scalar( key, val) + except: + raise #ValueError, "Value %s\n is not of a type suitable to storage in HDF file"%val + self._flush() + + #------------------------------------------------------------------------- + def get_raw (self,key): + """Similar to __getitem__ but it does NOT reconstruct the python object, + it presents it as a subgroup""" + return self.__getitem1__(key,False) + + #------------------------------------------------------------------------- + def __getitem__(self,key) : + """Return the object key, possibly reconstructed as a python object if + it has been properly set up""" + return self.__getitem1__(key,self._reconstruct_python_objects) + + #------------------------------------------------------------------------- + def __getitem1__(self,key,reconstruct_python_object) : + + if key not in self : + key = self._key_cipher(key) + if key not in self : raise KeyError, "Key %s does not exists"%key + + if self.is_group(key) : + SUB = HDFArchiveGroup(self,key) # View of the subgroup + if not reconstruct_python_object : return SUB + try : + hdf_data_scheme = SUB.read_attr("TRIQS_HDF5_data_scheme") + except: + return SUB + if hdf_data_scheme : + try : + sch = hdf_scheme_access(hdf_data_scheme) + except : + print "Warning : The TRIQS_HDF5_data_scheme %s is not recognized. Returning as a group. Hint : did you forgot to import this python class ?"%hdf_data_scheme + return SUB + r_class_name = sch.classname + r_module_name = sch.modulename + r_readfun = sch.read_fun + if not (r_class_name and r_module_name) : return SUB + try : + exec("from %s import %s as r_class" %(r_module_name,r_class_name)) in globals(), locals() + except KeyError : + raise RuntimeError, "I can not find the class %s to reconstruct the object !"%r_class_name + if r_readfun : + res = r_readfun(self._group,key) + elif "__factory_from_dict__" in dir(r_class) : + f = lambda K : SUB.__getitem1__(K,reconstruct_python_object) if SUB.is_group(K) else SUB._read(K) + values = dict( (self._key_decipher(K),f(K)) for K in SUB ) + res = r_class.__factory_from_dict__(values) + else : + raise ValueError, "Impossible to reread the class %s for group %s and key %s"%(r_class_name,self, key) + return res + elif self.is_data(key) : + return self._read(key) + else : + raise KeyError, "Key %s is of unknown type !!"%Key + + #--------------------------------------------------------------------------- + def __str__(self) : + def pr(name) : + if self.is_group(name) : + return "%s : subgroup"%name + elif self.is_data(name) : # can be an array of a number + return "%s : data "%(name) + else : + raise ValueError, "oopps %s"%(name) + + s= "HDFArchive%s with the following content:\n"%(" (partial view)" if self.is_top_level else '') + s+=string.join([ ' '+ pr(n) for n in self.keys() ], '\n') + return s + + #------------------------------------------------------------------------- + def __repr__(self) : + return self.__str__() + + #------------------------------------------------------------------------- + def apply_on_leaves (self,f) : + """ + For each named leaf (name,value) of the tree, it calls f(name,value) + f should return : + - `None` : no action is taken + - an `empty tuple` () : the leaf is removed from the tree + - an hdf-compliant value : the leaf is replaced by the value + """ + def visit_tree(n,d): + for k in d:# Loop over the subgroups in d + if d.is_group(k) : visit_tree(k,d[k]) + else : + r = f(k,d[k]) + if r != None : d[k] = r + elif r == () : del d[k] + visit_tree('/',self['/']) + + +# ------------------------------------------- +# +# The main class +# +# -------------------------------------------- + +class HDFArchive(HDFArchiveGroup): + """ + """ + _class_version = "HDFArchive | 1.0" + + def __init__(self, url_name, open_flag = 'a', key_as_string_only = True, + reconstruct_python_object = True, init = {}): + r""" + Parameters + ----------- + url_name : string + The url of the hdf5 file. + + * If url is a simple string, it is interpreted as a local file name + + * If url is a remote url (e.g. `http://ipht.cea.fr/triqs/data/single_site_bethe.output.h5` ) + then the h5 file is downloaded in temporary file and opened. + In that case, ``open_flag`` must be 'r', read-only mode. + The temporary file is deleted at exit. + open_flag : Legal modes: r, w, a (default) + key_as_string_only : True (default) + init : any generator of tuple (key,val), e.g. a dict.items(). + It will fill the archive with these values. + + Attributes + ---------- + LocalFileName : string + the name of the file or of the local downloaded copy + url_name : string + the name of the Url + + Examples + -------- + >>> # retrieve a remove archive (in read-only mode) : + >>> h = HDFArchive( 'http://ipht.cea.fr/triqs/data/single_site_bethe.output.h5') + >>> + >>> # full copy of an archive + >>> HDFArchive( f, 'w', init = HDFArchive(fmp,'r').items()) # full + >>> + >>> # partial copy of file of name fmp, with only the key 'G' + >>> HDFArchive( f, 'w', init = [ (k,v) for (k,v) in HDFArchive(fmp,'r') if k in ['G'] ) + >>> + >>> # faster version : the object are only retrieved when needed (list comprehension vs iterator comprehension) + >>> HDFArchive( f, 'w', init = ( (k,v) for (k,v) in HDFArchive(fmp,'r') if k in ['G'] ) ) + >>> + >>> # partial copy with processing on the fly with the P function + >>> HDFArchive( f, 'w', init = ( (k,P(v)) for (k,v) in HDFArchive(fmp,'r') if k in ['G'] ) ) + >>> + >>> # another variant with a filtered dict + >>> HDFArchive( f, 'w', init = HDFArchive(fmp,'r').items(lambda k : k in ['G'] )) + + """ + import os,os.path + assert open_flag in ['r','w','a'], "Invalid mode" + assert type(url_name)==type(''), "url_name must be a string" + + # If it is an url , retrieve if and check mode is read only + import urllib + LocalFileName, http_message = urllib.urlretrieve (url_name) if open_flag == 'r' else (url_name, None) + if LocalFileName != url_name : # this was not a local file, so it must be read only + assert open_flag == 'r', "You retrieve a distant Url %s which is not local, so it must be read-only. Use 'r' option"%url_name + + if open_flag == 'w' : + os.system("rm -f %s"%(os.path.abspath(LocalFileName))) # destroys the file, ignoring errors + + self._init_root( LocalFileName, open_flag) + self.options = {'key_as_string_only' : key_as_string_only, + 'do_not_overwrite_entries' : False, + 'reconstruct_python_object': reconstruct_python_object, + 'UseAlpsNotationForComplex' : True + } + HDFArchiveGroup.__init__(self,self,"") + self.is_top_level = True + for k,v in init : self[k]=v + + # These two methods are necessary for "with" + def __enter__(self): return self + + def __exit__(self, type, value, traceback): + self._flush() + self._close() + +#-------------------------------------------------------------------------------- + +class HDFArchiveInert: + """ + A fake class for the node in MPI. It does nothing, but + permits to write simply : + a= mpi.bcast(H['a']) # run on all nodes + -[] : __getitem__ returns self so that H['a']['b'] is ok... + - setitem : does nothing. + """ + def HDFArchive_Inert(self): + pass + def __getitem__(self,x) : return self + def __setitem__(self,k,v) : pass + +#-------------------------------------------------------------------------------- + + diff --git a/pytriqs/archive/hdf_archive_basic_layer_h5py.py b/pytriqs/archive/hdf_archive_basic_layer_h5py.py new file mode 100644 index 00000000..6a9c0b81 --- /dev/null +++ b/pytriqs/archive/hdf_archive_basic_layer_h5py.py @@ -0,0 +1,131 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +# h5py +import numpy,string,h5py +class HDFArchiveGroupBasicLayer : + _class_version = 1 + + def __init__(self, parent, subpath ): + """ """ + self.options = parent.options + self._group = parent._group[subpath] if subpath else parent._group + assert type(self._group) in [h5py.highlevel.Group,h5py.highlevel.File], "Internal error" + self.ignored_keys = [] + self.cached_keys = self._group.keys() + + def _init_root(self, LocalFileName, open_flag) : + try : + fich = h5py.File(LocalFileName, open_flag) + except : + print "Can not open the HDF file %s"%LocalFileName + raise + # checking the version + if open_flag not in ['r','r+','a'] : + self._version = self._class_version + else : + try : + self._version = int(fich.attrs['HDFArchive_Version']) + except : + self._version = 1 + if self._version > self._class_version : + raise IOError, "File %s is too recent for this version of HDFArchive module"%Filename + self._group = fich + + def is_group(self,p) : + """Is p a subgroup ?""" + assert len(p)>0 and p[0]!='/' + return p in self.cached_keys and type(self._group[p]) == h5py.highlevel.Group + + def is_data(self,p) : + """Is p a leaf ?""" + assert len(p)>0 and p[0]!='/' + return p in self.cached_keys and type(self._group[p]) == h5py.highlevel.Dataset + + def write_attr (self, key, val) : + self._group.attrs.create(key, val) + #self._group.attrs[key] = val + + def read_attr(self,attribute_name) : + return self._group.attrs[attribute_name] + + def _read (self, key) : + A = self._group[key] + val = numpy.array(A) if A.shape!=() else A.value + if self.options["UseAlpsNotationForComplex"] and '__complex__' in self._group[key].attrs : + assert type(val) == numpy.ndarray, 'complex tag is set, but I have not an array' + assert not numpy.iscomplexobj(val), 'complex tag is set, but I have a complex !' + if len(val.shape) == 1 : + val = val[0] + 1j * val[1] + else : + val = val[...,0] + 1j*val[...,1] + + def _numpy_scalar_to_python_scalar (v) : + n= numpy + if type(v) in [n.int, n.int8, n.int16, n.int32, n.int64] : return int(v) + if type(v) in [n.uint8, n.uint16, n.uint32, n.uint64] : return int(v) + if type(v) in [n.float, n.float32, n.float64] : return float(v) + if type(v) in [n.complex, n.complex64, n.complex128] : return complex(v) + if type(v) in [n.str_, n.string_] : return str(v) + return v + + return _numpy_scalar_to_python_scalar ( val) + + def _write_array(self, key, A) : + c = self.options["UseAlpsNotationForComplex"] and numpy.iscomplexobj(A) + if c: + val = numpy.zeros( A.shape + (2,) ) + val[...,0], val[...,1] = A.real, A.imag + else : + val = A + self._group[key] = numpy.array(val,copy=1,order='C') + if c : self._group[key].attrs["__complex__"] = 1 + self.cached_keys.append(key) + + def _write_scalar(self, key, A) : + c = self.options["UseAlpsNotationForComplex"] and type(A) ==type (1j) + val = numpy.array([A.real, A.imag]) if c else A + self._group[key] =val + if c : self._group[key].attrs["__complex__"]= 1 + self.cached_keys.append(key) + + def _flush(self): + self._group.file.flush() + + def _close(self): + self._group.file.close() + + def create_group (self,key): + self._group.create_group(key) + self.cached_keys.append(key) + + def keys(self) : + return self.cached_keys + + def _clean_key(self,key, report_error=False) : + if report_error and key not in self.cached_keys : + raise KeyError, "Key %s is not in archive !!"%key + if key in self.cached_keys : + del self._group[key] + self.cached_keys.remove(key) + else: raise KeyError, "Key %s is not in archive !!"%key + diff --git a/pytriqs/archive/hdf_archive_schemes.py b/pytriqs/archive/hdf_archive_schemes.py new file mode 100644 index 00000000..da289685 --- /dev/null +++ b/pytriqs/archive/hdf_archive_schemes.py @@ -0,0 +1,59 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + + +class HDF5Scheme : + def __init__(self, classname, modulename, doc, read_fun= None) : + self.classname, self.modulename, self.doc, self.read_fun = classname, modulename,doc, read_fun + def __str__(self) : + return """ + Name of the class : %s + Name of the module : %s + Documentation : %s"""(self.classname,self.modulename,self.doc) + +_hdf5_schemes_dict= {} + +def register_class (cls, doc = None, read_fun = None) : + """ + For each class, register it with:: + + from HDFArchive_Schemes_dict import register_class + register_class (GfImFreq, doc= doc_if_different_from cls._hdf5_data_scheme_doc_ ) + + """ + SchemeName = cls._hdf5_data_scheme_ if hasattr(cls,"_hdf5_data_scheme_") else cls.__name__ + doc = doc if doc else (cls._hdf5_data_scheme_doc_ if hasattr(cls,"_hdf5_data_scheme_doc_") else {}) + _hdf5_schemes_dict [SchemeName] = HDF5Scheme (cls.__name__, cls.__module__,doc, read_fun) + +def hdf_scheme_access (SchemeName) : + try : + return _hdf5_schemes_dict [SchemeName] + except KeyError : + raise KeyError, "HDF5 Data Scheme %s is not registered"%SchemeName + +def classname (SchemeName) : + return access(SchemeName).classname + +def modulename (SchemeName) : + return access(SchemeName).modulename + + diff --git a/pytriqs/dos/CMakeLists.txt b/pytriqs/dos/CMakeLists.txt new file mode 100644 index 00000000..bfd785d3 --- /dev/null +++ b/pytriqs/dos/CMakeLists.txt @@ -0,0 +1,9 @@ + +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/dos.py + ${CMAKE_CURRENT_SOURCE_DIR}/hilbert_transform.py +) + +install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/dos) + diff --git a/pytriqs/dos/__init__.py b/pytriqs/dos/__init__.py new file mode 100644 index 00000000..7cdfae31 --- /dev/null +++ b/pytriqs/dos/__init__.py @@ -0,0 +1,26 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +from dos import DOS, DOSFromFunction, dos_from_file +from hilbert_transform import HilbertTransform + +__all__ = ['DOS','DOSFromFunction','dos_from_file','HilbertTransform'] diff --git a/pytriqs/dos/dos.py b/pytriqs/dos/dos.py new file mode 100644 index 00000000..71e26083 --- /dev/null +++ b/pytriqs/dos/dos.py @@ -0,0 +1,191 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +import types,string,itertools +from operator import isSequenceType +import numpy + +class DOS : + r""" +* Stores a density of state of fermions + +.. math:: + :center: + + \rho (\epsilon) \equiv \sum'_k \delta( \epsilon - \epsilon_k) + +* The sum is normalized + +.. math:: + + \int_{-\infty}^{\infty} d\epsilon \rho (\epsilon) = 1 + +* Implement :ref:`Plot Protocol `. + + """ + def __init__(self, eps, rho, name = ''): + """ +Parameters +------------ +eps : 1d array-type + eps[i] is value of epsilon. +rho : 1d array-type + The corresponding value of the dos. +name : string + Name of the dos/orbital + + """ + self.name = name + try : + self.eps = numpy.array( eps ) + assert len(self.eps.shape) ==1 + except : + raise RuntimeError, "Argument eps mismatch" + try : + self.rho = numpy.array( rho ) + assert len(self.rho.shape) ==1 + except : + raise RuntimeError, "Argument rho mismatch" + assert self.eps.shape[0] == self.rho.shape[0], "Dimensions of eps and rho do not match" + + + #------------------------------------------------------------- + + def __reduce__(self) : + return self.__class__, (self.eps,self.rho, self.name) + + def __reduce_to_dict__(self) : + return {'epsilon' : self.eps, 'rho': self.rho, 'name' : self.name} + + @classmethod + def __factory_from_dict__(cls,D) : + return cls(D['epsilon'],D['rho'], D['name']) + + def __repr__(self) : + return """ + DOS object : + """%self.__dict__ + + def _plot_(self, Options) : + return [ {'type' : "XY", 'label' : self.name, 'xlabel' :r'$\epsilon$', 'ylabel' : r'%s$(\epsilon)$'%self.name, 'xdata' : self.eps,'ydata' : self.rho } ] + + def density(self,mu=0): + """Calculates the density of free fermions for the given DOS for chemical potential mu.""" + + dens = 0.0 + a = [ (e>mu) for e in self.eps ] + try: + ind = a.index(True) + except: + ind = self.eps.shape[0] + + de = self.eps[1]-self.eps[0] + #for e,r in itertools.izip(self.eps[0:ind],self.rho[0:ind]): + # dens += r + dens = (sum(self.rho[0:ind]) - self.rho[0]/2.0 - self.rho[ind-1]/2.0) * de + #dens2 = dens + (self.rho[ind-1]/2.0 + self.rho[ind]/2.0) * de + if (ind0, "File : wrong format" + # not very safe : fromfile routine can crashes if given non numerics + r = numpy.fromfile(Filename,sep=' ') + l,div = r.shape[0], N_Orbitals +1 + assert l%(div)==0,"File does not contains N*%d numbers !"%(div) + r.shape = l//(div) , div # reshape the array + eps = r[:,0] + if single_orbital : + assert single_orbital>0 and single_orbital <= N_Orbitals, " single_orbital " + return DOS (r[:,0] ,r[:,single_orbital], name) + else : + return [ DOS (r[:,0] ,r[:,i +1 ], name) for i in range (N_Orbitals)] + + +########################################################################## + +class DOSFromFunction(DOS): + """ + * A DOS class, but constructed from a function. + + * The number of points can be variable and self-adjusted in the Hilbert transform to adapt precision. + """ + def __init__(self, function, x_min, x_max, n_pts=100, name=''): + """ + :param function: * a function :math:`\\epsilon \\rightarrow \\rho(\\epsilon)` + * The result type can be anything from which a 1d-array can be constructed by numpy + :param x_min,x_max: Bound of the mesh (domain of the function). + :param n_pts: Number of points in the mesh. + :param name: Name of the DOS. + """ + assert callable(function), "function is not callable" + self.function,self.x_min,self.x_max = function,x_min,x_max + try : + e = function(0.001) + len(numpy.array(e).shape) ==1 + except : + raise RuntimeError , "Value of the function must be a 1d-array" + self.__f(n_pts) # compute arrays + DOS.__init__(self,self.eps,self.rho,name) + + #------------------------------------------------------------- + + def __reduce__(self) : + return self.__class__, (self.function,self.x_min, self.x_max, len(self.eps), self.name) + + #------------------------------------------------------------- + + def __f(self,N) : + r = (self.x_max - self.x_min)/float(N-1) + self.eps = numpy.array( [self.x_min + r* i for i in range(N) ] ) + self.rho = numpy.array( [self.function(e) for e in self.eps]) + +#----------------------------------------------------- +# Register the class for HDFArchive +#----------------------------------------------------- + +from pytriqs.archive.hdf_archive_schemes import register_class +register_class (DOS) + diff --git a/pytriqs/dos/hilbert_transform.py b/pytriqs/dos/hilbert_transform.py new file mode 100644 index 00000000..7b3acc08 --- /dev/null +++ b/pytriqs/dos/hilbert_transform.py @@ -0,0 +1,179 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +from pytriqs.gf.local import * +import types, string, inspect, itertools +from operator import isSequenceType +from pytriqs.dos import DOS, DOSFromFunction +import pytriqs.utility.mpi as mpi +import numpy + +class HilbertTransform : + r""" + Computes the Hilbert Transform from a DOS object + + .. math:: + + \int_{-\infty}^\infty d \epsilon \rho(\epsilon) \Bigl( (\omega + \mu + + I\eta)\mathbf{1} - \hat\varepsilon(\epsilon) - \text{field} - \Sigma(\epsilon) + \Bigr)^{-1} + + """ + def __init__(self, rho): + """ + :param rho: a DOS object. + """ + self.dos = rho + assert isinstance(rho, DOS), "See Doc. rho must be a DOS" + self.__normalize() + + #------------------------------------------------------------- + + def __reduce__(self) : + return self.__class__, (self.rho) + + #------------------------------------------------------------- + + def __normalize(self): + # normalisation. dos is not the value of the function, is the weight of the integrals + R = numpy.array(self.dos.rho, copy=True) + self.rho_for_sum = R + eps = self.dos.eps + R[0] *= (eps[1] - eps[0]) + R[-1] *= (eps[-1] - eps[-2]) + for i in xrange(1, eps.shape[0] - 1) : + R[i] *= (eps[i+1] - eps[i])/2+(eps[i] - eps[i-1])/2 + R /= numpy.sum(R) + + #------------------------------------------------------------- + + def __call__ (self, Sigma, mu=0, eta=0, field=None, epsilon_hat=None, result=None, + n_points_integral=None, test_convergence=None): + r""" + Compute the Hilbert Transform + + Parameters + ----------- + + mu : float + eta : float + Sigma : a GFBloc or a function epsilon-> GFBloc + field : anything that can added to the GFBloc Sigma, e.g. : + * an Array_with_GFBloc_Indices (same size as Sigma) + * a GBloc + epsilon_hat : a function that takes a 1d array eps[i] and returns 3d-array eps[i, :, :] + where the :, : has the matrix structure of Sigma. Default : eps[i] * Identity_Matrix + Used only when DOS is a DOSFromFunction : + n_points_integral : How many points to use. If None, use the Npts of construction + test_convergence : If defined, it will refine the grid until CV is reached + starting from n_points_integral and multiplying by 2 + + Returns + -------- + + Returns the result. If provided, use result to compute the result locally. + """ + + # we suppose here that self.eps, self.rho_for_sum such that + # H(z) = \sum_i self.rho_for_sum[i] * (z- self.eps[i])^-1 + + # Check Sigma and result + assert Sigma.N1==Sigma.N2, "Sigma must be square" + if result : + assert result.N1 == Sigma.N1 and result.N2 == Sigma.N2, "Size of result and Sigma mismatch" + else : + result = Sigma.copy() + + if not( isinstance (self.dos, DOSFromFunction)): + assert n_points_integral==None and test_convergence == None, " Those parameters can only be used with an dos_from_function" + if field !=None : + try : + result += field + except : + assert 0, "field can not be added to the Green function blocks !. Cf Doc" + + def HT(res) : + # First compute the eps_hat array + eps_hat = epsilon_hat(self.dos.eps) if epsilon_hat else numpy.array( [ x* numpy.identity (Sigma.N1) for x in self.dos.eps] ) + assert eps_hat.shape[0] == self.dos.eps.shape[0], "epsilon_hat function behaves incorrectly" + assert eps_hat.shape[1] == eps_hat.shape[2], "epsilon_hat function behaves incorrectly (result not a square matrix)" + assert Sigma.N1 == eps_hat.shape[1], "Size of Sigma and of epsilon_hat mismatch" + + res.zero() + Sigma_fnt = callable(Sigma) + if Sigma_fnt : assert len(inspect.getargspec(Sigma)[0]) ==1, "Sigma function is not of the correct type. See Documentation" + + # Perform the sum over eps[i] + tmp, tmp2 = res.copy(), res.copy() + tmp <<= iOmega_n + mu + eta * 1j + if not(Sigma_fnt) : + tmp -= Sigma + if field != None : tmp -= field + + # I slice all the arrays on the node. Cf reduce operation below. + for d, e_h, e in itertools.izip (*[mpi.slice_array(A) for A in [self.rho_for_sum, eps_hat, self.dos.eps]]): + tmp2.copy_from(tmp) + tmp2 -= e_h + if Sigma_fnt : tmp2 -= Sigma(e) + tmp2.invert() + tmp2 *= d + res += tmp2 + # sum the res GF of all nodes and returns the results on all nodes... + # Cf Boost.mpi.python, collective communicator for documentation. + # The point is that res is pickable, hence can be transmitted between nodes without further code... + res <<= mpi.all_reduce(mpi.world, res, lambda x, y : x+y) + mpi.barrier() + # END of HT + + def test_distance(G1, G2, dist) : + def f(G1, G2) : + dS = max(abs(G1.data - G2.data).flatten()) + aS = max(abs(G1.data).flatten()) + return dS <= aS*dist + #return reduce(lambda x, y : x and y, [f(g1, g2) for (i1, g1), (i2, g2) in izip(G1, G2)]) + return f(G1, G2) # for block function, the previous one is for GF functions + + if isinstance (self.dos, DOSFromFunction): + + if not(n_points_integral) : # if not defined, use the defaults given at construction of the dos + n_points_integral= len(self.dos.eps) + else: + self.dos._DOS__f(n_points_integral) + self.__normalize() + + HT(result) + + nloop, test = 1, 0 + while test_convergence and nloop < 10 and (nloop == 1 or test > test_convergence): + if nloop>1 : + self.dos._DOS__f(n_points_integral) + self.__normalize() + + result_old = result.copy() + result = DOS.HilbertTransform(self, Sigma, mu, eta, epsilon_hat, result) + test = test_distance(result, result_old, test_convergence) + n_points_integral *=2 + + else : # Ordinary DOS + HT(result) + + return result diff --git a/pytriqs/fit/CMakeLists.txt b/pytriqs/fit/CMakeLists.txt new file mode 100644 index 00000000..596646f7 --- /dev/null +++ b/pytriqs/fit/CMakeLists.txt @@ -0,0 +1,8 @@ +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/fit.py +) + +install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/fit) + + diff --git a/pytriqs/fit/__init__.py b/pytriqs/fit/__init__.py new file mode 100644 index 00000000..603d3bb5 --- /dev/null +++ b/pytriqs/fit/__init__.py @@ -0,0 +1,25 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +from fit import Fit, linear, quadratic + +__all__ = ['Fit', 'linear', 'quadratic'] diff --git a/pytriqs/fit/fit.py b/pytriqs/fit/fit.py new file mode 100644 index 00000000..7c967e77 --- /dev/null +++ b/pytriqs/fit/fit.py @@ -0,0 +1,70 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +from scipy.optimize import leastsq +import numpy as np, inspect as ins + +class Fit: + """ + A simple general functional fit of a X,Y plot + + Given a function f(x, p0,p1,p2 ...) with parameters p0, ..., p2, and an init guess + it adjust the parameters with least square method. + + The fitting is done at construction + + `self.param` is the tuple of adjusted parameters. + + The object is callable : `self(x) = f(x, *self.param)`, so it can be plotted e.g. + + """ + def __init__ (self, x_array, y_array, fitter, p0 = None ) : + """ + :param x_array,y_array: curve to fit, as two 1d numpy arrays + :param fitter: a tuple (F, name, init_value_default) where : + + * F is a function : `(x, *param_tuple)` -> y, which act on numpy arrays x and y + * name is string for which name%param_tuple gives the TeX representation of the function + * init_value_default is the default init point of the minimization + + :param p0: init guess of the fit. If None, uses the init_value_default of the function. + + """ + self.function, self.fname, p00 = fitter + assert len(ins.getargspec(self.function)[0])== len(p00) + 1, "error in number of parameters" + assert len(y_array) == len(x_array) + assert len(y_array) > len (p00) + errfunc = lambda x : np.abs ( self.function(x_array,*x) - y_array[:]) + self.param, success = leastsq(errfunc, p0 if p0 else p00 ) + + def __str__ (self) : return (self.fname%tuple(self.param) or 'Fit').replace("+ -","-") + def __repr__ (self) : return str(self) + def __repr_tex__ (self) : return str(self) + def __call__ (self,x) : return self.function(x,*self.param) + + +# a collection of useful fit ... + +linear = lambda X, a,b : a * X + b, r"$%f x + %f$" , (1,1) +quadratic = lambda X, a,b,c : (a * X + b)*X + c, r"$%f x^2 + %f x + %f$" , (0,1,1) + + diff --git a/pytriqs/gf/CMakeLists.txt b/pytriqs/gf/CMakeLists.txt new file mode 100644 index 00000000..94e68611 --- /dev/null +++ b/pytriqs/gf/CMakeLists.txt @@ -0,0 +1,10 @@ + +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ) + +install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/gf) +install (FILES ${CMAKE_SOURCE_DIR}/pytriqs/__init__.py.template DESTINATION "include/pytriqs/gf" RENAME __init__.py) + +add_subdirectory(local) + diff --git a/pytriqs/gf/__init__.py b/pytriqs/gf/__init__.py new file mode 100644 index 00000000..6148257c --- /dev/null +++ b/pytriqs/gf/__init__.py @@ -0,0 +1,31 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +r""" +This is the base module for all common operations with Green's functions. +It is imported with the command:: + + >>> from pytriqs.gf import * +""" + +__all__ = [] + diff --git a/pytriqs/gf/local/CMakeLists.txt b/pytriqs/gf/local/CMakeLists.txt new file mode 100644 index 00000000..5b29f75e --- /dev/null +++ b/pytriqs/gf/local/CMakeLists.txt @@ -0,0 +1,30 @@ + +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/block_gf.py + ${CMAKE_CURRENT_SOURCE_DIR}/descriptors.py + ${CMAKE_CURRENT_SOURCE_DIR}/gf_generic.py + ${CMAKE_CURRENT_SOURCE_DIR}/gf_imfreq.py + ${CMAKE_CURRENT_SOURCE_DIR}/gf_imtime.py + ${CMAKE_CURRENT_SOURCE_DIR}/gf_legendre.py + ${CMAKE_CURRENT_SOURCE_DIR}/gf_refreq.py + ${CMAKE_CURRENT_SOURCE_DIR}/gf_retime.py + ${CMAKE_CURRENT_SOURCE_DIR}/gf_two_real_times.py + ${CMAKE_CURRENT_SOURCE_DIR}/impl_plot.py + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/inverse.py + ${CMAKE_CURRENT_SOURCE_DIR}/lazy_expressions.py + ${CMAKE_CURRENT_SOURCE_DIR}/nothing.py + ${CMAKE_CURRENT_SOURCE_DIR}/tools.py +) + +# Install python sources +install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/gf/local) + +# Build cython module +cython_module( GF3 gf gf/local ) +cython_module( MS matrix_stack gf/local ) + +FILE(GLOB all_pxd_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.pxd ) +install (FILES ${all_pxd_files} DESTINATION "include/pytriqs/gf/local") +install (FILES ${CMAKE_SOURCE_DIR}/pytriqs/__init__.py.template DESTINATION "include/pytriqs/gf/local" RENAME __init__.py) + diff --git a/pytriqs/gf/local/__init__.py b/pytriqs/gf/local/__init__.py new file mode 100644 index 00000000..24d38c75 --- /dev/null +++ b/pytriqs/gf/local/__init__.py @@ -0,0 +1,42 @@ +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +r""" +This is the base module for all common operations with Green's functions. +It is imported with the command:: + + >>> from pytriqs.gf.local import * +""" + +from gf import TailGf + +from inverse import inverse +from gf_imfreq import GfImFreq +from gf_imtime import GfImTime +from gf_refreq import GfReFreq +from gf_retime import GfReTime +from gf_two_real_times import GfTwoRealTime +from gf_legendre import GfLegendre +from block_gf import BlockGf +from descriptors import Omega, iOmega_n, SemiCircular, Wilson, Fourier, InverseFourier, LegendreToMatsubara, MatsubaraToLegendre + +__all__ = ['Omega','iOmega_n','SemiCircular','Wilson','Fourier','InverseFourier','LegendreToMatsubara','MatsubaraToLegendre','lazy_expressions','TailGf','GfImFreq','GfImTime','GfReFreq','GfReTime','GfLegendre','BlockGf','inverse','GfTwoRealTime'] + diff --git a/pytriqs/gf/local/block_gf.py b/pytriqs/gf/local/block_gf.py new file mode 100644 index 00000000..e5bcb927 --- /dev/null +++ b/pytriqs/gf/local/block_gf.py @@ -0,0 +1,376 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +from itertools import izip +import operator +from impl_plot import PlotWrapperPartialReduce + +def call_factory_from_dict (cl,dic) : + """Given a class cl and a dict dic, it calls cl.__factory_from_dict__(dic)""" + return cl.__factory_from_dict__(dic) + +class BlockGf(object): + """ + Generic Green Function by Block. + """ + # not implemented as a dictionnary since we want to be sure of the order !). + def __init__(self, **kwargs) : + """ + * There are several possible constructors, which accept only keyword arguments. + + * BlockGf(name_list = list of names, block_list = list of blocks, make_copies = False, name = '') + + * ``name_list`` : list of the name of the blocks : e.g. ["up","down"]. + * ``block_list`` : list of blocks of Green functions. + * ``make_copies`` : If True, it makes a copy of the blocks and build the Green function from these copies. + + * BlockGf(name_block_generator, make_copies = False, name = '') + + * ``name_block_generator`` : a generator of (index, block) + * ``make_copies`` : If True, it makes a copy of the blocks and build the Green function from these copies. + + """ + # first extract the optional name argument + self.name = kwargs.pop('name','G') + self.note = kwargs.pop('note','') + self._rename_gf = kwargs.pop('rename_gf',True) + + if 'make_copies' not in kwargs : kwargs['make_copies'] = False + + if set(kwargs.keys()) == set(['name_list','block_list','make_copies']) : + BlockNameList, GFlist = kwargs['name_list'],kwargs['block_list'] + elif set(kwargs.keys()) == set(['name_block_generator','make_copies']) : + BlockNameList,GFlist = zip (* kwargs['name_block_generator']) + else : + raise RuntimeError, "BlockGf construction : error in parameters, see the documentation" + if kwargs['make_copies'] : GFlist =[g.copy() for g in GFlist] + + # First a few checks + assert GFlist !=[], "Empty list of blocks !" + for ind in BlockNameList : assert str(ind)[0:2] !='__', "indices should not start with __" + assert len(set(BlockNameList)) == len(BlockNameList),"Bloc indices of the Green Function are not unique" + assert len(BlockNameList) == len(GFlist), "Number of indices and of Green Function Blocks differ" + + # All blocks are compatible for binary operation + # --> correction : All blocks have the same type + #if not reduce (operator.and_,[ GFlist[0]._is_compatible_for_ops(x) for x in GFlist[1:] ] , True) : + # raise RuntimeError, "The blocks are not compatible for binary operations : not the same type, same temperature, etc..." + if len(set([ type(g) for g in GFlist])) != 1 : + raise RuntimeError, "BlockGf : All block must have the same type %s"%GFlist + + # init + self.__indices,self.__GFlist = BlockNameList,GFlist + try : + self.__me_as_dict = dict(self) + except TypeError: + raise TypeError, "indices are not of the correct type" + self.__BlockIndexNumberTable = dict( (i,n) for n,i in enumerate(self.__indices) ) # a dict : index -> numero of its order + + # Add the name to the G + self.note = '' + if self._rename_gf: + for i,g in self : g.name = "%s_%s"%(self.name,i) if self.name else '%s'%(i,) + del self._rename_gf + + #------------ copy and construction ----------------------------------------------- + + def copy(self,*args): + """Returns a (deep) copy of self (i.e. new independant Blocks initialised with self) """ + return self.__class__ (name_list = self.__indices[:], block_list = [ g.copy(*args) for g in self.__GFlist],make_copies=False) + + def view_selected_blocks(self, selected_blocks) : + """Returns a VIEW of the selected blocks of self, in the same order as self.""" + for b in selected_blocks : assert b in self.__indices,"Selected Blocks must be existing blocks" + return self.__class__ ( name_block_generator = [(n,g) for n,g in G if n in selected_blocks ],make_copies=False) + + def copy_selected_blocks(self, selected_blocks) : + """Returns a COPY of the selected blocks of self, in the same order as self.""" + for b in selected_blocks : assert b in self.__indices,"Selected Blocks must be existing blocks" + return self.__class__ ( name_block_generator = [(n,g) for n,g in G if n in selected_blocks ],make_copies=True) + + def copy_from(self, G2): + """Copy the green function from G2: G2 MUST have the same structure !!""" + assert isinstance(G2, BlockGf) + for (i,g),(i2,g2) in itertools.izip(self,G2) : + if (g.N1,g.N2) != (g2.N1,g2.N2) : + raise RuntimeError, "Blocks %s and %s of the Green Function do have the same dimension"%(i1,i2) + for (i,g),(i2,g2) in itertools.izip(self,G2) : g.copy_from(g2) + + #-------------- Iterators ------------------------- + + def __iter__(self) : + return izip(self.__indices,self.__GFlist) + + #--------------------------------------------------------------------------------- + + def _first(self) : + return self.__GFlist[0] + + def __len__(self) : + return len(self.__GFlist) + + #---------------- Properties ------------------------------------------- + + # Deprecated. Left for backward compatibility ?? but + # it would not work for Legendre + @property + def mesh(self) : + """Deprecated : backward compatibility only""" + return self._first().mesh + + @property + def beta(self) : + """ Inverse Temperature""" + return self._first().beta + + @property + def indices(self) : + """A generator of the block indices""" + for ind in self.__indices: + yield ind + + @property + def all_indices(self): + """ An Iterator on BlockGf indices and indices of the blocs of the form : block_index,n1,n2, where n1,n2 are indices of the block""" + for sig,g in self : + val = g.indices + for x in val : + for y in val : + yield (sig,x,y) + + @property + def n_blocks(self): + """ Number of blocks""" + return len(self.__GFlist) + + #---------------------- IO ------------------------------------- + + def __mymakestring(self,x): + return str(x).replace(' ','').replace('(','').replace(')','').replace("'",'').replace(',','-') + + def save(self, filename, accumulate=False) : + """ Save the Green function in i omega_n (as 2 columns). + - accumulate : + """ + for i,g in self : + g.save( "%s_%s"%(filename, self.__mymakestring(i)), accumulate) + + def load(self, filename, no_exception = False): + """ + adjust_temperature : if true, + """ + for i,g in self : + try : + g.load( "%s_%s"%(filename,self.__mymakestring(i))) + except : + if not(no_exception) : raise + + def __reduce__(self): + return call_factory_from_dict, (self.__class__,self.__reduce_to_dict__()) + + def __reduce_to_dict__(self): + val = {'name' : self.name, "note": self.note, "indices" : repr(self.__indices) } + val.update( dict(self ) ) + return val + + @classmethod + def __factory_from_dict__(cls,value): + exec "ind=%s"%value['indices'] + res = cls(name_list = ind, block_list = [value[i] for i in ind], make_copies=False, name=value['name']) + res.note = value['note'] + return res + + #-------------- Pretty print ------------------------- + + def __repr__(self) : + s = "Green Function %s composed of %d blocks : \n"%(self.name,self.n_blocks) + #s = "Green Function %s composed of %d blocks at inverse temperature beta = %s: \n"%(self.name,self.n_blocks,self.beta) + for i,g in self: + s += " %s \n"%repr(g) #" Bloc %s : indices %s \n"%(i,self[i].indices) + if self.note : s += "NB : %s\n"%self.note + return s + + def __str__ (self) : + return self.name if self.name else repr(self) + + #-------------- Bracket operator [] ------------------------- + + def __getitem__(self,key): + try : + g = self.__me_as_dict[key] + except KeyError : + raise IndexError, "bloc index '" + repr(key) + "' incorrect. Possible indices are : "+ repr(self.__indices) + return g + + def __setitem__(self,key,val): + try : + g = self.__me_as_dict[key] + except KeyError : + raise IndexError, "bloc index '" + repr(key) + "' incorrect. Possible indices are : "+ repr(self.__indices) + g <<= val + + # -------------- Various operations ------------------------------------- + + def __le__(self, other) : + raise RuntimeError, " Operator <= not defined " + + def __ilshift__(self, A): + """ A can be 2 things : + * G <<= any_init will init all the BlockGf with the initializer + * G <<= g2 where g2 is a BlockGf will copy g2 into self + """ + if isinstance(A, self.__class__): + for (i,g) in self : g.copy_from(A[i]) + else: + for i,g in self: g <<= A + return self + + def __iadd__(self,arg): + if isinstance(arg, self.__class__): + for (i,g),(i2,g2) in izip(self,arg) : g += g2 + elif operator.isSequenceType(arg): + assert len(arg) == len(self.__GFlist), "list of incorrect length" + for l,g in izip(arg,self.__GFlist) : g +=l + else: + for i,g in self: g += arg + return self + + def __add__(self,y): + c = self.copy() + c += y + return c + + def __radd__(self,y): return self.__add__(y) + + def __isub__(self,arg): + if isinstance(arg, self.__class__) : + for (i,g),(i2,g2) in izip(self,arg) : g -= g2 + elif operator.isSequenceType(arg): + assert len(arg) == len(self.__GFlist) , "list of incorrect length" + for l,g in izip(arg,self.__GFlist) : g -=l + else: + for i,g in self: g -= arg + return self + + def __sub__(self,y): + c = self.copy() + c -= y + return c + + def __rsub__(self,y): + c = (-1)*self.copy() + c += y + return c + + def __imul__(self,arg): + if isinstance(arg, BlockGf): + for (i,g),(i2,g2) in izip(self,arg) : g *= g2 + elif operator.isSequenceType(arg) : + assert len(arg) == len(self.__GFlist) , "list of incorrect length" + for l,g in izip(arg,self.__GFlist) : g*=l + else : + for i,g in self : g *= arg + return self + + def __mul__(self,y): + c = self.copy() + c *= y + return c + + def __rmul__(self,x): return self.__mul__(x) + + def __idiv__(self,arg): + if operator.isSequenceType(arg) : + assert len(arg) == len(self.__GFlist) , "list of incorrect length" + for l,g in izip(arg,self.__GFlist) : g /=l + else : + for i,g in self : g /= arg + return self + + def __div__(self,y): + c = self.copy() + c /= y + return c + + + + #-----------------------------plot protocol ----------------------------------- + + @property + def real(self) : + """Use self.real in a plot to plot only the real part""" + return PlotWrapperPartialReduce(self, RI='R') + + @property + def imag(self) : + """Use self.imag in a plot to plot only the imag part""" + return PlotWrapperPartialReduce(self, RI='I') + + def _plot_(self, *l, **kw) : + """ Implement the plot protocol""" + # NB : it is important to make a copy of the dictionnary, since the + # options are consumed by the _plot_ method + # however, a shallow copy should be enough here, no need for a deep copy + return sum([ g._plot_(*l, ** dict (** kw)) for sig,g in self],[]) + + #-------------------------------------------------------------------------- + + def zero(self) : + for i,g in self : g.zero() + + def density(self) : + """Returns the density as a dict of density of the blocks""" + return dict( (s,g.density()) for s,g in self ) + + def total_density(self) : + """ Total density of G """ + return sum([ g.total_density() for i,g in self ]).real + + def __check_attr(self,ATTR) : + if not hasattr(self._first(), ATTR ) : + raise RuntimeError, "The blocks of this Green Function do not possess the %s method"%ATTR + + def invert(self) : + """Inverse all the blocks""" + self.__check_attr("invert") + for i,g in self : g.invert() + + def delta(self) : + """Compute delta from G0""" + self.__check_attr("delta") + return self.__class__( name_block_generator = [ (n, g.delta()) for n,g in self], make_copies=False) + + def transpose(self): + """Transpose of the BlockGf""" + self.__check_attr("transpose") + return self.__class__( name_block_generator = [ (n, g.transpose()) for n,g in self], make_copies=False) + + def conjugate(self): + """Conjugate of the BlockGf""" + self.__check_attr("conjugate") + return self.__class__( name_block_generator = [ (n, g.conjugate()) for n,g in self], make_copies=False) + +#--------------------------------------------------------- + +from pytriqs.archive.hdf_archive_schemes import register_class +register_class (BlockGf) + diff --git a/pytriqs/gf/local/descriptors.py b/pytriqs/gf/local/descriptors.py new file mode 100644 index 00000000..dd94a740 --- /dev/null +++ b/pytriqs/gf/local/descriptors.py @@ -0,0 +1,337 @@ +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +r""" """ + +import numpy +from math import * +from gf import MeshImFreq, TailGf, MeshReFreq +from lazy_expressions import LazyExprTerminal, LazyExpr, transform + +def is_lazy(y): + #return type(y) in [ Omega_, LazyExpr] + return isinstance(y,(Omega_, LazyExpr, LazyExprTerminal)) + +def is_scalar(x): + return type(x) in [ type(1), type(1.0), type(1j), numpy.ndarray, numpy.int, numpy.int_, numpy.int8, numpy.int16, numpy.int32, numpy.float, numpy.float_, numpy.float32, numpy.float64, numpy.complex, numpy.complex_, numpy.complex64, numpy.complex128 ] + +def convert_scalar_to_const(expr): + + # if the expression is a pure scalar, replace it by Const + t= expr.get_terminal() + if is_scalar(t): return LazyExpr( Const(t) ) + + # otherwise: replace all scalar appearing in +/- operations by Const + def act (tag, childs): + if tag in ["+", "-"]: + for n,c in enumerate(childs): + t = c.get_terminal() + if is_scalar(t): childs[n] = Const (t) + return (tag,childs) + + return transform(expr, act) + +######################################################################### + +class Base (LazyExprTerminal): + def __init__(self,**kargs): + self.__dict__.update(kargs) + +######################################################################### + +class Function (Base): + r""" + Stores a python function and a tail. + + If the Green's function is defined on an array of points:math:`x_i`, then it will be initialized to:math:`F(x_i)`. + """ + def __init__ (self, function, tail=None): + r""" + :param function: the function:math:`\omega \rightarrow function(\omega)` + :param tail: The tail. Use None if you don't use any tail (will be put to 0) + """ + Base.__init__(self,function=function, tail=tail) + + def __call__(self,G): + if not(callable(self.function)): raise RuntimeError, "GFInitializer.Function: f must be callable" + res = G.data[:,:,:] + try: + for n,om in enumerate(G.mesh): res[n,:,:] = self.function(om) + except: + print "The given function has a problem..." + raise + if self.tail: G.tail.copy_from(self.tail) + return G + +######################################################################### + +class Const(Base): + def __init__ (self, C): + Base.__init__(self, C=C) + + def __call__(self,G): + C = self.C + if G.mesh.__class__.__name__ not in ['MeshImFreq', 'MeshReFreq']: + raise TypeError, "This initializer is only correct in frequency" + + if not isinstance(C,numpy.ndarray): + assert G.N1==G.N2, "Const only applies to square G" + C = C*numpy.identity(G.N1) + if C.shape !=(G.N1,G.N2): raise RuntimeError, "Size of constant incorrect" + + t = G.tail + G.tail = TailGf(shape = t.shape, size = t.size, order_min=0) + G.tail[0][:,:] = C + + Function(lambda om: C, None)(G) + return G + +######################################################################### + +class Omega_(Base): + r"""The function:math:`\omega \rightarrow \omega` """ + def __str__(self): return "Omega" + def __call__(self,G): + if G.mesh.__class__.__name__ not in ['MeshImFreq', 'MeshReFreq']: + raise TypeError, "This initializer is only correct in frequency" + + Id = numpy.identity(G.N1) + G.tail.zero() + G.tail[-1][:,:] = Id + for n,om in enumerate(G.mesh): G.data[n,:,:] = om*Id + return G + +Omega = Omega_() +iOmega_n = Omega_() + +########################################################################## + +class A_Omega_Plus_B(Base): + "deprecated. do not use" + def __init__ (self, A=1, B=0, Invert= False): + Base.__init__(self, A=A, B=B,Invert=Invert) + + def __call__(self,G): + A,B = self.A, self.B + if G.mesh.__class__.__name__ not in ['MeshImFreq', 'MeshReFreq']: + raise TypeError, "This initializer is only correct in frequency" + + if not isinstance(A,numpy.ndarray): A = A*numpy.identity(G.N1) + if not isinstance(B,numpy.ndarray): B = B*numpy.identity(G.N1) + if A.shape !=(G.N1,G.N2): raise RuntimeError, "Size of A incorrect" + if B.shape !=(G.N1,G.N2): raise RuntimeError, "Size of B incorrect" + + t,Id = G.tail, numpy.identity(G.N1) + G.tail = TailGf(shape = t.shape, size = t.size, order_min=-1) + G.tail[-1][:,:] = A + G.tail[0][:,:] = B + + Function(lambda om: A*om + B, None)(G) + + if self.Invert: G.invert() + return G + +####################################### + +class OneFermionInTime(Base): + def __init__ (self, l =0): + Base.__init__(self, L=l) + + def __call__(self,G): + L = self.L + if G.mesh.TypeGF not in [GF_Type.Imaginary_Time]: + raise TypeError, "This initializer is only correct in frequency" + + t,Id = G.tail, numpy.identity(G.N1) + G.tail = TailGf(shape = t.shape, size = 3, order_min=1) + t[1][:,:] = 1 + t[2][:,:] = L + t[3][:,:] = L*L + + fact = -1/(1+exp(-L*G.beta)) + Function(lambda t: fact* exp(-L*t) *Id, None)(G) + return G + + +################################################## + +def _SemiCircularDOS(half_bandwidth): + """ + Semi_Circular DOS function + Input: the 1/2 bandwidth + Returns: a function omega-> dos(omega) + """ + from math import sqrt,pi + larg = half_bandwidth + def semi(x): + if (abs(x) -D) and (om < D): + return (2.0/D**2) * (om - 1j* sqrt(D**2 - om**2)) + else: + return (2.0/D**2) * (om - copysign(1,om) * sqrt(om**2 - D**2)) + else: + raise TypeError, "This initializer is only correct in frequency" + + # Let's create a new tail + G.tail = TailGf(shape = G.tail.shape, size=5, order_min=1) + for i in range(G.N1): + G.tail[1][i,i] = 1.0 + G.tail[3][i,i] = D**2/4.0 + G.tail[5][i,i] = D**4/8.0 + + Function(f,None)(G) + return G + +################################################## + +class Wilson (Base): + r"""The Hilbert transform of a flat density of states, with cut-off + + .. math:: + g(z) = \int \frac{A(\omega)}{z-\omega} d\omega + + where :math:`A(\omega) = \theta( D^2 - \omega^2)/(2D)` + + (only works in combination with frequency Green's functions). + """ + def __init__ (self, half_bandwidth): + """:param half_bandwidth: :math:`D`, the half bandwidth """ + Base.__init__(self, half_bandwidth=half_bandwidth) + + def __str__(self): return "Wilson(%s)"%half_bandwidth + + def __call__(self,G): + + D = self.half_bandwidth + Id = numpy.identity(G.N1,numpy.complex_) + + if type(G.mesh) == MeshImFreq: + f = lambda om: (-1/(2.0*D)) * numpy.log((om-D)/(om+D)) * Id + elif type(G.mesh) == MeshReFreq: + def f(om): + if (om.real > -D) and (om.real < D): + return -numpy.log(abs(om-D)/abs(om+D))*Id/(2*D) - 1j*pi*Id/(2*D) + else: + return -numpy.log(abs(om-D)/abs(om+D))*Id/(2*D) + else: + raise TypeError, "This initializer is only correct in frequency" + + # Let's create a new tail + G.tail = TailGf(shape = G.tail.shape, size=5, order_min=1) + for i in range(G.N1): + G.tail[1][i,i] = 1.0 + G.tail[3][i,i] = D**2/3.0 + G.tail[5][i,i] = D**4/5.0 + + Function(f,None)(G) + return G + + +################################################## + +class Fourier (Base): + r""" + The Fourier transform as a lazy expression + """ + def __init__ (self, G): + """:param G: :math:`G`, the function to be transformed. Must in the time domain""" + Base.__init__(self, G = G) + + def __str__(self): return "Fourier(%s)"%self.G.name + + def __call__(self,G2): + G2.set_from_fourier(self.G) + return G2 + +class InverseFourier (Base): + r""" + The Inverse Fourier transform as a lazy expression + """ + def __init__ (self, G): + """:param G: :math:`G`, the function to be transformed. Must in the frequency domain""" + Base.__init__(self, G = G) + + def __str__(self): return "InverseFourier(%s)"%self.G.name + + def __call__(self,G2): + G2.set_from_inverse_fourier(self.G) + return G2 + +class LegendreToMatsubara (Base): + r""" + The transformation from Legendre to Matsubara as a lazy expression + """ + def __init__ (self, G): + """:param G: :math:`G`, the function to be transformed. Must in the Legendre domain""" + Base.__init__(self, G = G) + + def __str__(self): return "LegendreToMatsubara(%s)"%self.G.name + + def __call__(self,G2): + G2.set_from_legendre(self.G) + return G2 + +class MatsubaraToLegendre (Base): + r""" + The transformation from Legendre to Matsubara as a lazy expression + """ + def __init__ (self, G): + """:param G: :math:`G`, the function to be transformed. Must in the Matsubara domain""" + Base.__init__(self, G = G) + + def __str__(self): return "MatsubaraToLegendre(%s)"%self.G.name + + def __call__(self,G2): + G2.set_from_imfreq(self.G) + return G2 + diff --git a/pytriqs/gf/local/functions.pxd b/pytriqs/gf/local/functions.pxd new file mode 100644 index 00000000..f109a129 --- /dev/null +++ b/pytriqs/gf/local/functions.pxd @@ -0,0 +1,31 @@ +############### Density ######################### + +cdef extern from "triqs/gf/local/functions.hpp": + matrix_view density(gf_imfreq &) + matrix_view density(gf_legendre &) + void enforce_discontinuity(gf_legendre &, array_view[double,TWO]) + +############### Fourier ######################### + +cdef extern from "triqs/gf/local/fourier_matsubara.hpp" : + gf_imfreq lazy_fourier (gf_imtime & ) + gf_imtime lazy_inverse_fourier (gf_imfreq & ) + +cdef extern from "triqs/gf/local/fourier_real.hpp" : + gf_refreq lazy_fourier (gf_retime & ) + gf_retime lazy_inverse_fourier (gf_refreq & ) + gf_refreq fourier (gf_retime & ) except + + gf_retime inverse_fourier (gf_refreq & ) except + + +############### Legendre ######################### + +cdef extern from "triqs/gf/local/legendre_matsubara.hpp" : + gf_imfreq lazy_legendre_imfreq (gf_legendre &) + gf_imtime lazy_legendre_imtime (gf_legendre &) + gf_legendre lazy_imfreq_legendre (gf_imfreq &) + gf_legendre lazy_imtime_legendre (gf_imtime &) + +############### Pade ######################### + +cdef extern from "triqs/gf/local/pade.hpp": + void pade(gf_refreq &, gf_imfreq &, int, double) except + diff --git a/pytriqs/gf/local/gf.pxd b/pytriqs/gf/local/gf.pxd new file mode 100644 index 00000000..e57170c3 --- /dev/null +++ b/pytriqs/gf/local/gf.pxd @@ -0,0 +1,62 @@ +from dcomplex cimport * +from arrays cimport * +from libcpp.vector cimport vector +from libcpp.string cimport string as std_string +from shared_ptr cimport * +from extractor cimport * +from h5 cimport * + +# -------------------- Some generic tools ------------------------------- + +cdef extern from "triqs/gf/tools.hpp" namespace "triqs::gf" : + cdef enum statistic_enum "triqs::gf::statistic_enum" : + Boson,Fermion + + cdef cppclass nothing : + nothing () + + cdef cppclass freq_infty: + freq_infty () + + cdef cppclass mesh_pt_generator "triqs::gf::mesh_pt_generator" [MeshType] : + mesh_pt_generator( MeshType * ) + mesh_pt_generator() + complex to_point() + mesh_pt_generator operator++() + bint at_end() + void increment() + + cdef cppclass indices_2_t : + indices_2_t( ) + indices_2_t( vector[vector[std_string]] &) + vector[std_string] & operator[](int) + vector[vector[std_string]] & operator()() + bint same() + +cdef extern from "triqs/gf/meshes/linear.hpp" namespace "triqs::gf" : + + cdef enum mesh_enum "triqs::gf::mesh_kind": + half_bins, full_bins, without_last + +cdef extern from "triqs/gf/block.hpp" namespace "triqs::gf" : + + cdef cppclass discrete_domain : + discrete_domain () + discrete_domain (vector[std_string] &) + vector[std_string] & names() + + cdef cppclass discrete_mesh : + discrete_mesh () + discrete_mesh (discrete_mesh &) + discrete_domain & domain() + long size() + bint operator ==( discrete_mesh &) + +include "tail.pxd" +include "imfreq.pxd" +include "imtime.pxd" +include "refreq.pxd" +include "retime.pxd" +include "legendre.pxd" +include "two_real_times.pxd" + diff --git a/pytriqs/gf/local/gf.pyx b/pytriqs/gf/local/gf.pyx new file mode 100644 index 00000000..ad4f206f --- /dev/null +++ b/pytriqs/gf/local/gf.pyx @@ -0,0 +1,26 @@ +#!python +#cython: embedsignature=True +from cython.operator cimport dereference as deref, preincrement as inc #dereference and increment operators +cimport cython +import numpy +import string +import warnings +from block_gf import BlockGf +from math import pi +from h5 cimport * + +include "mesh_imfreq.pyx" +include "mesh_imtime.pyx" +include "mesh_refreq.pyx" +include "mesh_retime.pyx" +include "mesh_two_real_times.pyx" +include "mesh_legendre.pyx" +include "imfreq.pyx" +include "imtime.pyx" +include "refreq.pyx" +include "retime.pyx" +include "two_real_times.pyx" +include "legendre.pyx" +include "tail.pyx" +include "functions.pxd" + diff --git a/pytriqs/gf/local/gf_generic.py b/pytriqs/gf/local/gf_generic.py new file mode 100644 index 00000000..f098df44 --- /dev/null +++ b/pytriqs/gf/local/gf_generic.py @@ -0,0 +1,403 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011-2012 by M. Ferrero, 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 . +# +################################################################################ + +import numpy +import lazy_expressions, descriptors +from gf import MeshImFreq +from pytriqs.plot.protocol import clip_array +from types import IntType, SliceType, StringType +from tools import LazyCTX, IndicesConverter, get_indices_in_dict, py_deserialize +from impl_plot import PlotWrapperPartialReduce +from nothing import Nothing +from gf import TailGf +from matrix_stack import MatrixStack +import copy_reg +from nothing import Nothing + +def builder_cls_with_dict_arg(cls, args): return cls(**args) + +def reductor(x): + return (builder_cls_with_dict_arg, (x._derived, x.__reduce_to_dict__()) ) + + +class GfGeneric: + + def __init__(self, mesh, data, singularity, symmetry, indices_pack, name, derived): + + self._mesh = mesh + self._data = data + self._singularity = singularity + self._symmetry = symmetry + self._indices_pack = indices_pack + self.name = name + self._derived = derived + + self.indicesR, self.indicesL = indices_pack + + copy_reg.pickle(derived, reductor, builder_cls_with_dict_arg ) + + @property + def mesh(self): return self._mesh + + @property + def tail(self): return self._singularity + @tail.setter + def tail(self, t): + if type(t) == TailGf: + assert (self.N1, self.N2) == (t.N1, t.N2) + self._singularity.copy_from (t) + elif type(t) == Nothing: + self._singularity = Nothing() + else: + raise RuntimeError, "invalid rhs for tail assignment" + + @property + def data(self): return self._data + @data.setter + def data (self, value): self._data[:,:,:] = value + + @property + def indices(self): + assert (self.indicesR == self.indicesL), "right and left indices are different" + return self.indicesR + + @property + def N1(self): return self._data.shape[1] + + @property + def N2(self): return self._data.shape[2] + + #--------------------- h5 and reduction ------------------------------------------ + + def __reduce_to_dict__(self): + return {'mesh': self._mesh, 'data': self._data, + 'tail': self._singularity, 'symmetry': self._symmetry, + 'indices_pack': self._indices_pack, 'name': self.name } + + def __write_hdf5__ (self, gr, key): + self.__write_hdf5_cython__(gr, key) + gr[key].create_group('indices') + gr[key]['indices']['left'] = self.indicesL + gr[key]['indices']['right'] = self.indicesR + #gr[key]['name'] = self.name + + #--------------------- copies ------------------------------------------ + + def copy(self): + return self._derived(indices_pack = self._indices_pack, mesh = self._mesh, + data = self._data.copy(), tail = self._singularity.copy(), + name = self.name) + + def copy_from(self, X): + assert self._derived is X._derived + assert self.mesh == X.mesh + self.data = X.data + self.tail = X.tail + #assert list(self._indices)== list(X._indices) + self._symmetry = X._symmetry + self.name = X.name + + #--------------------- [ ] operator ------------------------------------------ + + def __getitem__(self, key): + """Key is a tuple of index (n1, n2) as defined at construction""" + if len(key) !=2: raise KeyError, "[ ] must be given two arguments" + sl1, sl2 = key + if type(sl1) == StringType and type(sl2) == StringType: + # Convert the indices to integer + indices_converter = [ IndicesConverter(self.indicesL), IndicesConverter(self.indicesR)] + sl1, sl2 = [ indices_converter[i].convertToNumpyIndex(k) for i, k in enumerate(key) ] + if type (sl1) != slice: sl1 = slice (sl1, sl1+1) + if type (sl2) != slice: sl2 = slice (sl2, sl2+1) + return self.__class__(indicesL = list(self.indicesL)[sl1], + indicesR = list(self.indicesR)[sl2], + name = self.name, + mesh = self.mesh, + data = self.data[:,sl1,sl2], + tail = self.tail._make_slice(sl1, sl2)) + + def __setitem__(self, key, val): + g = self.__getitem__(key) + g <<= val + + #------------- Iteration ------------------------------------ + + def __iter__(self): + for i in self.indicesL: + for j in self.indicesR: + b =self[i, j] + b.name = "%s_%s_%s"%(self.name if hasattr(self, 'name') else '', i, j) + yield i, j, b + + #---------------- Repr, str --------------------------------- + + def __str__(self): + return self.name if self.name else repr(self) + + def __repr__(self): + return """%s %s: indicesL = %s, indicesR = %s"""%(self.__class__.__name__, self.name, + [x for x in self.indicesL], [x for x in self.indicesR]) + + #-------------- PLOT --------------------------------------- + + @property + def real(self): + """Use self.real in a plot to plot only the real part""" + return PlotWrapperPartialReduce(self, RI='R') + + @property + def imag(self): + """Use self.imag in a plot to plot only the imag part""" + return PlotWrapperPartialReduce(self, RI='I') + + #------------------ + + def x_data_view(self, x_window = None, flatten_y = False): + """ + :param x_window: the window of x variable (omega/omega_n/t/tau) for which data is requested + if None, take the full window + :param flatten_y: If the Green function is of size (1, 1) flatten the array as a 1d array + :rtype: a tuple (X, data) where + * X is a 1d numpy of the x variable inside the window requested + * data is a 3d numpy array of dim (:,:, len(X)), the corresponding slice of data + If flatten_y is True and dim is (1, 1, *), returns a 1d numpy + """ + X = [x.imag for x in self.mesh] if type(self.mesh) == MeshImFreq else [x for x in self.mesh] + X, data = numpy.array(X), self.data + if x_window: + sl = clip_array (X, *x_window) if x_window else slice(len(X)) # the slice due to clip option x_window + X, data = X[sl], data[sl,:,:] + if flatten_y and data.shape[1:3]==(1, 1): data = data[:,0,0] + return X, data + + #-------- LAZY expression system ----------------------------------------- + + def __lazy_expr_eval_context__(self): + return LazyCTX(self) + + def __eq__(self, other): + raise RuntimeError, " Operator not defined " + + def __ilshift__(self, A): + """ A can be two things: + * G <<= any_init will init the GFBloc with the initializer + * G <<= g2 where g2 is a GFBloc will copy g2 into self + """ + if isinstance(A, self.__class__): + if self is not A: self.copy_from(A) # otherwise it is useless AND does not work !! + elif isinstance(A, lazy_expressions.LazyExpr): # A is a lazy_expression made of GF, scalars, descriptors + A2= descriptors.convert_scalar_to_const(A) + def e_t (x): + if not isinstance(x, descriptors.Base): return x + tmp = self.copy() + x(tmp) + return tmp + self.copy_from (lazy_expressions.eval_expr_with_context(e_t, A2) ) + elif isinstance(A, lazy_expressions.LazyExprTerminal): #e.g. g<<= SemiCircular (...) + self <<= lazy_expressions.LazyExpr(A) + elif descriptors.is_scalar(A): #in the case it is a scalar .... + self <<= lazy_expressions.LazyExpr(A) + else: + raise RuntimeError, " <<= operator: RHS not understood" + return self + + #-------------------- Arithmetic operations --------------------------------- + + def __add_iadd_impl (self, lhs, arg, is_add): + d, t, rhs = lhs.data, lhs.tail,None + if type(lhs) == type(arg): + d[:,:,:] += arg.data + t += arg.tail + elif isinstance(arg, numpy.ndarray): # an array considered as a constant function + MatrixStack(lhs.data).add(arg) + rhs = arg + elif descriptors.is_scalar(arg): # just a scalar + arg = arg*numpy.identity(lhs.N1,dtype = lhs.data.dtype ) + MatrixStack(lhs.data).add(arg) + assert lhs.tail.shape[0] == lhs.tail.shape[1], "tail + scalar only valid in diagonal case" + rhs = numpy.identity(lhs.tail.shape[0]) *arg + else: + raise RuntimeError, " argument type not recognized in += for %s"%arg + if rhs !=None : + new_tail = TailGf(shape=lhs.tail.shape, size=lhs.tail.size, order_min=min(0,lhs.tail.order_min)) + new_tail[0][:,:] = rhs + # if it is add, then we CAN change the shape of the tail, and + # reassign it since it is a new object, just create (then use the + # _singularity object. + # otherwise we can not, since it could be view, so we use the tail + # and if shape is not correct, = i.e. copy_from will raise an error + if is_add : lhs._singularity = lhs.tail + new_tail + else : lhs.tail = lhs.tail + new_tail + return lhs + + def __iadd__(self, arg): + return self.__add_iadd_impl(self,arg,False) + + def __add__(self, y): + if descriptors.is_lazy(y): return lazy_expressions.make_lazy(self) + y + c = self.copy() + return self.__add_iadd_impl(c,y,True) + + def __radd__(self, y): return self.__add__(y) + + def __sub_isub_impl (self, lhs, arg, is_sub): + d, t, rhs = lhs.data, lhs.tail,None + if type(lhs) == type(arg): + d[:,:,:] -= arg.data + t -= arg.tail + elif isinstance(arg, numpy.ndarray): # an array considered as a constant function + MatrixStack(lhs.data).sub(arg) + rhs = arg + elif descriptors.is_scalar(arg): # just a scalar + arg = arg*numpy.identity(lhs.N1,dtype = lhs.data.dtype ) + MatrixStack(lhs.data).sub(arg) + assert lhs.tail.shape[0] == lhs.tail.shape[1], "tail - scalar only valid in diagonal case" + rhs = numpy.identity(lhs.tail.shape[0]) *arg + else: + raise RuntimeError, " argument type not recognized in -= for %s"%arg + if rhs !=None : + new_tail = TailGf(shape=lhs.tail.shape, size=lhs.tail.size, order_min=min(0,lhs.tail.order_min)) + new_tail[0][:,:] = rhs + if is_sub : lhs._singularity = lhs.tail - new_tail + else : lhs.tail = lhs.tail - new_tail + return lhs + + def __isub__(self, arg): + return self.__sub_isub_impl(self,arg,False) + + def __sub__(self, y): + if descriptors.is_lazy(y): return lazy_expressions.make_lazy(self) - y + c = self.copy() + return self.__sub_isub_impl(c,y,True) + + def __rsub__(self, y): + c = (-1)*self.copy() + return c + y # very important to use the as +, cf above, _singularity vs tail + + def __imul__(self, arg): + + if type(self) == type(arg): + d, d2 = self.data, arg.data + assert d.shape == d2.shape, " Green function block multiplication with arrays of different size !" + for om in range (d.shape[0]): + d[om,:,:] = numpy.dot(d[om,:,:], d2[om,:,:]) + self.tail = self.tail * arg.tail + elif descriptors.is_scalar(arg): + self.data *= arg + self.tail *= arg + else: + raise RuntimeError, " argument type not recognized in *= for %s"%arg + return self + + def __mul__(self, arg): + + if descriptors.is_lazy(arg): + return lazy_expressions.make_lazy(self) * arg + else: + res = self.copy() + res *= arg + return res + + def __rmul__(self, arg): + + if descriptors.is_lazy(arg): + return arg * lazy_expressions.make_lazy(self) + elif descriptors.is_scalar(arg): + return self.__mul__(arg) + + def from_L_G_R(self, L, G, R): + + N1 = self.data.shape[1] + N2 = self.data.shape[2] + assert L.shape[0] == N1 + assert L.shape[1] == G.data.shape[1] + assert R.shape[0] == G.data.shape[2] + assert R.shape[1] == N2 + + MatrixStack(self.data).matmul_L_R(L, G.data, R) + + # this might be a bit slow + t = TailGf(shape=(N1,N2), size=G.tail.order_max-G.tail.order_min+1, order_min=G.tail.order_min) + for o in range(t.order_min, t.order_max+1): + t[o] = numpy.dot(L, numpy.dot(G.tail[o], R)) + self.tail = t + + def __idiv__(self, arg): + """ If arg is a scalar, simple scalar multiplication + """ + if descriptors.is_lazy(arg): return lazy_expressions.make_lazy(self) / arg + if descriptors.is_scalar(arg): + self.data /= arg + self.tail /= arg + else: + raise RuntimeError, " argument type not recognized in imul for %s"%arg + return self + + def __div__(self, arg): + assert descriptors.is_scalar(arg), "Error in /" + res = self.copy() + res /= arg + return res + + #--------------------------------------------------- + + def zero(self): + self <<= 0.0 + + #--------------------------------------------------- + + def invert(self): + """Invert the matrix for all arguments""" + MatrixStack(self.data).invert() + self.tail.invert() + + #--------------------------------------------------- + + def transpose(self): + """Transposes the GF Bloc: return a new transposed view""" + ### WARNING: this depends on the C++ layering .... + return self.__class__( + indices = list(self.indices), + mesh = self.mesh, + data = self.data.transpose( (0, 2, 1) ), + tail = self.tail.transpose(), + name = self.name+'(t)') + + #--------------------------------------------------- + + def conjugate(self): + """Complex conjugate of the GF Bloc. It follow the policy of numpy and + make a copy only if the Green function is complex valued""" + + return self.__class__( + indices = list(self.indices), + mesh = self.mesh, + data = self.data.conjugate(), + tail = self.tail.conjugate(), + name = self.name+'*') + + #------------------ Density ----------------------------------- + + def total_density(self): + """Trace density""" + return numpy.trace(self.density()) + diff --git a/pytriqs/gf/local/gf_imfreq.py b/pytriqs/gf/local/gf_imfreq.py new file mode 100644 index 00000000..924401c7 --- /dev/null +++ b/pytriqs/gf/local/gf_imfreq.py @@ -0,0 +1,140 @@ +from gf import GfImFreq_cython, MeshImFreq, TailGf +from gf_generic import GfGeneric +import numpy +from scipy.optimize import leastsq +from tools import get_indices_in_dict +from nothing import Nothing +import impl_plot + +class GfImFreq ( GfGeneric, GfImFreq_cython ) : + def __init__(self, **d): + """ + The constructor have two variants : you can either provide the mesh in + Matsubara frequencies yourself, or give the parameters to build it. + All parameters must be given with keyword arguments. + + GfImFreq(indices, beta, statistic, n_points, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``beta``: Inverse Temperature + * ``statistic``: 'F' or 'B' + * ``n_points``: Number of Matsubara frequencies + * ``data``: A numpy array of dimensions (len(indices),len(indices),n_points) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + GfImFreq(indices, mesh, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``mesh``: a MeshGf object, such that mesh.TypeGF== GF_Type.Imaginary_Frequency + * ``data``: A numpy array of dimensions (len(indices),len(indices),:) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + .. warning:: + + The Green function take a **view** of the array data, and a **reference** to the tail. + + """ + mesh = d.pop('mesh',None) + if mesh is None : + if 'beta' not in d : raise ValueError, "beta not provided" + beta = float(d.pop('beta')) + n_max = d.pop('n_points',1025) + stat = d.pop('statistic','F') + mesh = MeshImFreq(beta,stat,n_max) + + self.dtype = numpy.complex_ + indices_pack = get_indices_in_dict(d) + indicesL, indicesR = indices_pack + N1, N2 = len(indicesL),len(indicesR) + data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype ) + tail = d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2), size=10, order_min=-1) + symmetry = d.pop('symmetry', Nothing()) + name = d.pop('name','g') + assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys() + + GfGeneric.__init__(self, mesh, data, tail, symmetry, indices_pack, name, GfImFreq) + GfImFreq_cython.__init__(self, mesh, data, tail) + + #-------------- PLOT --------------------------------------- + + def _plot_(self, opt_dict): + """ Plot protocol. opt_dict can contain : + * :param RIS: 'R', 'I', 'S', 'RI' [ default] + * :param x_window: (xmin,xmax) or None [default] + * :param name: a string [default ='']. If not '', it remplaces the name of the function just for this plot. + """ + return impl_plot.plot_base( self, opt_dict, r'$\omega_n$', + lambda name : r'%s$(i\omega_n)$'%name, True, [x.imag for x in self.mesh] ) + + #-------------- OTHER OPERATIONS ----------------------------------------------------- + + def replace_by_tail(self,start) : + d = self.data + t = self.tail + for n, om in enumerate(self.mesh) : + if n >= start : d[n,:,:] = t(om) + + def fit_tail(self, fixed_coef, order_max, fit_start, fit_stop, replace_tail = True): + """ + Fit the tail of the Green's function + Input: + - fixed_coef: a 3-dim array of known coefficients for the fit starting from the order -1 + - order_max: highest order in the fit + - fit_start, fit_stop: fit the data between fit_start and fit_stop + Output: + On output all the data above fit_start is replaced by the fitted tail + and the new moments are included in the Green's function + """ + + # Turn known_coefs into a numpy array if ever it is not already the case + known_coef = fixed_coef + + # Change the order_max + # It is assumed that any known_coef will start at order -1 + self.tail = TailGf(shape = (self.N1,self.N2), size = order_max+2, order_min = -1) + + # Fill up two arrays with the frequencies and values over the range of interest + ninit, nstop = 0, -1 + x = [] + for om in self.mesh: + if (om.imag < fit_start): ninit = ninit+1 + if (om.imag <= fit_stop): nstop = nstop+1 + if (om.imag <= fit_stop and om.imag >= fit_start): x += [om] + omegas = numpy.array(x) + values = self.data[ninit:nstop+1,:,:] + + # Loop over the indices of the Green's function + for n1,indR in enumerate(self.indicesR): + for n2,indL in enumerate(self.indicesL): + + # Construct the part of the fitting functions which is known + f_known = numpy.zeros((len(omegas)),numpy.complex) + for order in range(len(known_coef[n1][n2])): + f_known += known_coef[n1][n2][order]*omegas**(1-order) + + # Compute how many free parameters we have and give an initial guess + len_param = order_max-len(known_coef[n1][n2])+2 + p0 = len_param*[1.0] + + # This is the function to be minimized, the diff between the original + # data in values and the fitting function + def fct(p): + y_fct = 1.0*f_known + for order in range(len_param): + y_fct += p[order]*omegas**(1-len(known_coef[n1][n2])-order) + y_fct -= values[:,n1,n2] + return abs(y_fct) + + # Now call the minimizing function + sol = leastsq(fct, p0, maxfev=1000*len_param) + + # Put the known and the new found moments in the tail + for order in range(len(known_coef[n1][n2])): + self.tail[order-1][n1,n2] = numpy.array([[ known_coef[n1][n2][order] ]]) + for order, moment in enumerate(sol[0]): + self.tail[len(known_coef[n1][n2])+order-1][n1,n2] = numpy.array([[ moment ]]) + + # Replace then end of the Green's function by the tail + if replace_tail: self.replace_by_tail(ninit); diff --git a/pytriqs/gf/local/gf_imtime.py b/pytriqs/gf/local/gf_imtime.py new file mode 100644 index 00000000..34ecbd8a --- /dev/null +++ b/pytriqs/gf/local/gf_imtime.py @@ -0,0 +1,70 @@ +from gf import GfImTime_cython, MeshImTime, TailGf +from gf_generic import GfGeneric +import numpy +from tools import get_indices_in_dict +from nothing import Nothing +import impl_plot + +class GfImTime ( GfGeneric, GfImTime_cython ) : + def __init__(self, **d): + """ + The constructor have two variants : you can either provide the mesh in + Matsubara frequencies yourself, or give the parameters to build it. + All parameters must be given with keyword arguments. + + GfImTime(indices, beta, statistic, n_points, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``beta``: Inverse Temperature + * ``statistic``: 'F' or 'B' + * ``n_points`` : Number of time points in the mesh + * ``data``: A numpy array of dimensions (len(indices),len(indices),n_points) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + GfImTime (indices, mesh, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``mesh``: a MeshGf object, such that mesh.TypeGF== GF_Type.Imaginary_Time + * ``data``: A numpy array of dimensions (len(indices),len(indices),n_points) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + .. warning:: + + The Green function take a **view** of the array data, and a **reference** to the tail. + + """ + mesh = d.pop('mesh',None) + if mesh is None : + if 'beta' not in d : raise ValueError, "beta not provided" + beta = float(d.pop('beta')) + n_max = d.pop('n_points',10000) + stat = d.pop('statistic','F') + kind = d.pop('kind','H') + mesh = MeshImTime(beta,stat,n_max,kind) + + self.dtype = numpy.float64 + indices_pack = get_indices_in_dict(d) + indicesL, indicesR = indices_pack + N1, N2 = len(indicesL),len(indicesR) + data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype ) + tail = d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2), size=10, order_min=-1) + symmetry = d.pop('symmetry', Nothing()) + name = d.pop('name','g') + assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys() + + GfGeneric.__init__(self, mesh, data, tail, symmetry, indices_pack, name, GfImTime) + GfImTime_cython.__init__(self, mesh, data, tail) + + #-------------- PLOT --------------------------------------- + + def _plot_(self, opt_dict): + """ Plot protocol. opt_dict can contain : + * :param RI: 'R', 'I', 'RI' [ default] + * :param x_window: (xmin,xmax) or None [default] + * :param name: a string [default ='']. If not '', it remplaces the name of the function just for this plot. + """ + has_complex_value = False + return impl_plot.plot_base( self, opt_dict, r'$\tau$', lambda name : r'%s$(\tau)$'%name, has_complex_value , list(self.mesh) ) + diff --git a/pytriqs/gf/local/gf_legendre.py b/pytriqs/gf/local/gf_legendre.py new file mode 100644 index 00000000..ae58ad51 --- /dev/null +++ b/pytriqs/gf/local/gf_legendre.py @@ -0,0 +1,67 @@ +from gf import GfLegendre_cython, MeshLegendre, TailGf +from gf_generic import GfGeneric +import numpy +from tools import get_indices_in_dict +from nothing import Nothing +import impl_plot + +class GfLegendre ( GfGeneric, GfLegendre_cython ) : + def __init__(self, **d): + """ + The constructor have two variants : you can either provide the mesh in + Matsubara frequencies yourself, or give the parameters to build it. + All parameters must be given with keyword arguments. + + GfLegendre(indices, beta, statistic, n_points, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``beta``: Inverse Temperature + * ``statistic``: 'F' or 'B' + * ``n_points`` : Number of legendre points in the mesh + * ``data``: A numpy array of dimensions (len(indices),len(indices),n_points) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + GfLegendre (indices, mesh, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``mesh``: a MeshGf object, such that mesh.TypeGF== GF_Type.Imaginary_Time + * ``data``: A numpy array of dimensions (len(indices),len(indices),n_points) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + .. warning:: + + The Green function take a **view** of the array data, and a **reference** to the tail. + + """ + mesh = d.pop('mesh',None) + if mesh is None : + if 'beta' not in d : raise ValueError, "beta not provided" + beta = float(d.pop('beta')) + stat = d.pop('statistic','F') + n_max = d.pop('n_points',30) + mesh = MeshLegendre(beta,stat,n_max) + + self.dtype = numpy.float64 + indices_pack = get_indices_in_dict(d) + indicesL, indicesR = indices_pack + N1, N2 = len(indicesL),len(indicesR) + data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype ) + tail = d.pop('tail',Nothing()) + symmetry = d.pop('symmetry',None) + name = d.pop('name','g') + assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys() + + GfGeneric.__init__(self, mesh, data, tail, symmetry, indices_pack, name, GfLegendre) + GfLegendre_cython.__init__(self, mesh, data) + + #-------------- PLOT --------------------------------------- + + def _plot_(self, opt_dict): + """ Plot protocol. opt_dict can contain : + * :param RI: 'R', 'I', 'RI' [ default] + * :param x_window: (xmin,xmax) or None [default] + * :param name: a string [default ='']. If not '', it remplaces the name of the function just for this plot. + """ + return impl_plot.plot_base( self, opt_dict, r'$l_n$', lambda name : r'%s$(l_n)$'%name, False, list(self.mesh) ) diff --git a/pytriqs/gf/local/gf_refreq.py b/pytriqs/gf/local/gf_refreq.py new file mode 100644 index 00000000..15cbfd77 --- /dev/null +++ b/pytriqs/gf/local/gf_refreq.py @@ -0,0 +1,67 @@ +from gf import GfReFreq_cython, MeshReFreq, TailGf +from gf_generic import GfGeneric +import numpy +from tools import get_indices_in_dict +import impl_plot + +class GfReFreq ( GfGeneric, GfReFreq_cython ) : + def __init__(self, **d): + """ + The constructor have two variants : you can either provide the mesh in + Matsubara frequencies yourself, or give the parameters to build it. + All parameters must be given with keyword arguments. + + GfReFreq(indices, window, n_points, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``window``: a tuple (omega_min, omega_max) + * ``n_points`` : Number of frequency points in the mesh + * ``data``: A numpy array of dimensions (len(indices),len(indices),n_points) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + GfReFreq (indices, mesh, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``mesh``: a MeshGf object, such that mesh.TypeGF== GF_Type.Imaginary_Time + * ``data``: A numpy array of dimensions (len(indices),len(indices),n_points) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + .. warning:: + + The Green function take a **view** of the array data, and a **reference** to the tail. + + """ + mesh = d.pop('mesh',None) + if mesh is None : + window = d.pop('window') + omega_min = window[0] + omega_max = window[1] + n_max = d.pop('n_points',10000) + kind = d.pop('kind','F') + mesh = MeshReFreq(omega_min, omega_max, n_max, kind) + + self.dtype = numpy.complex_ + indices_pack = get_indices_in_dict(d) + indicesL, indicesR = indices_pack + N1, N2 = len(indicesL),len(indicesR) + data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype ) + tail= d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2), size=10, order_min=-1) + symmetry = d.pop('symmetry',None) + name = d.pop('name','g') + assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys() + + GfGeneric.__init__(self, mesh, data, tail, symmetry, indices_pack, name, GfReFreq) + GfReFreq_cython.__init__(self, mesh, data, tail) + + #-------------- PLOT --------------------------------------- + + def _plot_(self, opt_dict): + """ Plot protocol. opt_dict can contain : + * :param RI: 'R', 'I', 'RI' [ default] + * :param x_window: (xmin,xmax) or None [default] + * :param name: a string [default ='']. If not '', it remplaces the name of the function just for this plot. + """ + return impl_plot.plot_base(self, opt_dict, r'$\omega$', lambda name : r'%s$(\omega)$'%name, True, list(self.mesh)) + diff --git a/pytriqs/gf/local/gf_retime.py b/pytriqs/gf/local/gf_retime.py new file mode 100644 index 00000000..b6e5c798 --- /dev/null +++ b/pytriqs/gf/local/gf_retime.py @@ -0,0 +1,67 @@ +from gf import GfReTime_cython, MeshReTime, TailGf +from gf_generic import GfGeneric +import numpy +from tools import get_indices_in_dict +import impl_plot + +class GfReTime ( GfGeneric, GfReTime_cython ) : + def __init__(self, **d): + """ + The constructor have two variants : you can either provide the mesh in + Matsubara frequencies yourself, or give the parameters to build it. + All parameters must be given with keyword arguments. + + GfReTime(indices, window, n_points, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``window``: a tuple (t_min, t_max) + * ``n_points`` : Number of time points in the mesh + * ``data``: A numpy array of dimensions (len(indices),len(indices),n_points) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + GfReTime (indices, mesh, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``mesh``: a MeshGf object, such that mesh.TypeGF== GF_Type.Imaginary_Time + * ``data``: A numpy array of dimensions (len(indices),len(indices),n_points) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + .. warning:: + + The Green function take a **view** of the array data, and a **reference** to the tail. + + """ + mesh = d.pop('mesh',None) + if mesh is None : + window = d.pop('window') + t_min = window[0] + t_max = window[1] + n_max = d.pop('n_points',10000) + kind = d.pop('kind','F') + mesh = MeshReTime(t_min, t_max, n_max, kind) + + self.dtype = numpy.complex_ + indices_pack = get_indices_in_dict(d) + indicesL, indicesR = indices_pack + N1, N2 = len(indicesL),len(indicesR) + data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype ) + tail= d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2), size=10, order_min=-1) + symmetry = d.pop('symmetry',None) + name = d.pop('name','g') + assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys() + + GfGeneric.__init__(self, mesh, data, tail, symmetry, indices_pack, name, GfReTime) + GfReTime_cython.__init__(self, mesh, data, tail) + + #-------------- PLOT --------------------------------------- + + def _plot_(self, opt_dict): + """ Plot protocol. opt_dict can contain : + * :param RI: 'R', 'I', 'RI' [ default] + * :param x_window: (xmin,xmax) or None [default] + * :param name: a string [default ='']. If not '', it remplaces the name of the function just for this plot. + """ + return impl_plot.plot_base(self, opt_dict, r'$\t$', lambda name : r'%s$(\t)$'%name, True, list(self.mesh)) + diff --git a/pytriqs/gf/local/gf_two_real_times.py b/pytriqs/gf/local/gf_two_real_times.py new file mode 100644 index 00000000..9cefb025 --- /dev/null +++ b/pytriqs/gf/local/gf_two_real_times.py @@ -0,0 +1,69 @@ +from gf import GfTwoRealTime_cython, MeshTwoRealTime, MeshReTime, TailGf +from gf_generic import GfGeneric +import numpy +from tools import get_indices_in_dict +import impl_plot + +class GfTwoRealTime( GfGeneric, GfTwoRealTime_cython ) : + def __init__(self, **d): + """ + The constructor have two variants : you can either provide the mesh in + Matsubara frequencies yourself, or give the parameters to build it. + All parameters must be given with keyword arguments. + + GfTwoRealTime(indices, window, n_points, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``window``: a tuple (t_min, t_max) + * ``n_points`` : Number of time points in the mesh + * ``data``: A numpy array of dimensions (len(indices),len(indices),n_points) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + GfReTime (indices, mesh, data, tail, name) + + * ``indices``: a list of indices names of the block + * ``mesh``: a MeshGf object, such that mesh.TypeGF== GF_Type.Imaginary_Time + * ``data``: A numpy array of dimensions (len(indices),len(indices),n_points) representing the value of the Green function on the mesh. + * ``tail``: the tail + * ``name``: a name of the GF + + .. warning:: + + The Green function take a **view** of the array data, and a **reference** to the tail. + + """ + mesh = d.pop('mesh',None) + if mesh is None : + window = d.pop('window') + t_min = window[0] + t_max = window[1] + n_max = d.pop('n_points',10000) + kind = d.pop('kind','F') + mesh = MeshTwoRealTime(t_max, n_max) + #mesh = MeshTwoRealTime(t_min, t_max, n_max) + #mesh = MeshReTime(t_min, t_max, n_max, 'F') + + self.dtype = numpy.complex_ + indices_pack = get_indices_in_dict(d) + indicesL, indicesR = indices_pack + N1, N2 = len(indicesL),len(indicesR) + data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype ) + symmetry = d.pop('symmetry',None) + name = d.pop('name','g') + assert len(d) ==0, "Unknown parameters in GfTwoRealTime constructions %s"%d.keys() + + GfGeneric.__init__(self, mesh, data, None, symmetry, indices_pack, name, GfTwoRealTime) + GfTwoRealTime_cython.__init__(self, mesh, data) + + #-------------- PLOT --------------------------------------- + + def _plot_(self, opt_dict): + """ Plot protocol. opt_dict can contain : + * :param RI: 'R', 'I', 'RI' [ default] + * :param x_window: (xmin,xmax) or None [default] + * :param name: a string [default ='']. If not '', it remplaces the name of the function just for this plot. + """ + # NOT CHANGED + return impl_plot.plot_base(self, opt_dict, r'$\t$', lambda name : r'%s$(\t)$'%name, True, list(self.mesh)) + diff --git a/pytriqs/gf/local/imfreq.pxd b/pytriqs/gf/local/imfreq.pxd new file mode 100644 index 00000000..1df5476f --- /dev/null +++ b/pytriqs/gf/local/imfreq.pxd @@ -0,0 +1,56 @@ +cdef extern from "triqs/gf/imfreq.hpp" namespace "triqs::gf" : + + cdef cppclass imfreq_domain : + double beta + statistic_enum statistic + imfreq_domain () + + #cdef cppclass mesh_imfreq "triqs::gf::linear_mesh" : + cdef cppclass mesh_imfreq "triqs::gf::linear_mesh>" : + mesh_imfreq () + mesh_imfreq (mesh_imfreq &) + imfreq_domain & domain() + double x_min() + long size() + bint operator ==( mesh_imfreq &) + + cdef mesh_imfreq make_mesh_imfreq "triqs::gf::make_gf_mesh" (double beta, statistic_enum S, size_t n_max) + #cdef mesh_imfreq make_mesh_imfreq "triqs::gf::gf_implementation::gf_factories::make_mesh" (double beta, statistic_enum S, size_t n_max) + + cdef cppclass gf_imfreq "triqs::python_tools::cython_proxy >" : + gf_imfreq() + gf_imfreq(gf_imfreq &) + # The constructor must be no_except, or the cython code won't be correct... + gf_imfreq(mesh_imfreq, array_view[dcomplex, THREE], tail, nothing) #except + + void operator << (gf_imfreq &) + mesh_imfreq mesh() + array_view[dcomplex, THREE] data() + tail singularity() + +cdef extern from "triqs/gf/imfreq.hpp" : + cdef void h5_write (h5_group, char *, gf_imfreq &) + +cdef extern from "triqs/utility/serialization.hpp" : + cdef std_string boost_serialize "triqs::serialize" (gf_imfreq &) + cdef void boost_unserialize_into "triqs::deserialize_into_view" (std_string, gf_imfreq &) + +# Python -> C +cdef gf_imfreq as_gf_imfreq (g) except + + +# C -> Python +cdef make_GfImFreq (gf_imfreq x, indices_pack=*, name=*) + +############### Blocks of Im Freq ######################### + +cdef extern from "triqs/gf/block.hpp" namespace "triqs::gf" : + + cdef cppclass gf_block_imfreq "triqs::python_tools::cython_proxy>>" : + gf_block_imfreq() + gf_imfreq & operator [](int) + discrete_mesh & mesh() + + cdef gf_block_imfreq make_gf_block_imfreq "triqs::gf::make_gf_view>" ( vector[gf_imfreq] &) + +cdef gf_block_imfreq as_gf_block_imfreq (G) except + +cdef make_BlockGfImFreq (gf_block_imfreq G, block_indices_pack=*, name=*) + diff --git a/pytriqs/gf/local/imfreq.pyx b/pytriqs/gf/local/imfreq.pyx new file mode 100644 index 00000000..76c3d712 --- /dev/null +++ b/pytriqs/gf/local/imfreq.pyx @@ -0,0 +1,81 @@ +from gf_imfreq import GfImFreq + +cdef class GfImFreq_cython: + + cdef gf_imfreq _c + + def __init__(self, MeshImFreq mesh, data, TailGf tail): + self._c = gf_imfreq (mesh._c, array_view[dcomplex,THREE](data), tail._c , nothing()) + + def __write_hdf5_cython__ (self, gr , char * key) : + h5_write (make_h5_group(gr), key, self._c) + + def set_from_fourier(self,GfImTime_cython gt) : + """Fills self with the Fourier transform of gt""" + self._c << lazy_fourier( gt._c ) + + def set_from_legendre(self, GfLegendre_cython gl) : + """Fills self with the Legendre transform of gl""" + self._c << lazy_legendre_imfreq(gl._c) + + def density(self): + return density(self._c).to_python() + + def __dealloc__ (self): + pass + +#---------------- Reading from h5 --------------------------------------- + +def h5_read_GfImFreq(gr, key): + try: + indicesL = gr[key]['indices']['left'] + indicesR = gr[key]['indices']['right'] + pack = [indicesL, indicesR] + except: + pack = [] + try: + name = gr[key]['name'] + except: + name = key + return make_GfImFreq(h5_extractor[gf_imfreq]()(make_h5_group(gr),key), pack, name) + +from pytriqs.archive.hdf_archive_schemes import register_class +register_class (GfImFreq, read_fun = h5_read_GfImFreq) + +#---------------- Convertions functions --------------------------------------- + +# Python -> C +cdef gf_imfreq as_gf_imfreq (g) except +: + return (g)._c + +# C -> Python. Do NOT add except + +cdef make_GfImFreq (gf_imfreq x, indices_pack = [], name = "g"): + data = x.data().to_python() + if indices_pack == []: + indices_pack = [range(data.shape[1]), range(data.shape[2])] + return GfImFreq( + mesh = make_MeshImFreq (x.mesh()), + data = data, + tail = make_TailGf (x.singularity()), + indices_pack = indices_pack, + name = name) + +# Python -> C for blocks +cdef gf_block_imfreq as_gf_block_imfreq (G) except +: + cdef vector[gf_imfreq] v_c + for n,g in G: + v_c.push_back(as_gf_imfreq(g)) + return make_gf_block_imfreq (v_c) + +# C -> Python for block +cdef make_BlockGfImFreq (gf_block_imfreq G, block_indices_pack = [], name = "G"): + gl = [] + name_list = G.mesh().domain().names() + if block_indices_pack == []: + for i,n in enumerate(name_list): + sha = G[i].data().to_python().shape[1:3] + block_indices_pack.append( [range(sha[0]), range(sha[1])] ) + for i,n in enumerate(name_list): + gl.append( make_GfImFreq(G[i], block_indices_pack[i]) ) + return BlockGf( name_list = name_list, block_list = gl, name = name ) + diff --git a/pytriqs/gf/local/impl_plot.py b/pytriqs/gf/local/impl_plot.py new file mode 100644 index 00000000..5dccb7fd --- /dev/null +++ b/pytriqs/gf/local/impl_plot.py @@ -0,0 +1,53 @@ +from pytriqs.plot.protocol import clip_array +import numpy + +class PlotWrapperPartialReduce: + """ Internal Use""" + def __init__(self, obj, **opt) : + self.obj, self.opt = obj,opt + def _plot_(self,Options) : + Options.update(self.opt) + return self.obj._plot_(Options) + +#---------------- + +def plot_base (self, opt_dict, xlabel, ylabel, use_ris, X): + """ Plot protocol. opt_dict can contain : + * :param RIS: 'R', 'I', 'S', 'RI' [ default] + * :param x_window: (xmin,xmax) or None [default] + * :param Name: a string [default ='']. If not '', it remplaces the name of the function just for this plot. + """ + Name = opt_dict.pop('name', '' ) # consume it + NamePrefix = opt_dict.pop('NamePrefix', '' ) # consume it + if Name and NamePrefix : raise ValueError, 'Name and NamePrefix can not be used at the same time' + if NamePrefix : name_save, self.name = self.name, Name or NamePrefix + + rx = opt_dict.pop('x_window',None ) # consume it + X = numpy.array(X).real + sl = clip_array (X, *rx) if rx else slice(len(X)) # the slice due to clip option x_window + + def mdic( prefix, f) : + return [{'type' : "XY", + 'xlabel' : xlabel, + 'ylabel' : ylabel (self.name), + 'xdata' : X[sl], + 'label' : Name if Name else prefix + B.name , + 'ydata' : f( B.data[sl,0,0] ) } for (i,j,B) in self ] + + if use_ris : + ris = opt_dict.pop('RI','RI') + if ris == "R" : + res = mdic( 'Re ', lambda x : x.real) + elif ris == "I" : + res = mdic( 'Im ', lambda x : x.imag) + elif ris == "S" : + res = mdic( '', lambda x : -1/numpy.pi *x.imag) + elif ris == 'RI' : + res = mdic( 'Re ', lambda x : x.real) + mdic( 'Im ', lambda x : x.imag) + else : + raise ValueError, "RIS flags meaningless %s"%ris + else: + res = mdic( '', lambda x : x) + + if NamePrefix: self.name = name_save + return res diff --git a/pytriqs/gf/local/imtime.pxd b/pytriqs/gf/local/imtime.pxd new file mode 100644 index 00000000..0b99afc9 --- /dev/null +++ b/pytriqs/gf/local/imtime.pxd @@ -0,0 +1,57 @@ +cdef extern from "triqs/gf/imtime.hpp" namespace "triqs::gf" : + + cdef cppclass imtime_domain : + double beta + statistic_enum statistic + imtime_domain () + + #cdef cppclass mesh_imtime "triqs::gf::linear_mesh" : + cdef cppclass mesh_imtime "triqs::gf::linear_mesh>" : + mesh_imtime () + mesh_imtime (mesh_imtime &) + imtime_domain & domain() + double x_min() + long size() + long kind() + bint operator ==( mesh_imtime &) + + cdef mesh_imtime make_mesh_imtime "triqs::gf::make_gf_mesh" (double beta, statistic_enum S, size_t n_time_slices, mesh_enum mk) + #cdef mesh_imtime make_mesh_imtime "triqs::gf::gf_factories::make_mesh" (double beta, statistic_enum S, size_t n_time_slices, mesh_enum mk) + + cdef cppclass gf_imtime "triqs::python_tools::cython_proxy>" : + gf_imtime() + gf_imtime(gf_imtime &) + # The constructor must be no_except, or the cython code won't be correct... + gf_imtime(mesh_imtime, array_view[double, THREE], tail, nothing) #except + + void operator << (gf_imtime &) + mesh_imtime mesh() + array_view[double, THREE] data() + tail singularity() + +cdef extern from "triqs/gf/imtime.hpp" : + cdef void h5_write (h5_group, char *, gf_imtime &) + +cdef extern from "triqs/utility/serialization.hpp" : + cdef std_string boost_serialize "triqs::serialize" (gf_imtime &) + cdef void boost_unserialize_into "triqs::deserialize_into_view" (std_string, gf_imtime &) + +# Python -> C +cdef gf_imtime as_gf_imtime (g) except + + +# C -> Python +cdef make_GfImTime (gf_imtime x, indices_pack=*, name=*) + +############### Blocks of Im Time ######################### + +cdef extern from "triqs/gf/block.hpp" namespace "triqs::gf" : + + cdef cppclass gf_block_imtime "triqs::python_tools::cython_proxy>>" : + gf_block_imtime() + gf_imtime & operator [](int) + discrete_mesh & mesh() + + cdef gf_block_imtime make_gf_block_imtime "triqs::gf::make_gf_view>" ( vector[gf_imtime] &) + +cdef gf_block_imtime as_gf_block_imtime (G) except + +cdef make_BlockGfImTime (gf_block_imtime G, block_indices_pack=*, name=*) + diff --git a/pytriqs/gf/local/imtime.pyx b/pytriqs/gf/local/imtime.pyx new file mode 100644 index 00000000..d8d54c5e --- /dev/null +++ b/pytriqs/gf/local/imtime.pyx @@ -0,0 +1,83 @@ +from gf_imtime import GfImTime + +cdef class GfImTime_cython: + + cdef gf_imtime _c + + def __init__(self, MeshImTime mesh, data, TailGf tail): + self._c = gf_imtime (mesh._c, array_view[double,THREE](data), tail._c, nothing()) + + def __write_hdf5_cython__ (self, gr , char * key) : + h5_write (make_h5_group(gr), key, self._c) + + def set_from_inverse_fourier(self,GfImFreq_cython gw) : + """Fills self with the Inverse Fourier transform of gw""" + self._c << lazy_inverse_fourier( gw._c) + + def set_from_legendre(self, GfLegendre_cython gl) : + """Fills self with the Legendre transform of gl""" + self._c << lazy_legendre_imtime(gl._c) + + def __dealloc__ (self): + pass + +#---------------- Reading from h5 --------------------------------------- + +def h5_read_GfImTime(gr, key): + try: + indicesL = gr[key]['indices']['left'] + indicesR = gr[key]['indices']['right'] + pack = [indicesL, indicesR] + except: + pack = [] + try: + name = gr[key]['name'] + except: + name = key + return make_GfImTime(h5_extractor[gf_imtime]()(make_h5_group(gr),key), pack, name) + +from pytriqs.archive.hdf_archive_schemes import register_class +register_class (GfImTime, read_fun = h5_read_GfImTime) + +#---------------- Convertions functions --------------------------------------- + +# Python -> C +cdef gf_imtime as_gf_imtime (g) except +: + return (g)._c + +# C -> Python. Do NOT add except + +cdef make_GfImTime (gf_imtime x, indices_pack = [], name = "g"): + data = x.data().to_python() + if indices_pack == []: + indices_pack = [range(data.shape[1]), range(data.shape[2])] + else : + # check that the dimensions are ok + assert len(indices_pack)==2 + assert len(indices_pack[0]) == data.shape[1] + assert len(indices_pack[1]) == data.shape[2] + return GfImTime( + mesh = make_MeshImTime (x.mesh()), + data = data, + tail = make_TailGf (x.singularity()), + indices_pack = indices_pack, + name = name) + +# Python -> C for blocks +cdef gf_block_imtime as_gf_block_imtime (G) except +: + cdef vector[gf_imtime] v_c + for n,g in G: + v_c.push_back(as_gf_imtime(g)) + return make_gf_block_imtime (v_c) + +# C -> Python for block +cdef make_BlockGfImTime (gf_block_imtime G, block_indices_pack = [], name = "G"): + gl = [] + name_list = G.mesh().domain().names() + if block_indices_pack == []: + for i,n in enumerate(name_list): + sha = G[i].data().to_python().shape[1:3] + block_indices_pack.append( [range(sha[0]), range(sha[1])] ) + for i,n in enumerate(name_list): + gl.append( make_GfImTime(G[i], block_indices_pack[i]) ) + return BlockGf( name_list = name_list, block_list = gl, name = name ) + diff --git a/pytriqs/gf/local/inverse.py b/pytriqs/gf/local/inverse.py new file mode 100644 index 00000000..c1e12426 --- /dev/null +++ b/pytriqs/gf/local/inverse.py @@ -0,0 +1,32 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +import lazy_expressions, descriptors + +def inverse(x): + if descriptors.is_lazy(x): + return lazy_expressions.lazy_function("inverse", inverse) (x) + assert hasattr(x,'invert') and hasattr(x,'copy') + cop = x.copy() + cop.invert() + return cop + diff --git a/pytriqs/gf/local/lazy_expressions.py b/pytriqs/gf/local/lazy_expressions.py new file mode 100644 index 00000000..f32783a4 --- /dev/null +++ b/pytriqs/gf/local/lazy_expressions.py @@ -0,0 +1,187 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +__all__ = ['LazyExpr', 'LazyExprTerminal', 'eval_expr_with_context', 'lazy', 'lazy_function', 'transform', 'eval_expr'] + +class __aux(object): + + def __add__(self, y): return LazyExpr("+", LazyExpr(self), LazyExpr(y)) + def __sub__(self, y): return LazyExpr("-", LazyExpr(self), LazyExpr(y)) + def __mul__(self, y): return LazyExpr("*", LazyExpr(self), LazyExpr(y)) + def __div__(self, y): return LazyExpr("/", LazyExpr(self), LazyExpr(y)) + + def __radd__(self, y): return LazyExpr("+", LazyExpr(y), LazyExpr(self)) + def __rsub__(self, y): return LazyExpr("-", LazyExpr(y), LazyExpr(self)) + def __rmul__(self, y): return LazyExpr("*", LazyExpr(y), LazyExpr(self)) + def __rdiv__(self, y): return LazyExpr("/", LazyExpr(y), LazyExpr(self)) + + def __iadd__(self, y): return self.set_from(self+y) + def __isub__(self, y): return self.set_from(self-y) + def __imul__(self, y): return self.set_from(self*y) + def __idiv__(self, y): return self.set_from(self/y) + + def __call__(self, *args): return LazyExpr("F", make_lazy(self), *map(make_lazy, args)) + +class LazyExprTerminal (__aux): + pass + +class LazyExpr (__aux): + """ + """ + + def __init__ (self, *args): + if len(args) == 1: + a0 = args[0] + self.tag, self.childs = (a0.tag, a0.childs) if isinstance(a0, self.__class__) else ("T", [a0]) + elif len(args) >1: + self.tag, self.childs = args[0], args[1:] + else: raise ValueError, "too few arguments" + + def copy(self): + """ Deep copy""" + return LazyExpr(self.tag, self.childs) + + def set_from(self, y): + """ self:= y """ + self.tag, self.childs = tmp.tag, tmp.childs + return self + + def is_terminal(self): + """Returns true iif the expression is a terminal """ + return self.tag=="T" + + def get_terminal(self): + """Returns the terminal if the expression is a terminal else None """ + return self.childs[0] if self.tag=="T" else None + + def __aux_print(self, F): + op_priority = {'T': 100, "+": 1 , '-': 1, '*': 2, '/': 2} + if self.tag == "T": return F(self.childs[0]) + if self.tag == "F": + return reduce (lambda s, e: s+ F(e), self.childs[1:], self.childs[0].get_terminal()[0] + "(" ) + ')' + par = lambda op, e: "%s"%e if op_priority[e.tag] >= op_priority[op] else "(%s)"%e + return "%s %s %s "%(par(self.tag , self.childs[0]), self.tag , par(self.tag , self.childs[1])) + + def __str__(self): return self.__aux_print(str) + def __repr__(self): return self.__aux_print(repr) + + #def __call__ (self, *args, **kwargs): + + +#----------------------------------------------------- + +def eval_expr_with_context(eval_term, expr ): + + if expr.tag == "T": return eval_term(expr.childs[0]) #eval the terminals + + if expr.tag == "F": + f= expr.childs[0].get_terminal()[1] + return f (*map(lambda e:eval_expr_with_context(eval_term, e) , expr.childs[1:]) ) + + # Binary operations: + ops = { "+": lambda x, y: x + y, "-": lambda x, y: x - y, "*": lambda x, y: x * y, "/": lambda x, y: x / y } + return ops[expr.tag] (*map(lambda e:eval_expr_with_context(eval_term, e) , expr.childs) ) + +#----------------------------------------------------- + +def make_lazy(x): return LazyExpr(x) + +#----------------------------------------------------- + +def lazy_function(name, F): + return LazyExpr("T", (name, F)) + +#----------------------------------------------------- + +def transform (expr, Fnode, Fterm = lambda x: x ): + """Given two functions + Fnode(tag, childs) -> (tag, childs) + Fterm(x) -> x' + it transforms the expression recursively + """ + if expr.tag == "T": return LazyExpr("T", Fterm(expr.childs[0])) + tag, ch = Fnode (expr.tag, map(lambda e: transform (e, Fnode), expr.childs)) + ch = map(lambda x: LazyExpr(x), ch) + return LazyExpr (tag, *ch) + +#----------------------------------------------------- + +def all_terminals (expr): + """Generate all terminals of an expression""" + if expr.tag == "T": + yield expr.childs[0] + else: + for ch in expr.childs: + for t in all_terminals(ch): + yield t + +def eval_expr (expr): +#def eval_expr_or_pass (expr): + """ + If expr is not a LazyExpr: returns expr unchanged. + Otherwise, tries to eval it by looking for some element in the tree that can create the evaluation context and is not purely abstract + """ + if not isinstance (expr, LazyExpr): return expr # do nothing + # first take all terminals + C = [ t.__lazy_expr_eval_context__() for t in all_terminals(expr) if hasattr(t, "__lazy_expr_eval_context__") ] + if C == []: raise ValueError, "Evaluation impossible: expression is purely abstract" + all_equal = reduce (lambda x, y: x and y , [ C[0] == x for x in C ]) + if not all_equal: raise ValueError, "Evaluation impossible: various terminals lead to incompatible evaluation contexts: their type are not compatible for binary ops" + C = C[0] + return eval_expr_with_context(C, expr) + +#--------------- TEST -------------------------------------- + +if __name__ == "__main__": + + class T (LazyExprTerminal): + def __init__(self, n): self.name = n + def __repr__(self): return self.name + + g1, g2 = T("g1"), T("g2") + a = 2 * g1 + g2/3 + 5 + print a + + def e_t(x): + d = { "g1": 10, "g2": 100} + return d[x.name] if isinstance(x, T) else x + + assert eval_expr_with_context(e_t, a) ==58 + + def find_sca(tag, childs): + if tag =="+": + t = childs[1].get_terminal() + if t: childs[1] = T("$$" + str(childs[1])) + return (tag, childs) + + b= transform(a, find_sca) + print b + + # a lazy function: + def f (x): return -x + + fa = lazy_function("f", f) (a) + print fa, eval_expr_with_context(e_t, fa) + + assert eval_expr_with_context(e_t, fa) == f(eval_expr_with_context(e_t, a) ) + + diff --git a/pytriqs/gf/local/legendre.pxd b/pytriqs/gf/local/legendre.pxd new file mode 100644 index 00000000..dac6c288 --- /dev/null +++ b/pytriqs/gf/local/legendre.pxd @@ -0,0 +1,54 @@ +cdef extern from "triqs/gf/legendre.hpp" namespace "triqs::gf" : + + cdef cppclass legendre_domain : + size_t Nmax + double beta + statistic_enum statistic + legendre_domain () + + #cdef cppclass mesh_legendre "triqs::gf::discrete_mesh": + cdef cppclass mesh_legendre "triqs::gf::discrete_mesh": + mesh_legendre () + mesh_legendre (mesh_legendre &) + legendre_domain & domain() + long size() + bint operator == (mesh_legendre &) + + cdef mesh_legendre make_mesh_legendre "triqs::gf::make_gf_mesh" (double beta, statistic_enum S, size_t n_leg) + #cdef mesh_legendre make_mesh_legendre "triqs::gf::gf_factories::make_mesh" (double beta, statistic_enum S, size_t n_leg) + + cdef cppclass gf_legendre "triqs::python_tools::cython_proxy>" : + gf_legendre() + gf_legendre(gf_legendre &) + gf_legendre(mesh_legendre, array_view[double, THREE], nothing, nothing) #except + + void operator << (gf_legendre &) + mesh_legendre mesh() + array_view[double, THREE] data() + +cdef extern from "triqs/gf/legendre.hpp" : + cdef void h5_write (h5_group, char *, gf_legendre &) + +cdef extern from "triqs/utility/serialization.hpp" : + cdef std_string boost_serialize "triqs::serialize" (gf_legendre &) + cdef void boost_unserialize_into "triqs::deserialize_into_view" (std_string, gf_legendre &) + +# Python -> C +cdef gf_legendre as_gf_legendre(g) except + + +# C -> Python +cdef make_GfLegendre(gf_legendre x, indices_pack=*, name=*) + +############### Blocks of Im Time ######################### + +cdef extern from "triqs/gf/block.hpp" namespace "triqs::gf" : + + cdef cppclass gf_block_legendre "triqs::python_tools::cython_proxy>>" : + gf_block_legendre() + gf_legendre & operator [](int) + discrete_mesh & mesh() + + cdef gf_block_legendre make_gf_block_legendre "triqs::gf::make_gf_view>" ( vector[gf_legendre] &) + +cdef gf_block_legendre as_gf_block_legendre (G) except + +cdef make_BlockGfLegendre (gf_block_legendre G, block_indices_pack=*, name=*) + diff --git a/pytriqs/gf/local/legendre.pyx b/pytriqs/gf/local/legendre.pyx new file mode 100644 index 00000000..65ae5a59 --- /dev/null +++ b/pytriqs/gf/local/legendre.pyx @@ -0,0 +1,81 @@ +from gf_legendre import GfLegendre + +cdef class GfLegendre_cython: + cdef gf_legendre _c + def __init__(self, MeshLegendre mesh, data): + self._c = gf_legendre(mesh._c, array_view[double,THREE](data), nothing(), nothing()) + + def __write_hdf5_cython__ (self, gr , char * key) : + h5_write (make_h5_group(gr), key, self._c) + + def set_from_imtime(self, GfImTime_cython gt) : + """Fills self with the Legendre transform of gt""" + self._c << lazy_imtime_legendre(gt._c) + + def set_from_imfreq(self, GfImFreq_cython gw) : + """Fills self with the Legendre transform of gw""" + self._c << lazy_imfreq_legendre(gw._c) + + def density(self): + return density(self._c).to_python() + + def enforce_discontinuity(self, disc): + enforce_discontinuity(self._c, array_view[double,TWO](disc)) + + def __dealloc__ (self): + pass + +#---------------- Reading from h5 --------------------------------------- + +def h5_read_GfLegendre(gr, key): + try: + indicesL = gr[key]['indices']['left'] + indicesR = gr[key]['indices']['right'] + pack = [indicesL, indicesR] + except: + pack = [] + try: + name = gr[key]['name'] + except: + name = key + return make_GfLegendre(h5_extractor[gf_legendre]()(make_h5_group(gr),key), pack, name) + +from pytriqs.archive.hdf_archive_schemes import register_class +register_class (GfLegendre, read_fun = h5_read_GfLegendre) + +#---------------- Convertions functions --------------------------------------- + +# Python -> C +cdef gf_legendre as_gf_legendre (g) except +: + return (g)._c + +# C -> Python. Do NOT add except + +cdef make_GfLegendre (gf_legendre x, indices_pack = [], name = "g"): + data = x.data().to_python() + if indices_pack == []: + indices_pack = [range(data.shape[1]), range(data.shape[2])] + return GfLegendre( + mesh = make_MeshLegendre (x.mesh()), + data = data, + indices_pack = indices_pack, + name = name) + +# Python -> C for blocks +cdef gf_block_legendre as_gf_block_legendre (G) except +: + cdef vector[gf_legendre] v_c + for n,g in G: + v_c.push_back(as_gf_legendre(g)) + return make_gf_block_legendre (v_c) + +# C -> Python for block +cdef make_BlockGfLegendre (gf_block_legendre G, block_indices_pack = [], name = "G"): + gl = [] + name_list = G.mesh().domain().names() + if block_indices_pack == []: + for i,n in enumerate(name_list): + sha = G[i].data().to_python().shape[1:3] + block_indices_pack.append( [range(sha[0]), range(sha[1])] ) + for i,n in enumerate(name_list): + gl.append( make_GfLegendre(G[i], block_indices_pack[i]) ) + return BlockGf( name_list = name_list, block_list = gl, name = name ) + diff --git a/pytriqs/gf/local/matrix_stack.pxd b/pytriqs/gf/local/matrix_stack.pxd new file mode 100644 index 00000000..dec5c32f --- /dev/null +++ b/pytriqs/gf/local/matrix_stack.pxd @@ -0,0 +1,17 @@ +include "arrays.pxd" +include "dcomplex.pxd" + +cdef extern from "" namespace "triqs::arrays": + + cdef cppclass matrix_stack "triqs::arrays::matrix_stack_view" [T]: + + matrix_stack(object) + + void iadd "operator +=" (matrix_view[T] &) except + + void isub "operator -=" (matrix_view[T] &) except + + + void imul "operator *=" (matrix_view[T] &) except + + void idiv "operator /=" (matrix_view[T] &) except + + + void invert() except + + void onsite_matmul_L_R(matrix_view[T] &, matrix_stack &, matrix_view[T] &) except + diff --git a/pytriqs/gf/local/matrix_stack.pyx b/pytriqs/gf/local/matrix_stack.pyx new file mode 100644 index 00000000..9fcc95ee --- /dev/null +++ b/pytriqs/gf/local/matrix_stack.pyx @@ -0,0 +1,34 @@ +import numpy + +class MatrixStack: + + def __init__(self, A): + """ + """ + self.data = A + self.is_double = A.dtype in [numpy.float, numpy.float64, numpy.float128, numpy.float, numpy.float_] + + def add(self, M): + if self.is_double: + matrix_stack[double](self.data).iadd(matrix_view[double](M)) + else: + matrix_stack[dcomplex](self.data).iadd(matrix_view[dcomplex](M.astype(numpy.complex))) + + def sub(self, M): + if self.is_double: + matrix_stack[double](self.data).isub(matrix_view[double](M)) + else: + matrix_stack[dcomplex](self.data).isub(matrix_view[dcomplex](M.astype(numpy.complex))) + + def matmul_L_R(self, L, D, R): + if self.is_double: + matrix_stack[double](self.data).onsite_matmul_L_R(matrix_view[double](L), matrix_stack[double](D), matrix_view[double](R)) + else: + matrix_stack[dcomplex](self.data).onsite_matmul_L_R( + matrix_view[dcomplex](L.astype(numpy.complex)), matrix_stack[dcomplex](D), matrix_view[dcomplex](R.astype(numpy.complex))) + + def invert(self): + if self.is_double: + matrix_stack[double](self.data).invert() + else: + matrix_stack[dcomplex](self.data).invert() diff --git a/pytriqs/gf/local/mesh_imfreq.pyx b/pytriqs/gf/local/mesh_imfreq.pyx new file mode 100644 index 00000000..56745cb9 --- /dev/null +++ b/pytriqs/gf/local/mesh_imfreq.pyx @@ -0,0 +1,33 @@ +cdef class MeshImFreq: + cdef mesh_imfreq _c + + def __init__(self, beta, stat, int n_max): + self._c = make_mesh_imfreq(beta,{'F' :Fermion, 'B' : Boson}[stat], n_max) + + def __len__ (self) : return self._c.size() + + property beta : + """Inverse temperature""" + def __get__(self): return self._c.domain().beta + + property statistic : + def __get__(self): return 'F' if self._c.domain().statistic==Fermion else 'B' + + def __iter__(self) : # I use the C++ generator ! + cdef mesh_pt_generator[mesh_imfreq ] g = mesh_pt_generator[mesh_imfreq ](&self._c) + while not g.at_end() : + yield g.to_point() + g.increment() + + def __richcmp__(MeshImFreq self, MeshImFreq other,int op) : + if op ==2 : # == + return self._c == other._c + + def __reduce__(self): + return self.__class__, (self.beta, self.statistic, len(self)) + +# C -> Python +cdef inline make_MeshImFreq (mesh_imfreq x) : + return MeshImFreq( x.domain().beta, 'F' if x.domain().statistic==Fermion else 'B', x.size() ) + + diff --git a/pytriqs/gf/local/mesh_imtime.pyx b/pytriqs/gf/local/mesh_imtime.pyx new file mode 100644 index 00000000..4606e325 --- /dev/null +++ b/pytriqs/gf/local/mesh_imtime.pyx @@ -0,0 +1,37 @@ +cdef class MeshImTime: + cdef mesh_imtime _c + + def __init__(self, beta, stat, int n_max, kind): + self._c = make_mesh_imtime(beta, {'F' :Fermion, 'B' : Boson}[stat], n_max, {'H':half_bins, 'F':full_bins, 'W':without_last}[kind]) + + def __len__ (self) : return self._c.size() + + property beta : + """Inverse temperature""" + def __get__(self): return self._c.domain().beta + + property kind : + """Inverse temperature""" + def __get__(self): return self._c.kind() + + property statistic : + def __get__(self): return 'F' if self._c.domain().statistic==Fermion else 'B' + + def __iter__(self) : # I use the C++ generator ! + cdef mesh_pt_generator[mesh_imtime ] g = mesh_pt_generator[mesh_imtime ](&self._c) + while not g.at_end() : + yield g.to_point() + g.increment() + + def __richcmp__(MeshImTime self, MeshImTime other,int op) : + if op ==2 : # == + return self._c == other._c + + def __reduce__(self): + return self.__class__, (self.beta, self.statistic, len(self), {half_bins: 'H', full_bins: 'F', without_last: 'W'}[self.kind]) + +# C -> Python +cdef inline make_MeshImTime ( mesh_imtime x) : + return MeshImTime( x.domain().beta, 'F' if x.domain().statistic==Fermion else 'B', + x.size(), {half_bins: 'H', full_bins: 'F', without_last: 'W'}[x.kind()] ) + diff --git a/pytriqs/gf/local/mesh_legendre.pyx b/pytriqs/gf/local/mesh_legendre.pyx new file mode 100644 index 00000000..53fb1031 --- /dev/null +++ b/pytriqs/gf/local/mesh_legendre.pyx @@ -0,0 +1,32 @@ +cdef class MeshLegendre: + cdef mesh_legendre _c + + def __init__(self, beta, stat, int n_leg): + self._c = make_mesh_legendre(beta, {'F' :Fermion, 'B' : Boson}[stat], n_leg) + + def __len__ (self) : return self._c.size() + + property beta : + """Inverse temperature""" + def __get__(self): return self._c.domain().beta + + property statistic : + def __get__(self): return 'F' if self._c.domain().statistic==Fermion else 'B' + + def __iter__(self) : # I use the C++ generator ! + cdef mesh_pt_generator[mesh_legendre ] g = mesh_pt_generator[mesh_legendre ](&self._c) + while not g.at_end() : + yield g.to_point() + g.increment() + + def __richcmp__(MeshLegendre self, MeshLegendre other,int op) : + if op ==2 : # == + return self._c == other._c + + def __reduce__(self): + return self.__class__, (self.beta, self.statistic, len(self)) + +# C -> Python +cdef inline make_MeshLegendre ( mesh_legendre x) : + return MeshLegendre( x.domain().beta, 'F' if x.domain().statistic==Fermion else 'B', x.size() ) + diff --git a/pytriqs/gf/local/mesh_refreq.pyx b/pytriqs/gf/local/mesh_refreq.pyx new file mode 100644 index 00000000..589bcb32 --- /dev/null +++ b/pytriqs/gf/local/mesh_refreq.pyx @@ -0,0 +1,34 @@ +cdef class MeshReFreq: + cdef mesh_refreq _c + + def __init__(self, double omega_min, double omega_max, int n_max, kind): + self._c = make_mesh_refreq(omega_min, omega_max, n_max, {'H':half_bins, 'F':full_bins, 'W':without_last}[kind]) + + property omega_min: + def __get__(self): return self._c.x_min() + + property omega_max: + def __get__(self): return self._c.x_max() + + property kind: + def __get__(self): return self._c.kind() + + def __len__ (self) : return self._c.size() + + def __iter__(self) : # I use the C++ generator ! + cdef mesh_pt_generator[mesh_refreq] g = mesh_pt_generator[mesh_refreq](&self._c) + while not g.at_end() : + yield g.to_point() + g.increment() + + def __richcmp__(MeshReFreq self, MeshReFreq other, int op) : + if op ==2 : # == + return self._c == other._c + + def __reduce__(self): + return self.__class__, (self.omega_min, self.omega_max, len(self), self.kind) + +# C -> Python +cdef inline make_MeshReFreq ( mesh_refreq x) : + return MeshReFreq( x.x_min(), x.x_max(), x.size(), {half_bins: 'H', full_bins: 'F', without_last: 'W'}[x.kind()] ) + diff --git a/pytriqs/gf/local/mesh_retime.pyx b/pytriqs/gf/local/mesh_retime.pyx new file mode 100644 index 00000000..0ceffbff --- /dev/null +++ b/pytriqs/gf/local/mesh_retime.pyx @@ -0,0 +1,34 @@ +cdef class MeshReTime: + cdef mesh_retime _c + + def __init__(self, double t_min, double t_max, int n_max, kind): + self._c = make_mesh_retime(t_min, t_max, n_max, {'H':half_bins, 'F':full_bins, 'W':without_last}[kind]) + + property t_min: + def __get__(self): return self._c.x_min() + + property t_max: + def __get__(self): return self._c.x_max() + + property kind: + def __get__(self): return self._c.kind() + + def __len__ (self) : return self._c.size() + + def __iter__(self) : # I use the C++ generator ! + cdef mesh_pt_generator[mesh_retime] g = mesh_pt_generator[mesh_retime](&self._c) + while not g.at_end() : + yield g.to_point() + g.increment() + + def __richcmp__(MeshReTime self, MeshReTime other, int op) : + if op ==2 : # == + return self._c == other._c + + def __reduce__(self): + return self.__class__, (self.t_min, self.t_max, len(self), self.kind) + +# C -> Python +cdef inline make_MeshReTime ( mesh_retime x) : + return MeshReTime( x.x_min(), x.x_max(), x.size(), {half_bins: 'H', full_bins: 'F', without_last: 'W'}[x.kind()] ) + diff --git a/pytriqs/gf/local/mesh_two_real_times.pyx b/pytriqs/gf/local/mesh_two_real_times.pyx new file mode 100644 index 00000000..26fece15 --- /dev/null +++ b/pytriqs/gf/local/mesh_two_real_times.pyx @@ -0,0 +1,34 @@ +cdef class MeshTwoRealTime: + cdef mesh_two_real_times _c + + def __init__(self, double tmax, double n_time_slices) : + self._c = make_mesh_two_real_times(tmax,n_time_slices) + + property t_min: + def __get__(self): return get_1d_mesh_from_2times_mesh(self._c).x_min() + + property t_max: + def __get__(self): return get_1d_mesh_from_2times_mesh(self._c).x_max() + + #property kind: + # def __get__(self): return self._c.kind() + + def __len__ (self) : return self._c.size() + + #def __iter__(self) : # I use the C++ generator ! + # cdef mesh_pt_generator[mesh_two_real_times] g = mesh_pt_generator[mesh_two_real_times](&self._c) + # while not g.at_end() : + # yield g.to_point() + # g.increment() + + def __richcmp__(MeshTwoRealTime self, MeshTwoRealTime other, int op) : + if op ==2 : # == + return self._c == other._c + + def __reduce__(self): + return self.__class__, (self.t_min, self.t_max, len(self)) #, self.kind) + +# C -> Python +cdef inline make_MeshTwoRealTime (mesh_two_real_times x) : + return MeshTwoRealTime(get_1d_mesh_from_2times_mesh(x).x_max(), get_1d_mesh_from_2times_mesh(x).size() ) + diff --git a/pytriqs/gf/local/nothing.py b/pytriqs/gf/local/nothing.py new file mode 100644 index 00000000..6f5cc3c5 --- /dev/null +++ b/pytriqs/gf/local/nothing.py @@ -0,0 +1,43 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011-2012 by M. Ferrero, 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 . +# +################################################################################ + +class Nothing (object): + + def __init__(self): pass + def __getitem__(self, key): return Nothing() + def __setitem__(self, key, val): pass + def __iadd__(self, arg): return Nothing() + def __add__(self, y): return Nothing() + def __radd__(self, y): return Nothing() + def __isub__(self, arg): return Nothing() + def __sub__(self, y): return Nothing() + def __rsub__(self, y): return Nothing() + def __imul__(self, arg): return Nothing() + def __mul__(self, arg): return Nothing() + def __rmul__(self, x): return Nothing() + def __idiv__(self, arg): return Nothing() + def __div__(self, arg): return Nothing() + def _make_slice(self, sl1, sl2): return Nothing() + def invert(self): pass + def transpose(self): return Nothing() + def conjugate(self): return Nothing() + def copy(self): return Nothing() diff --git a/pytriqs/gf/local/refreq.pxd b/pytriqs/gf/local/refreq.pxd new file mode 100644 index 00000000..0801fffd --- /dev/null +++ b/pytriqs/gf/local/refreq.pxd @@ -0,0 +1,56 @@ +cdef extern from "triqs/gf/refreq.hpp" namespace "triqs::gf" : + + cdef cppclass refreq_domain : + refreq_domain() + + #cdef cppclass mesh_refreq "triqs::gf::linear_mesh" : + cdef cppclass mesh_refreq "triqs::gf::linear_mesh" : + mesh_refreq () + mesh_refreq (mesh_refreq &) + refreq_domain & domain() + double x_min() + double x_max() + long size() + double kind() + bint operator ==( mesh_refreq &) + + cdef mesh_refreq make_mesh_refreq "triqs::gf::make_gf_mesh" (double omega_min, double omega_max, size_t n_freq, mesh_enum mk) + #cdef mesh_refreq make_mesh_refreq "triqs::gf::gf_factories::make_mesh" (double omega_min, double omega_max, size_t n_freq, mesh_enum mk) + + cdef cppclass gf_refreq "triqs::python_tools::cython_proxy>" : + gf_refreq() + gf_refreq(gf_refreq &) + # The constructor must be no_except, or the cython code won't be correct... + gf_refreq(mesh_refreq, array_view[dcomplex, THREE], tail, nothing) #except + + void operator << (gf_refreq &) + mesh_refreq mesh() + array_view[dcomplex, THREE] data() + tail singularity() + +cdef extern from "triqs/gf/refreq.hpp" : + cdef void h5_write (h5_group, char *, gf_refreq &) + +cdef extern from "triqs/utility/serialization.hpp" : + cdef std_string boost_serialize "triqs::serialize" (gf_refreq &) + cdef void boost_unserialize_into "triqs::deserialize_into_view" (std_string, gf_refreq &) + +# Python -> C +cdef gf_refreq as_gf_refreq (g) except + + +# C -> Python +cdef make_GfReFreq (gf_refreq x, indices_pack=*, name=*) + +############### Blocks of Im Time ######################### + +cdef extern from "triqs/gf/block.hpp" namespace "triqs::gf" : + + cdef cppclass gf_block_refreq "triqs::python_tools::cython_proxy>>" : + gf_block_refreq() + gf_refreq & operator [](int) + discrete_mesh & mesh() + + cdef gf_block_refreq make_gf_block_refreq "triqs::gf::make_gf_view>" ( vector[gf_refreq] &) + +cdef gf_block_refreq as_gf_block_refreq (G) except + +cdef make_BlockGfReFreq (gf_block_refreq G, block_indices_pack=*, name=*) + diff --git a/pytriqs/gf/local/refreq.pyx b/pytriqs/gf/local/refreq.pyx new file mode 100644 index 00000000..117ffc08 --- /dev/null +++ b/pytriqs/gf/local/refreq.pyx @@ -0,0 +1,78 @@ +from gf_refreq import GfReFreq + +cdef class GfReFreq_cython: + cdef gf_refreq _c + def __init__(self, MeshReFreq mesh, data, TailGf tail): + self._c = gf_refreq(mesh._c, array_view[dcomplex,THREE](data), tail._c, nothing()) + + def __write_hdf5_cython__ (self, gr , char * key) : + h5_write (make_h5_group(gr), key, self._c) + + def set_from_fourier(self, GfReTime_cython gt) : + """Fills self with the Fourier transform of gt""" + self._c << lazy_fourier( gt._c ) + + def inverse_fourier(self): + return make_GfReTime(inverse_fourier(self._c)) + + def set_from_pade(self, GfImFreq_cython gw, n_points = 100, freq_offset = 0.0) : + pade(self._c, gw._c, n_points, freq_offset) + + def __dealloc__ (self): + pass + +#---------------- Reading from h5 --------------------------------------- + +def h5_read_GfReFreq(gr, key): + try: + indicesL = gr[key]['indices']['left'] + indicesR = gr[key]['indices']['right'] + pack = [indicesL, indicesR] + except: + pack = [] + try: + name = gr[key]['name'] + except: + name = key + return make_GfReFreq(h5_extractor[gf_refreq]()(make_h5_group(gr),key), pack, name) + +from pytriqs.archive.hdf_archive_schemes import register_class +register_class (GfReFreq, read_fun = h5_read_GfReFreq) + +#---------------- Convertions functions --------------------------------------- + +# Python -> C +cdef gf_refreq as_gf_refreq (g) except +: + return (g)._c + +# C -> Python. Do NOT add except + +cdef make_GfReFreq (gf_refreq x, indices_pack = [], name = "g"): + data = x.data().to_python() + if indices_pack == []: + indices_pack = [range(data.shape[1]), range(data.shape[2])] + return GfReFreq( + mesh = make_MeshReFreq (x.mesh()), + data = data, + tail = make_TailGf (x.singularity()), + indices_pack = indices_pack, + name = name) + +# Python -> C for blocks +cdef gf_block_refreq as_gf_block_refreq (G) except +: + cdef vector[gf_refreq] v_c + for n,g in G: + v_c.push_back(as_gf_refreq(g)) + return make_gf_block_refreq (v_c) + +# C -> Python for block +cdef make_BlockGfReFreq (gf_block_refreq G, block_indices_pack = [], name = "G"): + gl = [] + name_list = G.mesh().domain().names() + if block_indices_pack == []: + for i,n in enumerate(name_list): + sha = G[i].data().to_python().shape[1:3] + block_indices_pack.append( [range(sha[0]), range(sha[1])] ) + for i,n in enumerate(name_list): + gl.append( make_GfReFreq(G[i], block_indices_pack[i]) ) + return BlockGf( name_list = name_list, block_list = gl, name = name ) + diff --git a/pytriqs/gf/local/retime.pxd b/pytriqs/gf/local/retime.pxd new file mode 100644 index 00000000..ac355153 --- /dev/null +++ b/pytriqs/gf/local/retime.pxd @@ -0,0 +1,56 @@ +cdef extern from "triqs/gf/retime.hpp" namespace "triqs::gf" : + + cdef cppclass retime_domain : + retime_domain() + + #cdef cppclass mesh_retime "triqs::gf::linear_mesh" : + cdef cppclass mesh_retime "triqs::gf::linear_mesh" : + mesh_retime () + mesh_retime (mesh_retime &) + retime_domain & domain() + double x_min() + double x_max() + long size() + double kind() + bint operator ==( mesh_retime &) + + cdef mesh_retime make_mesh_retime "triqs::gf::make_gf_mesh" (double t_min, double t_max, size_t n_freq, mesh_enum mk) + #cdef mesh_retime make_mesh_retime "triqs::gf::gf_factories::make_mesh" (double t_min, double t_max, size_t n_freq, mesh_enum mk) + + cdef cppclass gf_retime "triqs::python_tools::cython_proxy>" : + gf_retime() + gf_retime(gf_retime &) + # The constructor must be no_except, or the cython code won't be correct... + gf_retime(mesh_retime, array_view[dcomplex, THREE], tail, nothing) #except + + void operator << (gf_retime &) + mesh_retime mesh() + array_view[dcomplex, THREE] data() + tail singularity() + +cdef extern from "triqs/gf/retime.hpp" : + cdef void h5_write (h5_group, char *, gf_retime &) + +cdef extern from "triqs/utility/serialization.hpp" : + cdef std_string boost_serialize "triqs::serialize" (gf_retime &) + cdef void boost_unserialize_into "triqs::deserialize_into_view" (std_string, gf_retime &) + +# Python -> C +cdef gf_retime as_gf_retime (g) except + + +# C -> Python +cdef make_GfReTime (gf_retime x, indices_pack=*, name=*) + +############### Blocks of Im Time ######################### + +cdef extern from "triqs/gf/block.hpp" namespace "triqs::gf" : + + cdef cppclass gf_block_retime "triqs::python_tools::cython_proxy>>" : + gf_block_retime() + gf_retime & operator [](int) + discrete_mesh & mesh() + + cdef gf_block_retime make_gf_block_retime "triqs::gf::make_gf_view>" ( vector[gf_retime] &) + +cdef gf_block_retime as_gf_block_retime (G) except + +cdef make_BlockGfReTime (gf_block_retime G, block_indices_pack=*, name=*) + diff --git a/pytriqs/gf/local/retime.pyx b/pytriqs/gf/local/retime.pyx new file mode 100644 index 00000000..c2cc690a --- /dev/null +++ b/pytriqs/gf/local/retime.pyx @@ -0,0 +1,75 @@ +from gf_retime import GfReTime + +cdef class GfReTime_cython: + cdef gf_retime _c + def __init__(self, MeshReTime mesh, data, TailGf tail): + self._c = gf_retime(mesh._c, array_view[dcomplex,THREE](data), tail._c, nothing()) + + def __write_hdf5_cython__ (self, gr , char * key) : + h5_write (make_h5_group(gr), key, self._c) + + def fourier(self): + return make_GfReFreq(fourier(self._c)) + + def set_from_inverse_fourier(self, GfReFreq_cython gw) : + """Fills self with the Inverse Fourier transform of gw""" + self._c << lazy_inverse_fourier( gw._c) + + def __dealloc__ (self): + pass + +#---------------- Reading from h5 --------------------------------------- + +def h5_read_GfReTime(gr, key): + try: + indicesL = gr[key]['indices']['left'] + indicesR = gr[key]['indices']['right'] + pack = [indicesL, indicesR] + except: + pack = [] + try: + name = gr[key]['name'] + except: + name = key + return make_GfReTime(h5_extractor[gf_retime]()(make_h5_group(gr),key), pack, name) + +from pytriqs.archive.hdf_archive_schemes import register_class +register_class (GfReTime, read_fun = h5_read_GfReTime) + +#---------------- Convertions functions --------------------------------------- + +# Python -> C +cdef gf_retime as_gf_retime (g) except +: + return (g)._c + +# C -> Python. Do NOT add except + +cdef make_GfReTime (gf_retime x, indices_pack = [], name = "g"): + data = x.data().to_python() + if indices_pack == []: + indices_pack = [range(data.shape[1]), range(data.shape[2])] + return GfReTime( + mesh = make_MeshReTime (x.mesh()), + data = data, + tail = make_TailGf (x.singularity()), + indices_pack = indices_pack, + name = name) + +# Python -> C for blocks +cdef gf_block_retime as_gf_block_retime (G) except +: + cdef vector[gf_retime] v_c + for n,g in G: + v_c.push_back(as_gf_retime(g)) + return make_gf_block_retime (v_c) + +# C -> Python for block +cdef make_BlockGfReTime (gf_block_retime G, block_indices_pack = [], name = "G"): + gl = [] + name_list = G.mesh().domain().names() + if block_indices_pack == []: + for i,n in enumerate(name_list): + sha = G[i].data().to_python().shape[1:3] + block_indices_pack.append( [range(sha[0]), range(sha[1])] ) + for i,n in enumerate(name_list): + gl.append( make_GfReTime(G[i], block_indices_pack[i]) ) + return BlockGf( name_list = name_list, block_list = gl, name = name ) + diff --git a/pytriqs/gf/local/tail.pxd b/pytriqs/gf/local/tail.pxd new file mode 100644 index 00000000..ab3eafa9 --- /dev/null +++ b/pytriqs/gf/local/tail.pxd @@ -0,0 +1,37 @@ +from dcomplex cimport * +from arrays cimport * +cdef extern from "triqs/gf/local/tail.hpp" : + cdef cppclass tail "triqs::python_tools::cython_proxy" : + tail() + tail(array_view[dcomplex,THREE], int, array_view[long,TWO]) except + + matrix_view[dcomplex] operator()(int) except + + array_view[dcomplex,THREE] data() + array_view[long,TWO] mask_view() except + + void operator << (tail &) except + + void operator << (dcomplex &) except + + long order_min() except + + long order_max() except + + size_t size() except + + size_t shape(int) except + + + cdef tail operator +( tail &, tail &) except + + cdef tail operator -( tail &, tail &) except + + + cdef tail operator *( tail&, tail &) except + + + cdef tail operator *( double, tail &) except + + cdef tail operator *( tail &, double) except + + cdef tail operator /( double, tail &) except + + cdef tail operator /( tail &, double) except + + + cdef tail operator *( dcomplex, tail &) except + + cdef tail operator *( tail &, dcomplex) except + + cdef tail operator /( dcomplex, tail &) except + + cdef tail operator /( tail &, dcomplex) except + + cdef tail inverse_c "inverse" ( tail &) except + + + cdef void h5_write (h5_group, char *, tail &) + +cdef extern from "triqs/utility/serialization.hpp" : + cdef std_string boost_serialize "triqs::serialize" (tail &) + cdef void boost_unserialize_into "triqs::deserialize_into_view" (std_string, tail &) diff --git a/pytriqs/gf/local/tail.pyx b/pytriqs/gf/local/tail.pyx new file mode 100644 index 00000000..12effa39 --- /dev/null +++ b/pytriqs/gf/local/tail.pyx @@ -0,0 +1,190 @@ +from tools import py_deserialize +import descriptors + +cdef class TailGf: + cdef tail _c + def __init__(self, **d): + """ + TailGf ( shape, size, order_min ) + TailGf ( data, order_min ) + """ + c_obj = d.pop('encapsulated_c_object', None) + if c_obj : + assert d == {} + self._c = extractor [tail] (c_obj) () + return + + bss = d.pop('boost_serialization_string', None) + if bss : + assert d == {}, "Internal error : boost_serialization_string must be the only argument" + boost_unserialize_into(bss,self._c) + return + + omin = d.pop('order_min') + a = d.pop('data',None) + if a==None : + (N1, N2), s = d.pop('shape'), d.pop('size') + a = numpy.zeros((s,N1,N2), numpy.complex) + m = d.pop('mask',None) + if m==None : + m = numpy.zeros(a.shape[1:3], int) + m.fill(omin+a.shape[0]-1) + assert len(d) == 0, "Unknown parameters in TailGf constructions %s"%d.keys() + self._c = tail(array_view[dcomplex,THREE](a), omin, array_view[long,TWO](m)) + + #-------------- Reduction ------------------------------- + + def __reduce__(self): + return py_deserialize, (self.__class__,boost_serialize(self._c),) + + #-------------- Properties ------------------------------- + + property data : + """Access to the data array""" + def __get__(self) : + return self._c.data().to_python() + + property mask: + """Access to the mask""" + def __get__(self) : + return self._c.mask_view().to_python() + + property shape : + def __get__(self) : return self.data.shape[1:3] + + property order_min : + """Min order of the expansion""" + def __get__(self) : return self._c.order_min() + + property order_max : + """Max order of the expansion""" + def __get__(self) : return self._c.order_max() + + property N1 : + def __get__(self): return self.shape[0] + + property N2 : + def __get__(self): return self.shape[1] + + property size : + """Length of the expansion""" + def __get__(self) : return self._c.size() + + def copy(self) : + return self.__class__(data = self.data.copy(), order_min = self.order_min, mask = self.mask.copy()) + + def copy_from(self, TailGf T) : + assert self.order_min <= T.order_min, "Copy_from error " + self._c << T._c + + def _make_slice(self, sl1, sl2): + return self.__class__(data = self.data[:,sl1,sl2], order_min = self.order_min, mask = self.mask[sl1,sl2]) + + def __repr__ (self) : + return string.join([ "%s"%self[r]+ (" /" if r>0 else "") + " Om^%s"%(abs(r)) for r in range(self.order_min, self.order_max+1) ] , " + ") + + def __getitem__(self,i) : + """Returns the i-th coefficient of the expansion, or order Om^i""" + if not self.has_coef(i) : raise IndexError, "Index %s is out of range"%i + return self.data[i-self.order_min,:,:] + + def __setitem__(self,i, val) : + """Sets the i-th coefficient of the expansion, or order Om^i""" + if not self.has_coef(i) : raise IndexError, "Index %s is out of range"%i + self.data[i-self.order_min,:,:] = val + + def has_coef(self, i): + return (i >= self.order_min) and (i <= self.order_max) + + def __call__(self, x) : + val = 0.0 + for n in range(self.order_min, self.order_max+1): + val += self[n] * x**(-n) + return val + + def invert(self) : + self._c << inverse_c (self._c) + + ######### arithmetic operations ################# + + def __iadd__(self, TailGf arg): + self._c << self._c + arg._c + return self + + def __add__(self, TailGf y): + cdef tail t = (self)._c + y._c + return make_TailGf(t) + #c = self.copy() + #c += y + #return c + + def __isub__(self, TailGf arg): + self._c << self._c - arg._c + return self + + def __sub__(self,TailGf y): + cdef tail t = (self)._c - y._c + return make_TailGf(t) + #c = self.copy() + #c -= y + #return c + + def __imul__(self,arg): + n = type(arg).__name__ + if n == 'TailGf' : + self._c << self._c * (arg)._c + elif descriptors.is_scalar(arg): + self._c << as_dcomplex(arg)* self._c + else : + raise RuntimeError, " argument type not recognized in imul for %s"%arg + return self + + def __mul__(self,arg): + c = self.copy() + c *= arg + return c + + def __idiv__(self,arg): + if descriptors.is_scalar(arg): + self._c << self._c / as_dcomplex(arg) + else: + raise RuntimeError, "rhs must be a scalar" + return self + + def __div__(self,arg): + c = self.copy() + c /= arg + return c + + #---- other operations ---- + + def zero(self) : + """Sets the expansion to 0""" + self._c << as_dcomplex(0.0) + + def transpose (self) : + """Transpose the array : new view as in numpy""" + return TailGf(data=self.data.transpose(), order_min=self.order_min, mask=self.mask.transpose()) + + def conjugate(self) : + """Transpose the array : new view as in numpy""" + return TailGf(data=self.data.conjugate(), order_min=self.order_min, mask=self.mask) + + def __write_hdf5__ (self, gr , char * key) : + h5_write (make_h5_group(gr), key, self._c) + +#---------------- Reading from h5 --------------------------------------- + +def h5_read_TailGf( gr, std_string key) : + return make_TailGf( h5_extractor[tail]()(make_h5_group(gr),key)) + +from pytriqs.archive.hdf_archive_schemes import register_class +register_class (TailGf, read_fun = h5_read_TailGf) + +#----------------------------------------------------- +# C -> Python +#----------------------------------------------------- + +cdef inline make_TailGf ( tail x) : + return TailGf(encapsulated_c_object = encapsulate (&x)) + diff --git a/pytriqs/gf/local/tools.py b/pytriqs/gf/local/tools.py new file mode 100644 index 00000000..988a33b4 --- /dev/null +++ b/pytriqs/gf/local/tools.py @@ -0,0 +1,82 @@ +from types import SliceType +import descriptors + +class LazyCTX: + def __init__ (self, G): + self.G = G + def _is_compatible_for_ops(self, g): + m1,m2 = self.G.mesh, g.mesh + return m1 is m2 or m1 == m2 + def __eq__ (self, y): + return isinstance(y, self.__class__) and self._is_compatible_for_ops(y.G) + def __call__ (self, x): + if not isinstance(x, descriptors.Base): return x + tmp = self.G.copy() + x(tmp) + return tmp + +class IndicesConverter: + def __init__(self, indices): + if indices == None: # none is a trivial converter + self.indices=None + return + + try: + self.indices = list(indices)[:] # make a copy + except: + raise RuntimeError, "Indices must be a list or transformable into a list %s"(indices,) + assert len(set(repr(x) for x in self.indices)) == len(self.indices), "Error: indices are not unique !!!" + assert self.indices != [], "Error: indices are empty!!!" + try: + # a continuous list of ordered integers + self.__indices_are_sliceable = (self.indices== range(min(self.indices),max(self.indices)+1)) + self.__indexmin = min(self.indices) + self.__indexmax = max(self.indices) + #self.__indexlen = self.__indexmax - self.__indexmin +1 + except: + self.__indices_are_sliceable =False + self.Length = len(self.indices) + + def convertToNumpyIndex(self,a,noslice=False): + """ + Transcription of one Python index/slice into the index/slice of the numpy + """ + if self.indices==None: + if type(a)==SliceType: return a + return a if noslice else slice(a,a+1,1) + + if type(a)==SliceType: + if not self.__indices_are_sliceable: raise IndexError, "Indices %s can't be sliced"%self.indices + # put the slice to start at 0, and clip it + sta,sto,ste = slice(a.start, a.stop , a.step).indices(self.__indexmax+1) + return slice( max(0,sta-self.__indexmin), sto - self.__indexmin, ste) + + try: + s1 = self.indices.index(a) + except: + raise IndexError, "Index %s out of range %s"%(a,self.indices) + return s1 if noslice else slice(s1,s1+1,1) + +def get_indices_in_dict( d): + # exclusive: size = (n1,n2) or IndicesL/R + if 'indices_pack' in d: + indicesL, indicesR = d.pop('indices_pack') + else: + indicesL = list ( d.pop('indicesL',()) or d.pop('indices',()) ) + indicesR = list ( d.pop('indicesR',()) or indicesL ) + + # Now check the indices + ty = set([type(x) for x in indicesL]+[type(x) for x in indicesR]) + assert len(ty) !=0, "No indices found !" + assert len(ty)==1, " All indices must have the same type %s"%ty + + # If the indices are not string, make them string anyway + indicesL = [ str(x) for x in indicesL ] + indicesR = [ str(x) for x in indicesR ] + + return indicesL, indicesR + +def py_deserialize( cls, s): + return cls(boost_serialization_string = s) + + diff --git a/pytriqs/gf/local/two_real_times.pxd b/pytriqs/gf/local/two_real_times.pxd new file mode 100644 index 00000000..ed9ca38b --- /dev/null +++ b/pytriqs/gf/local/two_real_times.pxd @@ -0,0 +1,59 @@ +cdef extern from "triqs/gf/two_real_times.hpp" namespace "triqs::gf" : + + cdef cppclass two_real_times_domain : + two_real_times_domain() + + #cdef cppclass mesh_retime "triqs::gf::linear_mesh" : + cdef cppclass mesh_two_real_times "triqs::gf::mesh_product,triqs::gf::linear_mesh>" : + mesh_two_real_times () + mesh_two_real_times (mesh_two_real_times &) + two_real_times_domain & domain() + double x_min() + double x_max() + long size() + double kind() + bint operator ==( mesh_two_real_times &) + + cdef mesh_two_real_times make_mesh_two_real_times "triqs::gf::make_gf_mesh" (double t_max, double n_time_slices) + + cdef mesh_retime & get_1d_mesh_from_2times_mesh "triqs::gf::get_1d_mesh_from_2times_mesh" (mesh_two_real_times &) + + cdef cppclass gf_two_real_times "triqs::python_tools::cython_proxy>" : + gf_two_real_times() + gf_two_real_times(gf_two_real_times &) + # The constructor must be no_except, or the cython code won't be correct... + gf_two_real_times(mesh_two_real_times, array_view[dcomplex, THREE], nothing, nothing) #except + + void operator << (gf_two_real_times &) + mesh_two_real_times mesh() + array_view[dcomplex, THREE] data() + tail singularity() + + cdef gf_retime slice1d "triqs::gf::slice" (gf_two_real_times &, double t) except + + +cdef extern from "triqs/gf/two_real_times.hpp" : + cdef void h5_write (h5_group, char *, gf_two_real_times &) + +cdef extern from "triqs/utility/serialization.hpp" : + cdef std_string boost_serialize "triqs::serialize" (gf_two_real_times &) + cdef void boost_unserialize_into "triqs::deserialize_into_view" (std_string, gf_two_real_times &) + +# Python -> C +cdef gf_two_real_times as_gf_two_real_times (g) except + + +# C -> Python +cdef make_GfTwoRealTime (gf_two_real_times x, indices_pack=*, name=*) + +############### Blocks of Im Time ######################### + +cdef extern from "triqs/gf/block.hpp" namespace "triqs::gf" : + + cdef cppclass gf_block_two_real_times "triqs::python_tools::cython_proxy>>" : + gf_block_two_real_times() + gf_two_real_times & operator [](int) + discrete_mesh & mesh() + + cdef gf_block_two_real_times make_gf_block_two_real_times "triqs::gf::make_gf_view>" ( vector[gf_two_real_times] &) + +cdef gf_block_two_real_times as_gf_block_two_real_times (G) except + +cdef make_BlockGfTwoRealTime (gf_block_two_real_times G, block_indices_pack=*, name=*) + diff --git a/pytriqs/gf/local/two_real_times.pyx b/pytriqs/gf/local/two_real_times.pyx new file mode 100644 index 00000000..c585eb19 --- /dev/null +++ b/pytriqs/gf/local/two_real_times.pyx @@ -0,0 +1,71 @@ +from gf_two_real_times import GfTwoRealTime + +cdef class GfTwoRealTime_cython: + cdef gf_two_real_times _c + def __init__(self, MeshTwoRealTime mesh, data): + self._c = gf_two_real_times(mesh._c, array_view[dcomplex,THREE](data), nothing(), nothing()) + + def __write_hdf5_cython__ (self, gr , char * key) : + h5_write (make_h5_group(gr), key, self._c) + + def __dealloc__ (self): + pass + + def slice1d(self, double t): + return make_GfReTime(slice1d(self._c,t)) + + +#---------------- Reading from h5 --------------------------------------- + +def h5_read_GfTwoRealTime(gr, key): + try: + indicesL = gr[key]['indices']['left'] + indicesR = gr[key]['indices']['right'] + pack = [indicesL, indicesR] + except: + pack = [] + try: + name = gr[key]['name'] + except: + name = key + return make_GfTwoRealTime(h5_extractor[gf_two_real_times]()(make_h5_group(gr),key), pack, name) + +from pytriqs.archive.hdf_archive_schemes import register_class +register_class (GfTwoRealTime, read_fun = h5_read_GfTwoRealTime) + +#---------------- Convertions functions --------------------------------------- + +# Python -> C +cdef gf_two_real_times as_gf_two_real_times (g) except +: + return (g)._c + +# C -> Python. Do NOT add except + +cdef make_GfTwoRealTime (gf_two_real_times x, indices_pack = [], name = "g"): + data = x.data().to_python() + if indices_pack == []: + indices_pack = [range(data.shape[1]), range(data.shape[2])] + return GfTwoRealTime( + mesh = make_MeshTwoRealTime (x.mesh()), + data = data, + indices_pack = indices_pack, + name = name) + +# Python -> C for blocks +cdef gf_block_two_real_times as_gf_block_two_real_times (G) except +: + cdef vector[gf_two_real_times] v_c + for n,g in G: + v_c.push_back(as_gf_two_real_times(g)) + return make_gf_block_two_real_times (v_c) + +# C -> Python for block +cdef make_BlockGfTwoRealTime (gf_block_two_real_times G, block_indices_pack = [], name = "G"): + gl = [] + name_list = G.mesh().domain().names() + if block_indices_pack == []: + for i,n in enumerate(name_list): + sha = G[i].data().to_python().shape[1:3] + block_indices_pack.append( [range(sha[0]), range(sha[1])] ) + for i,n in enumerate(name_list): + gl.append( make_GfTwoRealTime(G[i], block_indices_pack[i]) ) + return BlockGf( name_list = name_list, block_list = gl, name = name ) + diff --git a/pytriqs/lattice/CMakeLists.txt b/pytriqs/lattice/CMakeLists.txt new file mode 100644 index 00000000..6224933e --- /dev/null +++ b/pytriqs/lattice/CMakeLists.txt @@ -0,0 +1,16 @@ +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/bz_patch.py + ${CMAKE_CURRENT_SOURCE_DIR}/super_lattice.py + ${CMAKE_CURRENT_SOURCE_DIR}/tight_binding.py +) + +install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/lattice) + +# THE C++ code +#SET(CPP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/C++) +cython_module(LatticeTools lattice_tools lattice ) + +# ??? +#target_link_libraries(_pytriqs_LatticeTools triqs ${TRIQS_LINK_LIBS}) + diff --git a/pytriqs/lattice/__init__.py b/pytriqs/lattice/__init__.py new file mode 100644 index 00000000..9b8d2cc7 --- /dev/null +++ b/pytriqs/lattice/__init__.py @@ -0,0 +1,23 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +__all__ = ['tight_binding','bz_patch','super_lattice'] diff --git a/pytriqs/lattice/bz_patch.py b/pytriqs/lattice/bz_patch.py new file mode 100644 index 00000000..50fea788 --- /dev/null +++ b/pytriqs/lattice/bz_patch.py @@ -0,0 +1,55 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +#from pytriqs import * +from super_lattice import * +from pytriqs.dos import DOS + +class BZPatch: + """Description of a Patch of the BZ""" + def __init__(self, name, polygons): + """ TO BE WRITTEN: MICHEL! """ + # Cut the patch in triangles (this is what is asked by the C-code) + self.weight, self.name = 0, name + self._triangles = [] + self._weights = [] + for polygon in polygons: + pnt = [0, 0, 0] + for np, point in enumerate(polygon): + if np > 1: + pnt[2] = point + self._triangles += pnt + self._weights += [ 0.5*abs((pnt[1][0]-pnt[0][0])*(pnt[2][1]-pnt[0][1]) + -(pnt[1][1]-pnt[0][1])*(pnt[2][0]-pnt[0][0])) ] + self.weight += 0.5*abs((pnt[1][0]-pnt[0][0])*(pnt[2][1]-pnt[0][1]) + -(pnt[1][1]-pnt[0][1])*(pnt[2][0]-pnt[0][0])) + pnt[1] = pnt[2] + else: + pnt[np%3] = point + + def dos(self, lattice, n_bins, n_div_triangle): + """ Compute the partial dos of the Patch for the Lattice lattice""" + assert isinstance(lattice, (Lattice, TBSuperLattice)) + return lattice.dos_patch(self._triangles, n_bins, n_div_triangle, self.name) + + + diff --git a/pytriqs/lattice/lattice_tools.pyx b/pytriqs/lattice/lattice_tools.pyx new file mode 100644 index 00000000..7998faf3 --- /dev/null +++ b/pytriqs/lattice/lattice_tools.pyx @@ -0,0 +1,105 @@ +from dcomplex cimport * +from shared_ptr cimport * +from arrays cimport * +from libcpp.pair cimport pair +from libcpp.vector cimport vector +from libcpp.string cimport string as std_string +#from extractor cimport * +#from h5 cimport * +from cython.operator cimport dereference as deref, preincrement as inc #dereference and increment operator + +import numpy + +cdef extern from "triqs/lattice/bravais_lattice_and_brillouin_zone.hpp" namespace "triqs::gf" : + cdef cppclass bravais_lattice_c " triqs::lattice_tools::bravais_lattice" : + bravais_lattice_c(matrix[double] & units) + int n_orbitals() + matrix[double] units() + int dim() + void push_back(std_string &, tqa_vector[double] &) + tqa_vector[double] lattice_to_real_coordinates (tqa_vector_view[double] &) + +cdef extern from "triqs/lattice/tight_binding.hpp" namespace "triqs::gf" : + cdef cppclass tight_binding " triqs::lattice_tools::tight_binding" : + tight_binding(bravais_lattice_c & units) + void push_back (vector[long] &, matrix[double] &) + + #Fix the name conflict pv wiht a pxd, cf doc....? + array_view[complex,THREE] hopping_stack_c "hopping_stack" (tight_binding & TB, array_view[double,TWO] & k_stack) + pair [array[double,ONE],array[double,TWO]] dos_c "dos" (tight_binding & TB, size_t nkpts, size_t neps) + pair [array[double,ONE],array[double,ONE]] dos_patch_c "dos_patch" (tight_binding & TB, array_view[double,TWO] & triangles, size_t neps, size_t ndiv) + array_view[double,TWO] energies_on_bz_path_c "energies_on_bz_path" (tight_binding & TB, tqa_vector[double] & K1, tqa_vector[double] & K2, size_t n_pts) + array_view[double,TWO] energies_on_bz_grid_c "energies_on_bz_grid" (tight_binding & TB, size_t n_pts) + +cdef class BravaisLattice : + """ + """ + cdef bravais_lattice_c * _c + def __init__(self, units, orbital_positions = None ) : + """ """ + self._c = new bravais_lattice_c( matrix[double](units)) + orbital_positions = orbital_positions if orbital_positions else dict ("", (0,0,0) ) + for name, pos in orbital_positions.items(): + self._c.push_back( name, tqa_vector[double](pos)) + + def __dealloc__(self): + del self._c + + def lattice_to_real_coordinates(self, R) : + """ + Transform into real coordinates. + :param x_in: coordinates in the basis of the unit vectors + :rtype: Output coordinates in R^3 (real coordinates) as an array + """ + return self._c.lattice_to_real_coordinates ( tqa_vector_view[double] (R)).to_python() + + property dim : + """Dimension of the lattice""" + def __get__(self) : + """Dimension of the lattice""" + return self._c.dim() + + def n_orbitals(self) : + """Number of orbitals""" + return self._c.n_orbitals() + +cdef class TightBinding: + """ + """ + cdef tight_binding * _c + def __init__(self, BravaisLattice bravais_lattice, hopping ) : + """ """ + self._c = new tight_binding(deref(bravais_lattice._c)) + cdef vector[long] d + for displ, mat in hopping.items() : + d = displ + self._c.push_back( d, matrix[double] (numpy.array(mat, dtype =float))) + + def __dealloc__(self): + del self._c + +# ------------------------------------------- + +def hopping_stack (TightBinding TB, k_stack) : + """ """ + return hopping_stack_c(deref(TB._c), array_view[double,TWO](k_stack)).to_python() + +def dos ( TightBinding TB, int nkpts, int neps): + """ """ + a = dos_c(deref(TB._c), nkpts, neps) + return (a.first.to_python(), a.second.to_python()) + +def dos_patch ( TightBinding TB, triangles, int neps, int ndiv): + """ """ + a = dos_patch_c(deref(TB._c), array_view[double,TWO] (triangles), neps, ndiv) + return (a.first.to_python(), a.second.to_python()) + +def energies_on_bz_path ( TightBinding TB, K1, K2, n_pts) : + """ """ + return energies_on_bz_path_c (deref(TB._c), tqa_vector[double](K1), tqa_vector[double] (K2), n_pts).to_python() + +def energies_on_bz_grid ( TightBinding TB, n_pts) : + """ """ + return energies_on_bz_grid_c (deref(TB._c), n_pts).to_python() + + diff --git a/pytriqs/lattice/super_lattice.py b/pytriqs/lattice/super_lattice.py new file mode 100644 index 00000000..0e504098 --- /dev/null +++ b/pytriqs/lattice/super_lattice.py @@ -0,0 +1,195 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +import numpy +from tight_binding import TBLattice + +__all__ = ['TBSuperLattice'] + + +def nint_strict(x, precision=1.e-9): + """ Round array x to the closest integer and asserts that its distance to this integer is less than precision. + precision must satisfy : precision >0 and precision <0.5 + """ + assert precision >0 and precision <0.5, "nint_strict : precision makes no sense !" + i = numpy.floor(x+0.5) + assert abs(i-x).max() < precision, repr(i) + "\n "+repr(x) + "\n The Float is not close enough to the integer " + return i.astype(numpy.int) + + +class TBSuperLattice(TBLattice): + """ + Builds a superlattice on top of a base Lattice, by picking superlattice units and optionally the cluster points. + """ + def __init__(self, tb_lattice, super_lattice_units, cluster_sites = None, remove_internal_hoppings = False): + """ + * tb_lattice: The underlying lattice + + * super_lattice_units: The unit vectors of the superlattice in the tb_lattice (integer) coordinates + + * cluster_sites [None]: Coordinates of the cluster in tb_lattice coordinates. + If None, an automatic computation of cluster positions is made as follows: + it takes all points whose coordinates in the basis of the superlattice are in [0, 1[^dimension + + * remove_internal_hoppings: If true, the hopping terms are removed inside the cluster. + Useful to add Hartree Fock terms at the boundary of a cluster, e.g. + """ + if not isinstance(tb_lattice, TBLattice): raise ValueError, "tb_lattice should be an instance of TBLattice" + self.__BaseLattice = tb_lattice + dim = tb_lattice.dim + + try: + self.__super_lattice_units = numpy.array(super_lattice_units, copy=True) + assert self.__super_lattice_units.shape == (dim, dim) + except: + raise ValueError, "super_lattice_units is not correct. Cf Doc. value is %s, dim = %s "%(super_lattice_units,dim) + + Ncluster_sites = int(numpy.rint(abs(numpy.linalg.det(self.__super_lattice_units )))) + assert Ncluster_sites >0, "Superlattice vectors are not independant !" + self._M = self.__super_lattice_units.transpose() + self._Mtilde = numpy.array(numpy.rint(numpy.linalg.inv(self._M)*Ncluster_sites), dtype = int) + + self.__remove_internal_hoppings = remove_internal_hoppings + #self.norb = tb_lattice.NOrbitalsInUnitCell + self.Norb = tb_lattice.NOrbitalsInUnitCell * Ncluster_sites + + # cluster_sites computation + if cluster_sites!=None: + self.__cluster_sites = list(cluster_sites)[:] + else: # Computes the position of the cluster automatically + self.__cluster_sites = [] + #We tile the super-cell with the tb_lattice points and retains + # the points inside it and store it. + M=numpy.array(self.__super_lattice_units) + assert M.shape==tuple(2*[dim]), "Tiling Construct: super_lattice_units does not have the correct size" + #Minv = Ncluster_sites*numpy.linalg.inverse(M) #+0.5 # +0.5 is for the round + #Mtilde = Minv.astype(numpy.Int) # now is integer. + Mtilde = nint_strict(Ncluster_sites*numpy.linalg.inv(M)) + # round to the closest integer, with assert that precision is <1.e-9 + if dim==1: a=(max(M[0,:]), 0, 0 ) + elif dim==2: a=(2*max(M[0,:]), 2*max(M[1,:]), 0 ) + elif dim==3: a= (3*max(M[0,:]), 3*max(M[1,:]), 3*max(M[2,:])) + else: raise ValueError, "dim is not between 1 and 3 !!" + r = lambda i: range(-a[i] , a[i]+1) + for nx in r(0): + for ny in r(1): + for nz in r(2): + nv = numpy.array([nx, ny, nz][0:dim]) + k_sl = numpy.dot(Mtilde, nv) + if (min(k_sl) >= 0) and (max(k_sl) < Ncluster_sites ): # The point is a point of the cluster. We store it. + self.__cluster_sites.append(nv.tolist()) + + assert len(self.__cluster_sites) == Ncluster_sites, """Number of cluster positions incorrect (compared to the volume of unit cell of the Superlattice)""" + self.Ncluster_sites = Ncluster_sites + + # creating a dictionnary position_of_sites -> number e.g. (1, 0): 2 etc... + # self._clustersites_hash = dict ([ (tuple(pos), n) for n, pos in enumerate(self.cluster_sites)]) + + # Compute the new Hopping in the supercell + Hopping = self.fold(tb_lattice.hopping_dict(), remove_internal_hoppings) + if 0: + for k, v in Hopping.items(): + print k + print v.real + + # Compute the new units of the lattice in real coordinates + Units = numpy.dot(self.__super_lattice_units, tb_lattice.Units) + + # Positions and names of orbitals in the supercell: just translate all orbitals for cluster site positions + # in R^3 coordinates. + Orbital_Positions = [POS + tb_lattice.latt_to_real_x(CS) for POS in tb_lattice.OrbitalPositions for CS in self.__cluster_sites] + + #Orbital_Names = [ '%s%s'%(n, s) for n in tb_lattice.OrbitalNames for s in range(Ncluster_sites)] + site_index_list, orbital_index_list = range(1, Ncluster_sites+1), tb_lattice.OrbitalNames + if len(orbital_index_list)==1: + Orbital_Names= [ s for s in site_index_list ] + elif len(site_index_list)==1 and len(orbital_index_list)>1: + Orbital_Names= [ o for o in orbital_index_list] + elif len(site_index_list)>1 and len(orbital_index_list)>1: + Orbital_Names= [ (pos, o) for o in orbital_index_list for pos in site_index_list] + + #print tb_lattice.OrbitalNames #Orbital_Names + TBLattice.__init__(self, Units, Hopping, Orbital_Positions, Orbital_Names) + # we pass False since the folding has arealdy been done in tb_lattice + + assert self.Norb == self.NOrbitalsInUnitCell + + __HDF_reduction__ = ['__BaseLattice', '__super_lattice_units', '__cluster_sites', '__remove_internal_hoppings'] + + def __reduce__ (self): + return tuple([getattr(self, x) for x in self.__HDF_reduction__]) + + def fold(self, D1, remove_internal=False, create_zero = None): + """ Input: a function r-> f(r) on the tb_lattice given as a dictionnary + Output: the function R-> F(R) folded on the superlattice. + Only requirement is that f(r)[orbital1, orbital2] is properly defined. + Hence f(r) can be a numpy, a GFBloc, etc... + """ + #Res , norb = {} , self.__BaseLattice.NOrbitalsInUnitCell + Res , norb = {} , len(D1.values()[0]) + pack = self.pack_index_site_orbital + for nsite, CS in enumerate(self.__cluster_sites): + for disp, t in D1.items(): + R, alpha = self.change_coordinates_L_to_SL(numpy.array(CS)+numpy.array(disp)) + if R not in Res: Res[R] = create_zero() if create_zero else numpy.zeros((self.Norb, self.Norb), dtype = type(t[0,0])) + if not(remove_internal) or R!= self.tb_lattice.dim*(0, ): + for orb1 in range(norb): + for orb2 in range(norb): + Res[R][pack(nsite, orb1), pack(alpha, orb2)] += t[orb1, orb2] + return Res + + def change_coordinates_SL_to_L(self, R , alpha): + """Given a point in the supercell R, site (number) alpha, it computes its position on the tb_lattice in lattice coordinates""" + return numpy.dot (self._M, numpy.array(R)) + self.__cluster_sites[alpha,:] + + def change_coordinates_L_to_SL(self, x): + """Given a point on the tb_lattice in lattice coordinates, returns its coordinates (R, alpha) in the Superlattice""" + aux = numpy.dot(self._Mtilde, numpy.array(x)) + R = aux // self.Ncluster_sites + dx = list (x - numpy.dot (self._M, R) ) # force int ? + return tuple(R), self.__cluster_sites.index(dx) + + def pack_index_site_orbital(self, n_site, n_orbital): + """ nsite and n_orbital must start at 0""" + return n_site + (n_orbital ) * self.Ncluster_sites + + def unpack_index_site_orbital (self, index): + """Inverse of pack_index_site_orbital""" + n_orbital = (index)//self.Ncluster_sites + n_site = index - n_orbital*self.Ncluster_sites + return n_site, n_orbital + + def cluster_sites(self): + """ + Generate the position of the cluster site in the tb_lattice coordinates. + """ + for pos in self.__cluster_sites: + yield pos + + def __repr__(self): + def f(A): + return list([ tuple(x) for x in A]) + return """SuperLattice class: \n + Base TBLattice: %s + SuperLattice Units: %s + Remove internal Hoppings: %s + Cluster site positions: %s"""%(self.__BaseLattice, f(self.__super_lattice_units), self.__cluster_sites, self.__remove_internal_hoppings) diff --git a/pytriqs/lattice/tight_binding.py b/pytriqs/lattice/tight_binding.py new file mode 100644 index 00000000..da0758d2 --- /dev/null +++ b/pytriqs/lattice/tight_binding.py @@ -0,0 +1,86 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +__all__ = ['BravaisLattice', 'TightBinding', 'dos', 'dos_patch', 'energies_on_bz_grid', 'energies_on_bz_path', + 'hopping_stack', 'TBLattice'] + +from lattice_tools import BravaisLattice as BravaisLattice +from lattice_tools import TightBinding as TightBinding +from lattice_tools import dos_patch as dos_patch_c +from lattice_tools import dos as dos_c +from lattice_tools import energies_on_bz_grid, energies_on_bz_path, hopping_stack +from pytriqs.dos import DOS +import numpy + + +# MOVE THIS BACK INTO CYTHON !!!! + +def dos(tight_binding, n_kpts, n_eps, name) : + """ + :param tight_binding: a tight_binding object + :param n_kpts: the number of k points to use in each dimension + :param n_eps: number of points used in the binning of the energy + :param name: name of the resulting dos + + :rtype: return a list of DOS, one for each band + """ + eps, arr = dos_c(tight_binding, n_kpts, n_eps) + return [ DOS (eps, arr[:, i], name) for i in range (arr.shape[1]) ] + +def dos_patch(tight_binding, triangles, n_kpts, n_div, name) : + """ + To be written + """ + eps, arr = dos_c(tight_binding, n_kpts, eps) + return DOS (eps, arr, name) + +# for backward compatibility. Not documented. +class TBLattice: + + def __init__ (self, units, hopping, orbital_positions = [ (0, 0, 0) ], orbital_names = [""]): + + # the k are int32 which boost python does like to convert + def reg(k) : return tuple( int(x) for x in k) + self._hop = dict ( ( reg(k), numpy.array(v)) for k, v in hopping.items()) + orb = dict ( (str(i), orb) for (i, orb) in enumerate(orbital_positions )) + self.bl = BravaisLattice(units, orb) + self.tb = TightBinding(self.bl, self._hop) #, orbital_positions ) + self.dim = self.bl.dim + self.NOrbitalsInUnitCell = self.bl.n_orbitals() + self.Units = units + self.OrbitalPositions = orbital_positions + self.OrbitalNames = orbital_names + self.MuPattern = numpy.identity(self.NOrbitalsInUnitCell) + + def latt_to_real_x(self, p) : + return self.bl.lattice_to_real_coordinates (numpy.array(p, numpy.float64)) + # modified since array are not converted automatically any more + ##return self.bl.lattice_to_real_coordinates (p ) #numpy.array(p.float64)) + + def hopping_dict(self) : return self._hop + + def hopping(self, k_stack) : + return hopping_stack(self.tb, k_stack) + + #def dos(self) : d = dos (TB, nkpts= 100, neps = 100, name = 'dos2') + + diff --git a/pytriqs/parameters/CMakeLists.txt b/pytriqs/parameters/CMakeLists.txt new file mode 100644 index 00000000..b9eb2de1 --- /dev/null +++ b/pytriqs/parameters/CMakeLists.txt @@ -0,0 +1,12 @@ +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py +) + +install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/parameters) + +cython_module(Parameters parameters parameters ) + +FILE(GLOB all_pxd_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.pxd ) +install (FILES ${all_pxd_files} DESTINATION "include/pytriqs/parameters") +install (FILES ${CMAKE_SOURCE_DIR}/pytriqs/__init__.py.template DESTINATION "include/pytriqs/parameters" RENAME __init__.py) + diff --git a/pytriqs/parameters/__init__.py b/pytriqs/parameters/__init__.py new file mode 100644 index 00000000..6148257c --- /dev/null +++ b/pytriqs/parameters/__init__.py @@ -0,0 +1,31 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +r""" +This is the base module for all common operations with Green's functions. +It is imported with the command:: + + >>> from pytriqs.gf import * +""" + +__all__ = [] + diff --git a/pytriqs/parameters/parameters.pxd b/pytriqs/parameters/parameters.pxd new file mode 100644 index 00000000..fe1f4975 --- /dev/null +++ b/pytriqs/parameters/parameters.pxd @@ -0,0 +1,21 @@ +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 diff --git a/pytriqs/parameters/parameters.pyx b/pytriqs/parameters/parameters.pyx new file mode 100644 index 00000000..2e010db9 --- /dev/null +++ b/pytriqs/parameters/parameters.pyx @@ -0,0 +1,86 @@ +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) + + 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, (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) + 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) + + + diff --git a/pytriqs/plot/CMakeLists.txt b/pytriqs/plot/CMakeLists.txt new file mode 100644 index 00000000..fb55c344 --- /dev/null +++ b/pytriqs/plot/CMakeLists.txt @@ -0,0 +1,9 @@ + +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/mpl_interface.py + ${CMAKE_CURRENT_SOURCE_DIR}/protocol.py +) + +install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/plot) + diff --git a/pytriqs/plot/__init__.py b/pytriqs/plot/__init__.py new file mode 100644 index 00000000..8f2e461e --- /dev/null +++ b/pytriqs/plot/__init__.py @@ -0,0 +1,23 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +__all__ = [] diff --git a/pytriqs/plot/mpl_interface.py b/pytriqs/plot/mpl_interface.py new file mode 100644 index 00000000..a0623e18 --- /dev/null +++ b/pytriqs/plot/mpl_interface.py @@ -0,0 +1,93 @@ +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +__all__ = ['plt','oplot','subplots','figsize_default','use_amsmath'] + +import numpy, matplotlib as mpl, matplotlib.pylab as plt +from protocol import plot_protocol_apply +from matplotlib import rc + +try: + subplots = mpl.pyplot.subplots +except: + def subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True, subplot_kw=None, **fig_kw): + print "subplots not supported" + return plt.figure(1), [plt.subplot(nrows,ncols,x+1) for x in range(nrows*ncols)] + +figsize_default = (12,8) + + +def oplot (*ob_list, **opt_dict) : + """ + A thin layer above pyplot.plot function that allows plotting objects with + plot protocol as well as arrays. + Options are the same as for the pyplot.plot function. + """ + plt.figure(1, figsize = opt_dict.pop('figsize', figsize_default ) ) + __oplot_impl(plt.plot, plt.xlabel,plt.ylabel,plt.legend, *ob_list,**opt_dict) + # remove this in the notebook... + #if hasattr(plt.figure(1), "show") : plt.figure(1).show() + +mpl.axes.Axes.oplot = lambda self, *ob_list, **opt_dict : __oplot_impl(self.plot,self.set_xlabel, self.set_ylabel, self.legend, *ob_list,**opt_dict) + +def __oplot_impl (plot_fct, xlabel_fct, ylabel_fct, legend_fct, *ob_list, **opt_dict) : + """ + A thin layer above pyplot.plot function that allows plotting objects with + plot protocol as well as arrays. + Options are the same as for the pyplot.plot function. + """ + + def objs() : # filter the arguments for the format strings ... + i, l = 0, [] + while i< len (ob_list) : + if i < len(ob_list) - 1 and type(ob_list[i+1]) == type("") : + res = ob_list[i], [ ob_list[i+1] ] + i+=2 + else : + res = ob_list[i], [ ] + i+=1 + yield res + + for ob, OptionsList in objs() : + opt = opt_dict.copy() # the plot protocol will consume the dict.... + #ob2 = eval_expr_or_pass (ob) # if it is a lazy_expr, it is time to evaluate it ! + for curvedata in plot_protocol_apply(ob, opt, plt.xlim ) : + X,Y = curvedata['xdata'],curvedata['ydata'] + d = { 'label' : curvedata['label'] } + d.update(opt) + try : + plot_fct(X,Y,*OptionsList,**d) + except TypeError, e: + import re + m = re.search('(?<=There is no line property )"(.*)"', str(e) ) + if m : + raise RuntimeError, "Option %s is not understood in plot function : it is not an option of the object to be plotted, nor a matplotlib option"%m.group(0) + else : + raise + if 'xlabel' in curvedata : xlabel_fct(curvedata['xlabel'], fontsize=20) + if 'ylabel' in curvedata : ylabel_fct(curvedata['ylabel'], fontsize=20) + + legend_fct(loc = 1) #legend is built from the label + +def use_amsmath(): + rc('text', usetex=True) + rc('text.latex', preamble="\usepackage{amsmath}") + diff --git a/pytriqs/plot/protocol.py b/pytriqs/plot/protocol.py new file mode 100644 index 00000000..b2be904f --- /dev/null +++ b/pytriqs/plot/protocol.py @@ -0,0 +1,75 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +import numpy + +def clip_array(x_array, x_min, x_max): + """ + Given: + - x_array a 1d numpy array of shape (L), of ordered values + or in fact any generator of ordered values. + - x_min, x_max + it returns the slice sl such that + * x_array[sl] is in [x_min, x_max] + """ + assert x_max >= x_min, "Windowing error" + + try: + low = (i for i,x in enumerate(x_array) if not( x < x_min) ).next() + except StopIteration: + return slice(0,0) # there is no x >= x_min + + try: + high = (i for i,x in enumerate(x_array) if x > x_max ).next() + r = slice(low,high) + except StopIteration: + r = slice(low,len(x_array)) # there is no x > x_max + + return r + +def plot_protocol_apply(ob, opt_dict, xlims): + """ + Given an object ob that supports the plot protocol, it applies the protocol + or emulate it + """ + + if hasattr(ob, '_plot_'): return ob._plot_(opt_dict) + elif callable(ob): + n_points = opt_dict.pop('n_points',100) + rx = opt_dict.pop('x_window', None) + xmin, xmax = rx if rx else xlims() + X = numpy.arange(xmin,xmax, (xmax- xmin)/float(n_points)) + Y = numpy.array( [ob(x) for x in X] ) + else: + try: # generator x,y + X, Y = izip (*ob) + except: + raise RuntimeError, "Object can not be plotted" + + name = opt_dict.pop('name','') + if not name: name = str(ob) + if numpy.iscomplexobj(Y): + return( [ {'type': "XY", 'xdata':X, 'ydata':Y.real, 'label': "Re " + name} , + {'type': "XY", 'xdata':X, 'ydata':Y.imag, 'label': "Im " + name} ] ) + else: + return( [ {'type': "XY", 'xdata':X, 'ydata':Y, 'label': name} ] ) + diff --git a/pytriqs/pxd/CMakeLists.txt b/pytriqs/pxd/CMakeLists.txt new file mode 100644 index 00000000..5eb7bbcf --- /dev/null +++ b/pytriqs/pxd/CMakeLists.txt @@ -0,0 +1,3 @@ +FILE(GLOB all_pxd_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.pxd ) +install (FILES ${all_pxd_files} DESTINATION "include/pytriqs") +install (FILES ${CMAKE_SOURCE_DIR}/pytriqs/__init__.py.template DESTINATION "include/pytriqs" RENAME __init__.py) diff --git a/pytriqs/pxd/arrays.pxd b/pytriqs/pxd/arrays.pxd new file mode 100644 index 00000000..25d379d3 --- /dev/null +++ b/pytriqs/pxd/arrays.pxd @@ -0,0 +1,72 @@ +from clef cimport * +cdef extern from "" namespace "triqs::arrays" : + + cdef cppclass array "triqs::arrays::array" [T,R] : + array() + array(object) except + + array operator +( array_view &) + array operator -( array_view &) + array operator *( array_view &) + array operator /( array_view &) + object to_python() + + cdef cppclass array_view "triqs::arrays::array_c" [T,R] : + array_view() + array_view(object) except + + array_view operator +( array_view &) + array_view operator -( array_view &) + array_view operator *( array_view &) + array_view operator /( array_view &) + void operator << (array_view &) + object to_python() + int shape(int) + # bug in cython + #_lazy_expr operator()(_lazy_expr&) + #_lazy_expr operator()(_lazy_expr&, _lazy_expr&) + #_lazy_expr operator()(_lazy_expr&, _lazy_expr&, _lazy_expr&) + #_lazy_expr operator()(_lazy_expr&, _lazy_expr&, _lazy_expr&, _lazy_expr&) + _lazy_expr call "operator()" (_lazy_expr&) + _lazy_expr call "operator()" (_lazy_expr&, _lazy_expr&) + _lazy_expr call "operator()" (_lazy_expr&, _lazy_expr&, _lazy_expr&) + _lazy_expr call "operator()" (_lazy_expr&, _lazy_expr&, _lazy_expr&, _lazy_expr&) + _lazy_expr call "operator()" (_lazy_expr&, _lazy_expr&, _lazy_expr&, _lazy_expr&, _lazy_expr&) + + cdef cppclass matrix_view "triqs::arrays::matrix_c" [T] : + matrix_view() + matrix_view(matrix) + matrix_view(object) except + + void operator << (matrix_view &) + object to_python() + + cdef cppclass matrix "triqs::arrays::matrix" [T] : + matrix() + matrix(object) except + + matrix operator +( matrix_view &) + matrix operator -( matrix_view &) + matrix operator /( matrix_view &) + object to_python() + + cdef matrix_view operator +( matrix_view & , matrix_view &) + cdef matrix_view operator -( matrix_view & , matrix_view &) + cdef matrix_view operator *( matrix_view & , matrix_view &) + cdef matrix_view operator /( matrix_view & , matrix_view &) + + cdef cppclass tqa_vector "triqs::arrays::vector" [T] : + tqa_vector() + tqa_vector(object) except + + tqa_vector operator +( tqa_vector_view &) + tqa_vector operator -( tqa_vector_view &) + tqa_vector operator *( tqa_vector_view &) + tqa_vector operator /( tqa_vector_view &) + object to_python() + + cdef cppclass tqa_vector_view "triqs::arrays::vector_c" [T] : + tqa_vector_view() + tqa_vector_view(object) except + + tqa_vector_view operator +(tqa_vector_view &) + tqa_vector_view operator -(tqa_vector_view &) + tqa_vector_view operator *(tqa_vector_view &) + tqa_vector_view operator /(tqa_vector_view &) + void operator << (tqa_vector_view &) + object to_python() + diff --git a/pytriqs/pxd/boost.pxd b/pytriqs/pxd/boost.pxd new file mode 100644 index 00000000..cc943878 --- /dev/null +++ b/pytriqs/pxd/boost.pxd @@ -0,0 +1,5 @@ +cdef extern from "triqs/python_tools/boost_object.hpp" namespace "triqs::python_tools": + + cdef cppclass boost_object "triqs::python_tools::boost_object": + boost_object(object ob) + diff --git a/pytriqs/pxd/clef.pxd b/pytriqs/pxd/clef.pxd new file mode 100644 index 00000000..3ae0a462 --- /dev/null +++ b/pytriqs/pxd/clef.pxd @@ -0,0 +1,66 @@ +cdef extern from "" namespace "triqs::clef" : + ctypedef int ZERO "0" + ctypedef int ONE "1" + ctypedef int TWO "2" + ctypedef int THREE "3" + ctypedef int FOUR "4" + ctypedef int FIVE "5" + ctypedef int SIX "6" + + cdef cppclass placeholder "triqs::clef::placeholder" [T] : + placeholder() + #_lazy_expr operator []() + + cdef _lazy_expr ph "triqs::clef::placeholder<0>" (placeholder[ZERO] &) + cdef _lazy_expr ph "triqs::clef::placeholder<1>" (placeholder[ONE] &) + cdef _lazy_expr ph "triqs::clef::placeholder<2>" (placeholder[TWO] &) + cdef _lazy_expr ph "triqs::clef::placeholder<3>" (placeholder[THREE] &) + cdef _lazy_expr ph "triqs::clef::placeholder<4>" (placeholder[FOUR] &) + cdef _lazy_expr ph "triqs::clef::placeholder<5>" (placeholder[FIVE] &) + cdef _lazy_expr ph "triqs::clef::placeholder<6>" (placeholder[SIX] &) + + cdef _lazy_expr ph0 "triqs::clef::placeholder<0>" () + cdef _lazy_expr ph1 "triqs::clef::placeholder<1>" () + cdef _lazy_expr ph2 "triqs::clef::placeholder<2>" () + cdef _lazy_expr ph3 "triqs::clef::placeholder<3>" () + cdef _lazy_expr ph4 "triqs::clef::placeholder<4>" () + cdef _lazy_expr ph5 "triqs::clef::placeholder<5>" () + + cdef _lazy_expr _i "triqs::clef::placeholder<0>" () + cdef _lazy_expr _j "triqs::clef::placeholder<1>" () + cdef _lazy_expr _k "triqs::clef::placeholder<2>" () + cdef _lazy_expr _l "triqs::clef::placeholder<3>" () + cdef _lazy_expr _m "triqs::clef::placeholder<4>" () + cdef _lazy_expr _n "triqs::clef::placeholder<5>" () + + cdef cppclass _lazy_expr : + void operator << (_lazy_expr &) + _lazy_expr operator()(_lazy_expr&) + _lazy_expr operator()(_lazy_expr&, _lazy_expr&) + _lazy_expr operator()(_lazy_expr&, _lazy_expr&, _lazy_expr&) + _lazy_expr operator()(_lazy_expr&, _lazy_expr&, _lazy_expr&, _lazy_expr&) + + cdef _lazy_expr operator +(_lazy_expr, _lazy_expr ) + cdef _lazy_expr operator -(_lazy_expr , _lazy_expr) + cdef _lazy_expr operator *(_lazy_expr, _lazy_expr ) + cdef _lazy_expr operator /(_lazy_expr, _lazy_expr) + + cdef _lazy_expr operator +(long, _lazy_expr ) + cdef _lazy_expr operator +(_lazy_expr , long) + cdef _lazy_expr operator -(long, _lazy_expr &) + cdef _lazy_expr operator -(_lazy_expr &, long) + cdef _lazy_expr operator *(long, _lazy_expr &) + cdef _lazy_expr operator *(_lazy_expr &, long) + cdef _lazy_expr operator /(long, _lazy_expr &) + cdef _lazy_expr operator /(_lazy_expr &, long) + + cdef _lazy_expr operator +(double, _lazy_expr ) + cdef _lazy_expr operator +(_lazy_expr , double) + cdef _lazy_expr operator -(double, _lazy_expr &) + cdef _lazy_expr operator -(_lazy_expr &, double) + cdef _lazy_expr operator *(double, _lazy_expr &) + cdef _lazy_expr operator *(_lazy_expr &, double) + cdef _lazy_expr operator /(double, _lazy_expr &) + cdef _lazy_expr operator /(_lazy_expr &, double) + + diff --git a/pytriqs/pxd/dcomplex.pxd b/pytriqs/pxd/dcomplex.pxd new file mode 100644 index 00000000..fead7bc9 --- /dev/null +++ b/pytriqs/pxd/dcomplex.pxd @@ -0,0 +1,21 @@ +cdef extern from "" namespace "std": + cdef cppclass dcomplex "std::complex": + dcomplex() + dcomplex(dcomplex &) + dcomplex(double,double) + double real() + double imag() + +# Python -> C +cdef inline dcomplex as_dcomplex (a) : + x = complex(a) + return dcomplex(a.real, a.imag) + +# C -> Python +cdef inline make_dcomplex (dcomplex z) : + return complex(z.real(), z.imag()) + +# Python -> C +cdef inline float as_float (a) : + return float (a) + diff --git a/pytriqs/pxd/extractor.pxd b/pytriqs/pxd/extractor.pxd new file mode 100644 index 00000000..016f401c --- /dev/null +++ b/pytriqs/pxd/extractor.pxd @@ -0,0 +1,13 @@ +cdef extern from * : + object PyCObject_FromVoidPtr(void* cobj, void *) + void* PyCObject_AsVoidPtr(object self) + +cdef inline encapsulate (void * p) : + return PyCObject_FromVoidPtr(p, NULL) + +cdef extern from "triqs/utility/python/extractor.hpp" : + + cdef cppclass extractor "triqs::utility::python::extractor" [T] : + extractor (object) + T & operator()() + diff --git a/pytriqs/pxd/h5.pxd b/pytriqs/pxd/h5.pxd new file mode 100644 index 00000000..a0c0d42b --- /dev/null +++ b/pytriqs/pxd/h5.pxd @@ -0,0 +1,17 @@ +from libcpp.string cimport string as std_string +cdef extern from "" namespace "triqs::h5" : +#cdef extern from "" : #namespace "triqs::arrays::h5" : + + cdef cppclass h5_group "triqs::h5::group" : + h5_group (int, bint) + h5_group () + +cdef extern from "" namespace "triqs::h5" : + + cdef cppclass h5_extractor "triqs::h5::h5_extractor" [T] : + h5_extractor() + T & operator()( h5_group &, std_string) + +cdef inline h5_group make_h5_group (gr) : + import h5py + return h5_group (gr.id.id, type(gr) == h5py.highlevel.Group) diff --git a/pytriqs/pxd/inserter_in_map.pxd b/pytriqs/pxd/inserter_in_map.pxd new file mode 100644 index 00000000..ff419247 --- /dev/null +++ b/pytriqs/pxd/inserter_in_map.pxd @@ -0,0 +1,15 @@ +from libcpp.string cimport string as std_string +cdef extern from "" namespace "triqs::python_tools" : + + cdef cppclass inserter_in_map "triqs::python_tools::inserter_in_map" [T,U] : + inserter_in_map(T &) + void operator()(std_string &, U&) + + cdef cppclass inserter_in_map2 "triqs::python_tools::inserter_in_map2" [T,U] : + inserter_in_map(T &) + void operator()(std_string &, object) + + cdef cppclass printer "triqs::python_tools::printer" [T] : + printer() + std_string operator()(T &) + diff --git a/pytriqs/pxd/shared_ptr.pxd b/pytriqs/pxd/shared_ptr.pxd new file mode 100644 index 00000000..2a8f31d9 --- /dev/null +++ b/pytriqs/pxd/shared_ptr.pxd @@ -0,0 +1,8 @@ +cdef extern from "" namespace "std" : + cdef cppclass shared_ptr "std::shared_ptr" [T] : + shared_ptr(T*) + shared_ptr() + T* get() + void reset (T*) + + diff --git a/pytriqs/sumk/CMakeLists.txt b/pytriqs/sumk/CMakeLists.txt new file mode 100644 index 00000000..aec9a09f --- /dev/null +++ b/pytriqs/sumk/CMakeLists.txt @@ -0,0 +1,9 @@ + +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/sumk_discrete_from_lattice.py + ${CMAKE_CURRENT_SOURCE_DIR}/sumk_discrete.py +) + +install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/sumk) + diff --git a/pytriqs/sumk/__init__.py b/pytriqs/sumk/__init__.py new file mode 100644 index 00000000..15bbf989 --- /dev/null +++ b/pytriqs/sumk/__init__.py @@ -0,0 +1,26 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +from sumk_discrete import SumkDiscrete +from sumk_discrete_from_lattice import SumkDiscreteFromLattice + +__all__ = ['SumkDiscrete','SumkDiscreteFromLattice'] diff --git a/pytriqs/sumk/sumk_discrete.py b/pytriqs/sumk/sumk_discrete.py new file mode 100644 index 00000000..c35ce0f6 --- /dev/null +++ b/pytriqs/sumk/sumk_discrete.py @@ -0,0 +1,147 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +from pytriqs.gf.local import * +import pytriqs.utility.mpi as mpi +from itertools import * +import inspect +import copy,numpy + +class SumkDiscrete: + """ + INTERNAL USE + The function to compute \[ G \leftarrow \sum_k (\omega + \mu - eps_k - Sigma(k,\omega))^{-1} \] + for GF functions with blocks of the size of the matrix eps_k with a discrete sum. + The class contains the discretized hoppings and points in the arrays + Hopping, BZ_Points,BZ_weights,Mu_Pattern,Overlap (IF non orthogonal) + It can also generate a grid (ComputeGrid) for a regular grid or a Gauss-Legendre sum. + """ + def __init__ (self, dim, gf_struct, orthogonal_basis = True ): + """ + Just constructs the arrays, but without initializing them + - dim is the dimension + - gf_struct : Indices of the Green function + - orthogonal_basis : True by default + """ + self.__GFBLOC_Structure = copy.deepcopy(gf_struct) + self.orthogonal_basis,self.dim = orthogonal_basis,dim + + #------------------------------------------------------------- + + def resize_arrays (self, nk): + """ + Just constructs the arrays, but without initializing them + - nk : total number of k points + """ + # constructs the arrays. + no = len(self.__GFBLOC_Structure) + self.Hopping = numpy.zeros([nk,no,no],numpy.complex_) # t(k_index,a,b) + self.BZ_Points = numpy.zeros([nk,self.dim],numpy.float_) # k(k_index,:) + self.BZ_weights = numpy.ones([nk],numpy.float_)/ float(nk) # w(k_kindex) , default normalisation + self.Mu_Pattern = numpy.identity(no,numpy.complex_) if self.orthogonal_basis else numpy.zeros([no,no,nk],numpy.complex_) + self.Overlap = numpy.array(self.Mu_Pattern, copy=True) + + #------------------------------------------------------------- + + def __get_GFBloc_Structure(self) : + """Returns the ONLY block indices accepted for the G and Sigma argument of the + SumK function""" + return self.__GFBLOC_Structure + + GFBlocIndices = property(__get_GFBloc_Structure) + + #------------------------------------------------------------- + + def __call__ (self, Sigma, mu=0, eta=0, field=None, epsilon_hat=None, result=None, selected_blocks=()): + """ + - Computes : + result <- \[ \sum_k (\omega + \mu - field - t(k) - Sigma(k,\omega)) \] + if result is None, it returns a new GF with the results. + otherwise, result must be a GF, in which the calculation is done, and which is then returned. + (this allows chain calculation : SK(mu = mu,Sigma = Sigma, result = G).total_density() + which computes the sumK into G, and returns the density of G. + + - Sigma can be a X, or a function k-> X or a function k,eps ->X where : + - k is expected to be a 1d-numpy array of size self.dim of float, + containing the k vector in the basis of the RBZ (i.e. -0.5< k_i <0.5) + - eps is t(k) + - X is anything such that X[BlockName] can be added/subtracted to a GFBloc for BlockName in selected_blocks. + e.g. X can be a BlockGf(with at least the selected_blocks), or a dictionnary Blockname -> array + if the array has the same dimension as the GF blocks (for example to add a static Sigma). + + - field : Any k independant object to be added to the GF + + - epsilon_hat : a function of eps_k returning a matrix, the dimensions of Sigma + + - selected_blocks : The calculation is done with the SAME t(k) for all blocks. If this list is not None + only the blocks in this list are calculated. + e.g. G and Sigma have block indices 'up' and 'down'. + if selected_blocks ==None : 'up' and 'down' are calculated + if selected_blocks == ['up'] : only 'up' is calculated. 'down' is 0. + + + """ + S = Sigma.view_selected_blocks(selected_blocks) if selected_blocks else Sigma + Gres = result if result else Sigma.copy() + G = Gres.view_selected_blocks(selected_blocks) if selected_blocks else Gres + + # check input + assert self.orthogonal_basis, "Local_G : must be orthogonal. non ortho cases not checked." + assert isinstance(G,BlockGf), "G must be a BlockGf" + assert len(list(set([g.N1 for i,g in G]))) == 1 + assert self.BZ_weights.shape[0] == self.n_kpts(), "Internal Error" + no = list(set([g.N1 for i,g in G]))[0] + Sigma_Nargs = len(inspect.getargspec(Sigma)[0]) if callable (Sigma) else 0 + assert Sigma_Nargs <=2 , "Sigma function is not of the correct type. See Documentation" + + # Initialize + G.zero() + tmp,tmp2 = G.copy(),G.copy() + mupat = mu * numpy.identity(no, numpy.complex_) + tmp <<= iOmega_n + if field != None : tmp -= field + if Sigma_Nargs==0: tmp -= Sigma # substract Sigma once for all + + # Loop on k points... + for w, k, eps_k in izip(*[mpi.slice_array(A) for A in [self.BZ_weights, self.BZ_Points, self.Hopping]]): + + eps_hat = epsilon_hat(eps_k) if epsilon_hat else eps_k + tmp2 <<= tmp + tmp2 -= tmp2.n_blocks * [eps_hat - mupat] + + if Sigma_Nargs == 1: tmp2 -= Sigma (k) + elif Sigma_Nargs ==2: tmp2 -= Sigma (k,eps_k) + + tmp2.invert() + tmp2 *= w + G += tmp2 + + G <<= mpi.all_reduce(mpi.world,G,lambda x,y : x+y) + mpi.barrier() + + return Gres + + #------------------------------------------------------------- + + def n_kpts(self) : + """ Returns the number of k points""" + return self.BZ_Points.shape[0] diff --git a/pytriqs/sumk/sumk_discrete_from_lattice.py b/pytriqs/sumk/sumk_discrete_from_lattice.py new file mode 100644 index 00000000..5e3c9de4 --- /dev/null +++ b/pytriqs/sumk/sumk_discrete_from_lattice.py @@ -0,0 +1,178 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +from sumk_discrete import SumkDiscrete +from pytriqs.lattice.tight_binding import TBLattice + +class SumkDiscreteFromLattice (SumkDiscrete) : + r""" + * Computes + + .. math:: + G \leftarrow \sum_k (\omega + \mu - \epsilon_k - \Sigma(k,\omega))^{-1} + + for GF functions with blocks of the size of the matrix eps_k with a discrete sum. + + * The object contains the discretized hoppings and points in the arrays + Hopping, BZ_Points,BZ_weights,Mu_Pattern,Overlap (IF non orthogonal) + It can also generate a grid (ReComputeGrid) for a regular grid or a Gauss-Legendre sum + for the whole Brillouin Zone or a patch of the BZ. + """ + + def __init__(self, lattice, patch = None, n_points = 8, method = "Riemann") : + """ + :param lattice: The underlying pytriqs.lattice or pytriqs.super_lattice provinding t(k) + :param n_points: Number of points in the BZ in EACH direction + :param method: Riemann (default) or 'Gauss' (not checked) + """ + assert isinstance(lattice,TBLattice), "lattice must be a TBLattice instance" + self.SL = lattice + self.patch,self.method = patch,method + # init the array + SumkDiscrete.__init__ (self, dim = self.SL.dim, gf_struct = lattice.OrbitalNames) + self.Recompute_Grid(n_points, method) + + #------------------------------------------------------------- + + def __reduce__(self) : + return self.__class__, (self.SL, self.patch, self.BZ_weights.shape[0],self.method) + + #------------------------------------------------------------- + + def Recompute_Grid (self, n_points, method="Riemann", Q=None) : + """(Re)Computes the grid on the patch given at construction : + + * n_points : Number of points in the BZ in EACH direction + * method : Riemann (default) or 'Gauss' (not checked) + * Q : anything from which a 1d-array can be computed. + computes t(k+Q) instead of t(k) (useful for bare chi_0) + """ + assert method in ["Riemann","Gauss"], "method %s is not recognized"%method + self.method = method + self.resize_arrays(n_points) + if self.patch : + self.__Compute_Grid_One_patch(self.patch, n_points , method, Q) + else : + self.__Compute_Grid(n_points, method, Q) + + #------------------------------------------------------------- + + def __Compute_Grid (self, n_bz, method="Riemann", Q=None) : + """ + Internal + """ + + n_bz_A,n_bz_B, n_bz_C = n_bz, (n_bz if self.dim > 1 else 1), (n_bz if self.dim > 2 else 1) + nk = n_bz_A* n_bz_B* n_bz_C + self.resize_arrays(nk) + + # compute the points where to evaluate the function in the BZ and with the weights + def pts1d(N): + for n in range(N) : + yield (n - N/2 +1.0) / N + + if method=="Riemann" : + BZ_weights=1.0/nk + k_index =0 + for nz in pts1d(n_bz_C) : + for ny in pts1d(n_bz_B) : + for nx in pts1d(n_bz_A) : + self.BZ_Points[k_index,:] = (nx,ny,nz)[0:self.dim] + k_index +=1 + + elif method=="Gauss" : + assert 0, "Gauss : NR gauleg not checked" + k_index =0 + for wa,ptsa in NR.Gauleg(-pi,pi,n_bz_A) : + for wb,ptsb in NR.Gauleg(-pi,pi,n_bz_B) : + for wc,ptsc in NR.Gauleg(-pi,pi,n_bz_C) : + self.BZ_Points[k_index,:] = (ptsa,ptsb,ptsc)[0:self.dim] /(2*pi) + self.BZ_weights[k_index] = wa * wb * wc + k_index +=1 + else : + raise IndexError, "Summation method unknown" + + # A shift + if Q : + try : + Q = numpy.array(Q) + assert len(Q.shape) ==1 + except : + raise RuntimeError, "Q is not of correct type" + for k_index in range(self.N_kpts()) : + self.BZ_Points[k_index,:] +=Q + + # Compute the discretized hoppings from the Superlattice + self.Hopping[:,:,:] = self.SL.hopping(self.BZ_Points.transpose()).transpose(2,0,1) + + if self.orthogonal_basis: + self.Mu_Pattern[:,:] = self.SL.MuPattern[:,:] + else : + assert 0 , "not checked" + self.Overlap[:,:,:] = self.SL.Overlap(BZ_Points.transpose()) + mupat = self.SL.Mu_Pattern() + for k_index in range(self.N_kpts()) : + self.Mu_Pattern[:,:,k_index] = Num.dot( mupat ,self.Overlap[:,:,k_index]) + + #------------------------------------------------------------- + + + def __Compute_Grid_One_patch(self, patch, n_bz, method = "Riemann", Q=None) : + """ + Internal + """ + + tritemp = numpy.array(patch._triangles) + ntri = len(tritemp)/3 + nk = n_bz*n_bz*ntri + self.resize_arrays(nk) + + # Reshape the list to group 3 points together + triangles = tritemp.reshape((ntri,3,2)) + total_weight = 0 + + # Loop over all k-points in the triangles + k_index = 0 + for (a,b,c),w in zip(triangles,patch._weights): + g = ((a+b+c)/3.0-a)/n_bz; + for i in range(n_bz): + s = i/float(n_bz) + for j in range(n_bz-i): + t = j/float(n_bz) + for k in range(2): + rv = a+s*(b-a)+t*(c-a)+(k+1)*g + if k == 0 or j < n_bz-i-1: + self.BZ_Points[k_index] = rv + self.BZ_weights[k_index] = w/(n_bz*n_bz) + total_weight += self.BZ_weights[k_index] + k_index = k_index+1 + + # Normalize weights so that they sum up to 1 + self.BZ_weights /= total_weight + + # Compute the discretized hoppings from the Superlattice + self.Hopping[:,:,:] = self.SL.hopping(self.BZ_Points.transpose()).transpose(2,0,1) + + if self.orthogonal_basis: + self.Mu_Pattern[:,:] = self.SL.MuPattern[:,:] + else : + assert 0 , "not checked" diff --git a/pytriqs/utility/CMakeLists.txt b/pytriqs/utility/CMakeLists.txt new file mode 100644 index 00000000..f6da00ce --- /dev/null +++ b/pytriqs/utility/CMakeLists.txt @@ -0,0 +1,12 @@ + +SET(PYTHON_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py + ${CMAKE_CURRENT_SOURCE_DIR}/dichotomy.py + ${CMAKE_CURRENT_SOURCE_DIR}/dist_on_nodes.py + ${CMAKE_CURRENT_SOURCE_DIR}/mpi.py + ${CMAKE_CURRENT_SOURCE_DIR}/redirect.py +) + +install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/utility) + + diff --git a/pytriqs/utility/__init__.py b/pytriqs/utility/__init__.py new file mode 100644 index 00000000..8f2e461e --- /dev/null +++ b/pytriqs/utility/__init__.py @@ -0,0 +1,23 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +__all__ = [] diff --git a/pytriqs/utility/dichotomy.py b/pytriqs/utility/dichotomy.py new file mode 100644 index 00000000..335a761e --- /dev/null +++ b/pytriqs/utility/dichotomy.py @@ -0,0 +1,99 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +import pytriqs.utility.mpi as mpi + +def dichotomy(function, x_init, y_value, precision_on_y, delta_x, max_loops = 1000, x_name="", y_name="", verbosity=1): + """ + Solver function(x) = y_value. + + Arguments : + - function : function (real valued) to be solved by dichotomy + - x_init : Init value for x. On success, returns the new value of x + - y_value : + - precision_on_y : calculation stops for abs(f(x) - y_value)0.0 : return 1 + if x<0.0 : return -1 + return 0 + + mpi.report("Dichotomy adjustment of %(x_name)s to obtain %(y_name)s = %(y_value)f +/- %(precision_on_y)f"%locals() ) + PR = " " + if x_name=="" or y_name=="" : verbosity = max(verbosity,1) + x=x_init;delta_x= abs(delta_x) + + # First find the bounds + y1 = function(x) + eps = sign(y1-y_value) + x1=x;y2=y1;x2=x1 + nbre_loop=0 + while (nbre_loop<= max_loops) and (y2-y_value)*eps>0 and abs(y2-y_value)>precision_on_y : + nbre_loop +=1 + x2 -= eps*delta_x + y2 = function(x2) + if x_name!="" and verbosity>2: + mpi.report("%(PR)s%(x_name)s = %(x2)f \n%(PR)s%(y_name)s = %(y2)f"%locals()) + + mpi.report("%(PR)s%(x1)f < %(x_name)s < %(x2)f"%locals()) + mpi.report("%(PR)s%(y1)f < %(y_name)s < %(y2)f"%locals()) + + # Now mu is between mu1 and mu2 + yfound = y2 + # We found bounds. What if the next loop is never run ? + # i.e. x1 or x2 are close to the solution + # we have to know which one is the best .... + if abs(y1-y_value)< abs(y2-y_value) : + x=x1 + else: + x=x2 + + #Now let's refine our mu.... + while (nbre_loop<= max_loops) and (abs(yfound-y_value)>precision_on_y) : + nbre_loop +=1 + x = x1 + (x2 - x1) * (y_value - y1)/(y2-y1) + yfound = function(x) + if (y1-y_value)*(yfound - y_value)>0 : + x1 = x; y1=yfound + else : + x2= x;y2=yfound; + if verbosity>2 : + mpi.report("%(PR)s%(x1)f < %(x_name)s < %(x2)f"%locals()) + mpi.report("%(PR)s%(y1)f < %(y_name)s < %(y2)f"%locals()) + if abs(yfound - y_value) < precision_on_y : + if verbosity>0: + mpi.report("%(PR)s%(x_name)s found in %(nbre_loop)d iterations : "%locals()) + mpi.report("%(PR)s%(y_name)s = %(yfound)f;%(x_name)s = %(x)f"%locals()) + return (x,yfound) + else : + if verbosity>0: + mpi.report("%(PR)sFAILURE to adjust %(x_name)s to the value %(y_value)f after %(nbre_loop)d iterations."%locals()) + return (None,None) + diff --git a/pytriqs/utility/dist_on_nodes.py b/pytriqs/utility/dist_on_nodes.py new file mode 100644 index 00000000..3f468a09 --- /dev/null +++ b/pytriqs/utility/dist_on_nodes.py @@ -0,0 +1,154 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +import os,sys,time,cPickle +import pytriqs.utility.mpi as mpi + +class DistributionOnNodes: + """ + Distribution of the calculation of a function over the nodes. + Derive from it and reimplement : + - treate : will be called by the MASTER each time a point is computed. this function will typically + store it, and possibly affect the list of points waiting to be computed, as returned by next... + NB : "None" result is ignored. + - next : next point to compute. If it returns None (which is not the same as finished()) + the computation is ignored. + - finished() : Whether the calculation is finished + - the_function : function to be computed, with the argument given by next() + In the module DistributionOnNodeTest is a test example + """ + SleepTime = 1 + + #def treate(self,x,node_where_computed): pass + #def next(self): return None + #def finished(self): return True #None + #def the_function(self,x): return x + + def run(self): + """ + """ + mpi.barrier() + if mpi.size==1 : # single machine. Avoid the fork + while not(self.finished()): + n = self.next() + if n!=None : + self.treate(self.the_function(n),0) + return + + # Code for multiprocessor machines + RequestList,pid = [],0 # the pid of the child on the master + node_running,node_stopped= mpi.size*[False],mpi.size*[False] + + if mpi.rank==0 : + while not(self.finished()) or pid or [n for n in node_running if n] != [] : + # Treat the request which have self.finished + def keep_request(r) : + #if not(mpi.test(r)) : return True + #if r.message !=None : self.treate(*r.message) + #node_running[r.status.source] = False + T = r.test() + if T is None : return True + value = T[0] + if value !=None : self.treate(*value) + node_running[T[1].source] = False + return False + RequestList = filter(keep_request,RequestList) + # send new calculation to the nodes or "stop" them + for node in [ n for n in range(1,mpi.size) if not(node_running[n] or node_stopped[n]) ] : + #open('tmp','a').write("master : comm to node %d %s\n"%(node,self.finished())) + mpi.send(self.finished(),node) + if not(self.finished()) : + mpi.send(self.next(),node) # send the data for the computation + node_running[node] = True + RequestList.append(mpi.irecv(node)) #Post the receive + else : + node_stopped[node] = True + + # Look if the child process on the master has self.finished. + if not(pid) or os.waitpid(pid,os.WNOHANG) : + if pid : + RR = cPickle.load(open("res_master",'r')) + if RR != None : self.treate(*RR) + if not(self.finished()) : + pid=os.fork(); + currently_calculated_by_master = self.next() + if pid==0 : # we are on the child + if currently_calculated_by_master : + res = self.the_function(currently_calculated_by_master) + else: + res = None + cPickle.dump((res,mpi.rank),open('res_master','w')) + os._exit(0) # Cf python doc. Used for child only. + else : pid=0 + if (pid): time.sleep(self.SleepTime) # so that most of the time is for the actual calculation on the master + + else : # not master + while not(mpi.recv(0)) : # master will first send a finished flag + omega = mpi.recv(0) + if omega ==None : + res = None + else : + res = self.the_function(omega) + mpi.send((res,mpi.rank),0) + + mpi.barrier() + +######################################### + +class DistributionOnNodesOneStack(DistributionOnNodes) : + """ + A special of distribution, when one has a given stack of points to compute + Reimplement just the_function + """ + def __init__(self,the_stack) : + self.__l = the_stack + self.__l.reverse() + self.__result = [] + + def treate(self,x,node): + self.__result.append((node,x)) + + def finished(self): + return self.__l==[] + + def next(self): + return self.__l.pop() + + def result(self) : return self.__result + + def run(self): + DistributionOnNodes.run(self) + return self.result() + + +# TEST ONLY +class DistributionOnNodesTest(DistributionOnNodesOneStack) : + """ + """ + def the_function(self,x): + return (x,x+1,x+2) + +if __name__ == '__main__' : + d = DistributionOnNodesTest(range(21)) + d.run() + if mpi.rank==0 : + print d.result() diff --git a/pytriqs/utility/mpi.py b/pytriqs/utility/mpi.py new file mode 100644 index 00000000..190b67be --- /dev/null +++ b/pytriqs/utility/mpi.py @@ -0,0 +1,110 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +import os,sys,datetime +myprint_err = lambda x : sys.stderr.write("%s\n"%x) +myprint_out = lambda x : sys.stdout.write("%s\n"%x) + +if 'additional_builtin_modules' in dir(sys) and 'mpi' in sys.additional_builtin_modules: #link is static + from mpi import * +else : + from pytriqs.boost.mpi import * + +if rank==0 : + myprint_err ("Starting on %s Nodes at : %s"%(size,str(datetime.datetime.now()))) + +master =0 + +All_Nodes_report = False #True + +def bcast(x) : + return broadcast(world,x,0) + +def send(val,node) : + world.send(node,0,val) + #print "node ", rank, "has sent ",val, " to node ", node + +def recv(node) : + r = world.recv(node,0) + #print "node", rank, "receives ", r , "from Node ",node + return r + +def irecv(node) : + return world.irecv(node,0) + +def barrier() : + world.barrier() + + +Verbosity_Level_Report_Max = 1 +def report(*x,**opt): + """ print on the master, do nothing on the nodes """ + try : + if opt['Verbosity_Level'] > Verbosity_Level_Report_Max : return + except : + pass + if All_Nodes_report and rank!=0 : + for y in x: + open('report_node%s'%rank,'a').write(str(y) + '\n') # print y + + if rank==0 : + myprint,myflush = (myprint_err,sys.stderr.flush) if 'stderr' in opt and opt['stderr'] else (myprint_out,sys.stdout.flush) + for y in x: + myprint( y) # open('report','a').write(str(y) + '\n') # print y + myflush() # be sure to flush the buffer! + +def slice_inf(imin,imax) : + j=(imax - imin + 1)/size + i= imax - imin + 1 - size*j + return imin + rank*(j+1) if rank<=i-1 else imin + rank*j + i + +def slice_sup(imin,imax) : + j=(imax - imin + 1)/size + i= imax - imin + 1 - size*j; + return imin + (rank+1)*(j+1) -1 if rank<=i-1 else imin + (rank+1)*j + i - 1 + +def slice_array(A) : + """Given an array A, it returns a VIEW of a slice over the first dim on the node""" + imax = A.shape[0]-1 + return A[slice_inf(0,imax):slice_sup(0,imax)+1] # +1 due to the slice convention + +def is_master_node(): return rank == master + +HostNames = {} +def master_gets_host_names(): + """ find the host name of all the nodes """ + from socket import gethostname + global HostNames + HostNames[rank] = gethostname() + if is_master_node() : + for proc in range (1,size) : + HostNames[proc],status = recv(proc) + else: + send(gethostname(),master) + barrier() + assert len(HostNames)==size," internal pb MPI module" + + if is_master_node() : + print "Hostnames : " + for u,host in HostNames.items() : + print "Node %d on machine %s"%(u,host) + diff --git a/pytriqs/utility/redirect.py b/pytriqs/utility/redirect.py new file mode 100644 index 00000000..5da72937 --- /dev/null +++ b/pytriqs/utility/redirect.py @@ -0,0 +1,66 @@ +import threading, time, sys, os, fcntl + +__all__ = ['start_redirect', 'stop_redirect'] + +# A thread that will redirect the c++ stdout to the ipython notebook +class T(threading.Thread): + + def __init__(self): + threading.Thread.__init__(self) + self.go_on = True + + # copy the c++ stdout handler for later + self.oldhandle = os.dup(1) + + def stop(self): + self.go_on = False + + def run(self): + + # create a pipe and glue the c++ stdout to its write end + # make the read end non-blocking + piper, pipew = os.pipe() + os.dup2(pipew, 1) + os.close(pipew) + fcntl.fcntl(piper,fcntl.F_SETFL,os.O_NONBLOCK) + + while self.go_on: + + # give the system 1 second to fill up the pipe + time.sleep(1) + try: + # read out the pipe and write it to the screen + # if the pipe was empty it return an error (hence the try-except) + sys.stdout.write(os.read(piper, 10000)) + sys.stdout.flush() + except: + pass + + # when we want to stop the thread put back the c++ stdout where it was + # clear the pipe + os.dup2(self.oldhandle, 1) + os.close(piper) + return + +# flag to know if the thread was started +started = False + +# start the redirection +def start_redirect(): + global started + global a + if started: + print "Already redirected c++ output" + else: + started = True + # start a new redirection thread + a = T() + a.start() + +# stop the redirection +def stop_redirect(): + global started + global a + if started: + started = False + a.stop() diff --git a/pytriqs/version.py.in b/pytriqs/version.py.in new file mode 100644 index 00000000..beb6739f --- /dev/null +++ b/pytriqs/version.py.in @@ -0,0 +1,28 @@ + +VersionNumber = "1.0" + +# if we use a git clone, then tag with the hash, else just the plain number +git_hash = "@GIT_HASH@" + +branch_info_all = [ b.strip() for b in """@GIT_BRANCHES@""".split('\n')] +try : + branch_info = [ b[1:].strip() for b in branch_info_all if b[0] == '*'][0] +except : + branch_info = "" + +revision = "branch = %s; commit = %s"%(branch_info, git_hash if git_hash else VersionNumber) + +def cmake_options() : + return open ("@CMAKE_BINARY_DIR@/CMakeCache.txt").read() + + +machine_info = """Code compiled on @myHostName@ under login @WhoAmI@ """ + +all_info = """ + Code revision : %s + %s + For all the configuration options, use cmake_options() + """%(revision,machine_info) + +greeting = """ Code revision : %s """%(revision) + diff --git a/shells/CMakeLists.txt b/shells/CMakeLists.txt new file mode 100644 index 00000000..594bfb1c --- /dev/null +++ b/shells/CMakeLists.txt @@ -0,0 +1,30 @@ + +MESSAGE( STATUS "Preparing the various scripts ") +# a simple script to set the python path and have the same effect as the statically compiled code. +option(TRIQS_ADD_PYPATHS_TO_SHELLS "Add the correct python paths to shell (ON except for packaging)" ON) +mark_as_advanced( TRIQS_ADD_PYPATHS_TO_SHELLS) +if (TRIQS_ADD_PYPATHS_TO_SHELLS) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/pytriqs_shell.bash.in ${CMAKE_CURRENT_BINARY_DIR}/pytriqs) + if (TRIQS_IPYTHON_DETECTED) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/ipytriqs_shell.bash.in ${CMAKE_CURRENT_BINARY_DIR}/ipytriqs) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/ipytriqs_shell.notebook.bash.in ${CMAKE_CURRENT_BINARY_DIR}/ipytriqs_notebook) + endif (TRIQS_IPYTHON_DETECTED) +else (TRIQS_ADD_PYPATHS_TO_SHELLS) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/pytriqs_shell.nopypath.bash.in ${CMAKE_CURRENT_BINARY_DIR}/pytriqs) + if (TRIQS_IPYTHON_DETECTED) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/ipytriqs_shell.nopypath.bash.in ${CMAKE_CURRENT_BINARY_DIR}/ipytriqs) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/ipytriqs_shell.notebook.nopypath.bash.in ${CMAKE_CURRENT_BINARY_DIR}/ipytriqs_notebook) + endif (TRIQS_IPYTHON_DETECTED) +endif (TRIQS_ADD_PYPATHS_TO_SHELLS) + +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/pytriqs_for_test_shell.bash.in ${CMAKE_BINARY_DIR}/run_pytriqs_for_test.sh) +execute_process( COMMAND chmod u+x ${CMAKE_BINARY_DIR}/run_pytriqs_for_test.sh ) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pytriqs DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) + + if (TRIQS_IPYTHON_DETECTED) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ipytriqs ${CMAKE_CURRENT_BINARY_DIR}/ipytriqs_notebook DESTINATION bin + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) + endif (TRIQS_IPYTHON_DETECTED) + + diff --git a/shells/ipytriqs_shell.bash.in b/shells/ipytriqs_shell.bash.in new file mode 100755 index 00000000..d728e476 --- /dev/null +++ b/shells/ipytriqs_shell.bash.in @@ -0,0 +1,13 @@ +#!/bin/bash +export PYTHONPATH=@CMAKE_INSTALL_PREFIX@/@TRIQS_PYTHON_LIB_DEST_ROOT@:$PYTHONPATH + +@PYTHON_INTERPRETER@ -c " +import sys +import IPython +if IPython.__version__ >= '0.11' : + from IPython.frontend.terminal.ipapp import launch_new_instance + sys.exit(launch_new_instance()) +else: + import IPython.Shell + IPython.Shell.start().mainloop() +" $@ diff --git a/shells/ipytriqs_shell.nopypath.bash.in b/shells/ipytriqs_shell.nopypath.bash.in new file mode 100755 index 00000000..8a6d17b5 --- /dev/null +++ b/shells/ipytriqs_shell.nopypath.bash.in @@ -0,0 +1,13 @@ +#!/bin/bash + +@PYTHON_INTERPRETER@ -c " +import sys +import IPython +if IPython.__version__ >= '0.11' : + from IPython.frontend.terminal.ipapp import launch_new_instance + sys.exit(launch_new_instance()) +else: + import IPython.Shell + IPython.Shell.start().mainloop() +" $@ + diff --git a/shells/ipytriqs_shell.notebook.bash.in b/shells/ipytriqs_shell.notebook.bash.in new file mode 100755 index 00000000..4882a3f4 --- /dev/null +++ b/shells/ipytriqs_shell.notebook.bash.in @@ -0,0 +1,13 @@ +#!/bin/bash +export PYTHONPATH=@CMAKE_INSTALL_PREFIX@/@TRIQS_PYTHON_LIB_DEST_ROOT@:$PYTHONPATH + +@PYTHON_INTERPRETER@ -c " +import sys +sys.argv.insert(1, 'notebook') +sys.argv.insert(2, '--pylab=inline') +sys.argv.insert(3, '--MappingKernelManager.time_to_dead=3600') +import IPython +assert IPython.__version__ >= '0.11' , 'ipython version too low: need 0.12 or higher for the notebook' +from IPython.frontend.terminal.ipapp import launch_new_instance +sys.exit(launch_new_instance()) +" $@ diff --git a/shells/ipytriqs_shell.notebook.nopypath.bash.in b/shells/ipytriqs_shell.notebook.nopypath.bash.in new file mode 100755 index 00000000..aba796be --- /dev/null +++ b/shells/ipytriqs_shell.notebook.nopypath.bash.in @@ -0,0 +1,12 @@ +#!/bin/bash + +@PYTHON_INTERPRETER@ -c " +import sys +sys.argv.insert(1, 'notebook') +sys.argv.insert(2, '--pylab=inline') +sys.argv.insert(3, '--MappingKernelManager.time_to_dead=3600') +import IPython +assert IPython.__version__ >= '0.11' , 'ipython version too low: need 0.12 or higher for the notebook' +from IPython.frontend.terminal.ipapp import launch_new_instance +sys.exit(launch_new_instance()) +" $@ diff --git a/shells/pytriqs_for_test_shell.bash.in b/shells/pytriqs_for_test_shell.bash.in new file mode 100755 index 00000000..65b75524 --- /dev/null +++ b/shells/pytriqs_for_test_shell.bash.in @@ -0,0 +1,5 @@ +#!/bin/bash +export PYTHONPATH=@CMAKE_BINARY_DIR@:$PYTHONPATH + +@PYTHON_INTERPRETER@ $@ + diff --git a/shells/pytriqs_shell.bash.in b/shells/pytriqs_shell.bash.in new file mode 100755 index 00000000..b0bfc3ed --- /dev/null +++ b/shells/pytriqs_shell.bash.in @@ -0,0 +1,4 @@ +#!/bin/bash +export PYTHONPATH=@CMAKE_INSTALL_PREFIX@/@TRIQS_PYTHON_LIB_DEST_ROOT@:$PYTHONPATH + +@PYTHON_INTERPRETER@ $@ diff --git a/shells/pytriqs_shell.nopypath.bash.in b/shells/pytriqs_shell.nopypath.bash.in new file mode 100755 index 00000000..634eb595 --- /dev/null +++ b/shells/pytriqs_shell.nopypath.bash.in @@ -0,0 +1,4 @@ +#!/bin/bash + +@PYTHON_INTERPRETER@ $@ + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..02c3ea0f --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,16 @@ +# some specific flags for tests... +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +include_directories( ${CMAKE_SOURCE_DIR} ) + +SET( link_libs ${LAPACK_LIBS} ${BOOST_LIBRARY} ) +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + list (REMOVE_DUPLICATES link_libs) +ENDIF( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +link_libraries( ${link_libs} triqs) + +add_subdirectory(triqs) +if (PythonSupport) + add_subdirectory(pytriqs) +endif() +add_subdirectory(speed) + diff --git a/test/pytriqs/CMakeLists.txt b/test/pytriqs/CMakeLists.txt new file mode 100644 index 00000000..38392411 --- /dev/null +++ b/test/pytriqs/CMakeLists.txt @@ -0,0 +1,4 @@ +enable_testing() +find_package(TestScriptHdf) +add_all_subdirectories_with_cmakelist() + diff --git a/test/pytriqs/arrays/CMakeLists.txt b/test/pytriqs/arrays/CMakeLists.txt new file mode 100644 index 00000000..99cb5a8f --- /dev/null +++ b/test/pytriqs/arrays/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +cython_module( array_cython array_cython ) + +add_triqs_test_txt( array_cython ) + +cython_module( expr_cython expr ) + +cython_module( bug bug ) + diff --git a/test/pytriqs/arrays/__init__.py b/test/pytriqs/arrays/__init__.py new file mode 100644 index 00000000..edb351e9 --- /dev/null +++ b/test/pytriqs/arrays/__init__.py @@ -0,0 +1,24 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +__all__ = [] + diff --git a/test/pytriqs/arrays/array_cython.output b/test/pytriqs/arrays/array_cython.output new file mode 100644 index 00000000..ccf030d4 --- /dev/null +++ b/test/pytriqs/arrays/array_cython.output @@ -0,0 +1,107 @@ +---- calling f------------- + A[:,:,0] = +[[1 2] + [3 4]] + A[:,:,1] = +[[10 20] + [30 40]] + A(range(),range(),0) = +[[1,2] + [3,4]] + A(range(),range(),1) = +[[10,20] + [30,40]] + memory_layout (permutation of indices) = (2 1 0) + strides = (6 3 1) + is_contiguous = 1 +---- END calling f------------- +---- calling f------------- + A[:,:,0] = +[[1 3] + [2 4]] + A[:,:,1] = +[[20 60] + [40 80]] + A(range(),range(),0) = +[[1,3] + [2,4]] + A(range(),range(),1) = +[[20,60] + [40,80]] + memory_layout (permutation of indices) = (2 0 1) + strides = (3 6 1) + is_contiguous = 1 +---- END calling f------------- + ------------ F -------------- +---- calling f------------- + A[:,:,0] = +[[1 2] + [3 4]] + A[:,:,1] = +[[10 20] + [30 40]] + A(range(),range(),0) = +[[1,2] + [3,4]] + A(range(),range(),1) = +[[10,20] + [30,40]] + memory_layout (permutation of indices) = (0 1 2) + strides = (1 2 4) + is_contiguous = 1 +---- END calling f------------- +---- calling f------------- + A[:,:,0] = +[[1 3] + [2 4]] + A[:,:,1] = +[[20 60] + [40 80]] + A(range(),range(),0) = +[[1,3] + [2,4]] + A(range(),range(),1) = +[[20,60] + [40,80]] + memory_layout (permutation of indices) = (1 0 2) + strides = (2 1 4) + is_contiguous = 1 +---- END calling f------------- +---- calling f------------- + A[:,:,0] = +[[ 1 40 100] + [ 2 80 200]] + A[:,:,1] = +[[ 3 120 300] + [ 4 160 400]] + A(range(),range(),0) = +[[1,40,100] + [2,80,200]] + A(range(),range(),1) = +[[3,120,300] + [4,160,400]] + memory_layout (permutation of indices) = (2 0 1) + strides = (2 4 1) + is_contiguous = 1 +---- END calling f------------- +---- calling f------------- + A[:,:,0] = +[[ 1 6] + [ 40 240] + [100 600]] + A[:,:,1] = +[[ 2 8] + [ 80 320] + [200 800]] + A(range(),range(),0) = +[[1,6] + [40,240] + [100,600]] + A(range(),range(),1) = +[[2,8] + [80,320] + [200,800]] + memory_layout (permutation of indices) = (1 2 0) + strides = (4 1 2) + is_contiguous = 1 +---- END calling f------------- diff --git a/test/pytriqs/arrays/array_cython.py b/test/pytriqs/arrays/array_cython.py new file mode 100644 index 00000000..6069593f --- /dev/null +++ b/test/pytriqs/arrays/array_cython.py @@ -0,0 +1,27 @@ +#import pytriqs.tools.test.array_cython as M +import array_cython as M +import numpy as np,sys + +a = np.array([[1,2],[3,4]]) +b = np.array( np.transpose( np.array([a, 10*a,100*a]), (1,2,0)), order = 'C') +c = b.transpose(1,0,2) +M.f(b) +M.f(c) + +print " ------------ F --------------" + +b = np.array( np.transpose( np.array([a, 10*a,100*a]), (1,2,0)), order = 'F') +c = b.transpose(1,0,2) +M.f(b) +M.f(c) + +d = b.transpose(1,2,0) +M.f(d) + +dd = b.transpose(2,0,1) +M.f(dd) + +#print "ref b ", sys.getrefcount(b) +#M.f(b) +#print "ref b ", sys.getrefcount(b) + diff --git a/test/pytriqs/arrays/array_cython.pyx b/test/pytriqs/arrays/array_cython.pyx new file mode 100644 index 00000000..06dd8697 --- /dev/null +++ b/test/pytriqs/arrays/array_cython.pyx @@ -0,0 +1,28 @@ +#!python +#cython: embedsignature=True +from cython.operator cimport dereference as deref, preincrement as inc #dereference and increment operators +cimport cython +import numpy +import string +import warnings + +from dcomplex cimport * +from arrays cimport * +#from libcpp.vector cimport vector +#from libcpp.string cimport string as std_string +#from extractor cimport * + +cdef extern from "./f.hpp" : + cdef void f_c2 "f2" ( array_view[long,TWO] & ) + cdef void f_c "f" ( array_view[long,THREE] & ) + +def f(A) : + print "---- calling f-------------" + print " A[:,:,0] = \n", A[:,:,0] + print " A[:,:,1] = \n", A[:,:,1] + f_c(array_view[long,THREE](A)) + #f_c(array_view[long,TWO](A)) + print "---- END calling f-------------" + + + diff --git a/test/pytriqs/arrays/bug.hpp b/test/pytriqs/arrays/bug.hpp new file mode 100644 index 00000000..462939e7 --- /dev/null +++ b/test/pytriqs/arrays/bug.hpp @@ -0,0 +1,7 @@ +#include + +struct Obj1 { + std::vector V; + Obj1() : V(10000){} +}; + diff --git a/test/pytriqs/arrays/bug.pyx b/test/pytriqs/arrays/bug.pyx new file mode 100644 index 00000000..085d5a29 --- /dev/null +++ b/test/pytriqs/arrays/bug.pyx @@ -0,0 +1,27 @@ +#!python +cimport cython + +cdef extern from "./bug.hpp" : + cdef cppclass Obj1 : + Obj1() + +cdef class G_generic : + def __init__(self) : + pass + +cdef class G_cython (G_generic) : + cdef Obj1 co + def __init__(self, A): + G_generic.__init__(self) + self.co = Obj1() + + # Comment this and there is a memory leak + def __dealloc__(self) : + pass + +class G (G_cython) : + def __init__(self, A): + G_cython.__init__(self,A) + + + diff --git a/test/pytriqs/arrays/expr.py b/test/pytriqs/arrays/expr.py new file mode 100644 index 00000000..4ce6584a --- /dev/null +++ b/test/pytriqs/arrays/expr.py @@ -0,0 +1,7 @@ +import numpy as np +from expr import f + +a = np.array( [[1,2], [3,4]]) + +print f(a) + diff --git a/test/pytriqs/arrays/expr.pyx b/test/pytriqs/arrays/expr.pyx new file mode 100644 index 00000000..4c5f30b5 --- /dev/null +++ b/test/pytriqs/arrays/expr.pyx @@ -0,0 +1,39 @@ +#!python +#cython: embedsignature=True +from cython.operator cimport dereference as deref, preincrement as inc #dereference and increment operators +#cimport cython +import numpy +import string +import warnings + +from arrays cimport * + +def f(A) : + + # Solution 1 + cdef array_view[long,TWO] a = array_view[long,TWO](A) + # .... + a.call ( _i(), _j()) << ( _i() + 3*_j() + 2 ) + # can not do this ... unless with preprocessing the cython files... + # indeed _i is placeholder[ONE], not lazy_expr, I need to erase its type for + # cython compiler... + #a.call ( _i, _j) << ( _i + 3*_j + 2 ) + #.... + return A + + #Solution 2 + cdef placeholder[ONE] i_ + cdef placeholder[TWO] j_ + array_view[long,TWO] (A).call ( ph(i_), ph(j_)) << ph(i_) + ph(j_) + + #Solution 3 ? + array_view[long,TWO] (A).call ( ph0(), ph1()) << ph0() + ph1() + + #array_view[long,TWO] (A).call ( _i(), _j()) << 3*_i() + _j()*2 + + #array_view[long,TWO] (A)( ph(i_), ph(j_)) << ph(i_) + ph(j_) + + return A + + + diff --git a/test/pytriqs/arrays/f.hpp b/test/pytriqs/arrays/f.hpp new file mode 100644 index 00000000..99b3ecfd --- /dev/null +++ b/test/pytriqs/arrays/f.hpp @@ -0,0 +1,16 @@ +#include + +using namespace triqs::arrays; + +void f(array_view A) { + + std::cout << " A(range(),range(),0) = "<< A(range(),range(),0) <;!!R=N9Hgk?qn5M@DQixwxuYnH|)h%VA~ z01f<$rMCOzr4yA(>A;}T3w@J2I~=dLCQ=d1QtbZ>4rs$}YC{yx+*ce-6Zq`6-Qz@RwGmOHuqOp@U?C6WQv|6pO z=&*fvzB~cQkKT&gR@W)1crA)e?v;yynH>6FZ228F?T)RtJKuDB=zIp zL)z7X6Lx&aTEE-t{p|Rh;a1ofdVJ@P7sUUQ&M&{+iW#5myt= zZ^U^Gs;?M-PQ59{oyPu?>KI|KQn^^~5SC_@gitT+W~i3^fa5{pI|=9y&_9?3FAZ>9 zjBkWSi3boLNFFW$;s=ZeJ{R*^;c3Bh8ypk!+X49ilEp$a^Pv3O#heZpk+w z|A6@b%nxgp`C^~R{IL}>pX@1_U#64!W|)75dSJ7qKG;yH7j|CihwYPkVhK`T4E4rP ze+>1=HcEZ68B(vzL+Y2Em3n5VZ-#njsDIWb_X8`E`-8F3Ig7hYW*Fyjs^xrz8Cv?+ zxz1}eL!7qF81_&eyx2Ubc0zg{lwQlsP7lw6OGj!ppK;HJC!2O&T=8ZeoXff8TDCSH zq6;sasG6D&o41U#jL=!Yw6u2Gw3QZEoVmYzzKaDc^OJV0F1ElnQ%7z=g#}jm1z9$2 zKL8m)50BeD?f_iuw|>pSi3KpSe`>^K?}G03l!^=GqXG+IO}=jA`&or>W8c6fTPyCC zZZR8bt9~qk&2!%yROVd_x#8}H*W8Q2^U9=B;&cq{gh$8#a2@X99_ zzD*202t#(K*!wO&2xV!^0ikLY}j>mrCVGLc$=@b z1V?|<-KKsTPxHwi`KR@0eZoWd2ruEMcql%Km*OWrh#%sM_#-}vU*enir+iR;?#&zJ zlk(eB{z)IC7t#;uiS$K!BmI#cNuQ)w(l6. +# +################################################################################ + +from pytriqs.lattice.tight_binding import * + +# Define the Bravais Lattice : a square lattice in 2d +BL = BravaisLattice(units = [(1,0,0) , (0,1,0) ], orbital_positions= {"" : (0,0,0)} ) + +# Prepare a nearest neighbour hopping on BL +t = -1.00 # First neighbour Hopping +tp = 0.0*t # Second neighbour Hopping + +# Hopping[ Displacement on the lattice] = [[t11,t12,t13....],[t21,t22,t23....],...,[....,tnn]] +# where n=Number_Orbitals +hop = { (1,0) : [[ t]], + (-1,0) : [[ t]], + (0,1) : [[ t]], + (0,-1) : [[ t]], + (1,1) : [[ tp]], + (-1,-1): [[ tp]], + (1,-1) : [[ tp]], + (-1,1) : [[ tp]]} + +TB = TightBinding(BL, hop) + +# Compute the density of states +d = dos(TB, n_kpts= 500, n_eps = 101, name = 'dos')[0] + +from pytriqs.archive import HDFArchive +R = HDFArchive('dos.output.h5','w') +R['SquareLatt'] = d + diff --git a/test/pytriqs/base/gf_base_op.output.h5 b/test/pytriqs/base/gf_base_op.output.h5 new file mode 100644 index 0000000000000000000000000000000000000000..852524eea9dd8d9633e2d52e43c29d941cdb0f9b GIT binary patch literal 127648 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
    e^0ob{&;?VutuoLFlg6<<r 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 k&mTW?^0nBsP5E. +# +################################################################################ + +from pytriqs.archive import * +from pytriqs.gf.local import * +import numpy, copy + +h=HDFArchive('gf_base_op.output.h5','w') + +ga = GfImFreq(indices = [1,2], beta = 50, n_points = 100, name = "a1Block") +gb = GfImFreq(indices = [1,2], beta = 50, n_points = 100, name = "b1Block") + +G = BlockGf(name_list = ('a','b'), block_list = (ga,gb), make_copies = False) + +G <<= iOmega_n + 2.0 +h['G1'] = G + +# inverse: +G <<= inverse(G) + +# Density: +dens = G.total_density() +h['dens'] = dens + +# FT: +f = lambda g,L : GfImTime(indices = g.indices, beta = g.mesh.beta, n_points =L ) +gt = BlockGf(name_block_generator = [ (n,f(g,200) ) for n,g in G], make_copies=False, name='gt') +for (i,gtt) in gt : gtt.set_from_inverse_fourier(G[i]) + +h['gt'] = gt + +# Matrix operations: +ga2 = GfImFreq(indices = [1,2,3], beta = 50, n_points = 100, name = "a1Block") +mat = numpy.array([[1.0,0.0,1.0],[-1.0,1.0,0.0]], numpy.complex) + +ga2.from_L_G_R(mat.transpose(),ga,mat) + +h['ga2'] = ga2 + + +# conjugate: +Gc = G.conjugate() +h['Gc'] = Gc + +# Some tail stuff: +tailtempl={} +for sig,g in G: + tailtempl[sig] = copy.deepcopy(g.tail) +h['tt'] = tailtempl + + +# tranpose +g = G['a'] +gt = G['a'].transpose() +gt.data[3,0,1] = 100 +assert g.data[3,1,0] == 100 + +del h diff --git a/test/pytriqs/base/gf_bcast.py b/test/pytriqs/base/gf_bcast.py new file mode 100644 index 00000000..e53ececb --- /dev/null +++ b/test/pytriqs/base/gf_bcast.py @@ -0,0 +1,51 @@ +# Import the Green's functions +from pytriqs.gf.local import GfImFreq, iOmega_n, inverse + +# Create the Matsubara-frequency Green's function and initialize it +g = GfImFreq(indices = [1], beta = 50, n_points = 1000, name = "imp") +g <<= inverse( iOmega_n + 0.5 ) + +import pytriqs.utility.mpi as mpi + +mpi.bcast(g) + + + +#Block + +from pytriqs.gf.local import * +g1 = GfImFreq(indices = ['eg1','eg2'], beta = 50, n_points = 1000, name = "egBlock") +g2 = GfImFreq(indices = ['t2g1','t2g2','t2g3'], beta = 50, n_points = 1000, name = "t2gBlock") +G = BlockGf(name_list = ('eg','t2g'), block_list = (g1,g2), make_copies = False) + + +mpi.bcast(G) + + +#imtime +from pytriqs.gf.local import * + +# A Green's function on the Matsubara axis set to a semicircular +gw = GfImFreq(indices = [1], beta = 50) +gw <<= SemiCircular(half_bandwidth = 1) + +# Create an imaginary-time Green's function and plot it +gt = GfImTime(indices = [1], beta = 50) +gt <<= InverseFourier(gw) + +mpi.bcast(gt) + + +## + +gt2 = GfImTime(indices = [1], beta = 50) + +gt2 = mpi.bcast(gt2) + +print gt2.tail.order_max +print gt2.tail.order_min + +gw2 = GfImFreq(indices = [1], beta = 50) +gw2 <<= Fourier(gt2) + + diff --git a/test/pytriqs/base/gf_init.output.h5 b/test/pytriqs/base/gf_init.output.h5 new file mode 100644 index 0000000000000000000000000000000000000000..e1f2997f04ac4723e2ffc2a66cd41f8e077080a3 GIT binary patch literal 45824 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 literal 0 HcmV?d00001 diff --git a/test/pytriqs/base/gf_init.py b/test/pytriqs/base/gf_init.py new file mode 100644 index 00000000..23cc2b66 --- /dev/null +++ b/test/pytriqs/base/gf_init.py @@ -0,0 +1,50 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +from pytriqs.archive import * +from pytriqs.gf.local import * +import numpy + + + +h=HDFArchive('gf_init.output.h5','w') + +g = GfImFreq(indices = ['eg1','eg2'], beta = 50, n_points = 100, name = "egBlock") +g['eg1','eg1'] <<= SemiCircular(half_bandwidth = 1) +g['eg2','eg2'] <<= SemiCircular(half_bandwidth = 2) + + +h['g1'] = g + +g <<= numpy.array([[1,2],[2,3]]) + +h['g2'] = g + +some_mesh = numpy.arange(-5,5,0.1) +g = GfReFreq(indices = ['eg1','eg2'], window = (-5, 4.9), n_points = 100, name = "egBlock") + +g['eg1','eg1'] <<= iOmega_n - 1.0 +g['eg2','eg2'] <<= iOmega_n + 1.0 + +h['g3'] = g + +del h diff --git a/test/pytriqs/base/h5_example.output.h5 b/test/pytriqs/base/h5_example.output.h5 new file mode 100644 index 0000000000000000000000000000000000000000..5370763d0819ec801eafd4f471ee491f9b2b8647 GIT binary patch literal 12968 zcmeHM&rcIk5PsW&RDNgy6~rG|V>H#%YB1@IH33r-BNa&GMoU2<@dpu1@Wv5uJ$mFw z;)OqfV~-p?a`Vc?#2fDJd|z?5?ruvq!nV64oi}ghE&IOCd^7v{wJ`Z?pm(fS*;gi` zx>VK~^5YoS?qivuPJ0Oh4RRZDHzfm2*?&rnVtx?!_xjDvOid}vllP~@GG%nhD9?#R zb`%1Isi#GI!}Hj+30Xs&K~-f879lH;OOVTuZy?`7GJYASn6@JFf)l^;p;WiZIKxyb z`PN4 z7T;vl+|2V=vkTVC(36Fw@P(vYMJz*U=>6?q!oG(tXa}%vGKexni#-DzD-Z%7{B|KkPpJxn< zqnnk^cyr0W|8EHR^?9{H_aoH%xQP0^)9159DtYrHf9GS(Z{EIb^NJgPua?8a7Ff$` zr_Q|Ahd9&TGWxjM2BQ*5!LP9{oX__G<_YT_`<88-U+f~!Tj^WurM$27EpwmO-Yq+g zi(g%;;(Vio@Z)O2_;ci#|_vRK$4lwe$fgoK-268w-Y#`MPy8*ss&9(Z^LT z)^WwUUmcN1*h5~oQuiCrD<)Sf_4A5<{~kMfTmD~O7a3NE_V0)v`A4+mvr`c8)*&4m zpXUI&w+>Y>&w7-H-mHk8FN|381>Z+mMfdbzBw2?tcZ2Vf3HTf@xW_w>&)w#=lgVf zwT~8ky)|PUSJC59h&3L3Uop^66pJEMxVJ1ti#^s#2eV8TLNrFIv QK!QMmK!Sij0yUWa02l^M@&Et; literal 0 HcmV?d00001 diff --git a/test/pytriqs/base/h5_example.py b/test/pytriqs/base/h5_example.py new file mode 100644 index 00000000..4bc394a9 --- /dev/null +++ b/test/pytriqs/base/h5_example.py @@ -0,0 +1,42 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +from pytriqs.archive import * +from numpy import * + +print "bonjour" + +d = {'a' : 1.0, 'b' : [1,2,3]} + +h = HDFArchive('h5_example.output.h5','w', init = d.items()) + +h['c'] = 100 +h['d'] = array([[1,2,3],[4,5,6]]) +h['e'] = (1,2,3) +h['f'] = { 'a':10, 'b': 20} +h.create_group('g') +g = h['g'] +g['a'] = 98 +g['b'] = (1,2,3) +g['c'] = 200 + +del h diff --git a/test/pytriqs/base/hdf5_io.output.h5 b/test/pytriqs/base/hdf5_io.output.h5 new file mode 100644 index 0000000000000000000000000000000000000000..1a719806a901bca274778f7281f50f5465b33509 GIT binary patch literal 12968 zcmeHMOHUI~6u#5)s64cQ3gRPUjHbF84JO?&CSYn}qymZTXelTpK8Rp~JC=3VrAwA1 zZuki-yJYE-om)00?r>(#_Z4SgW+<5m)6S6e+;h*F;oh(3eCN#Vx5C8p{+`huWnY<$ z>QGr{$d5x@+fQVMI_)J4G{`FCc1i}Cvj3DC!TbQ8@AaFVo}5&cC!bG=+mz8EqdX@P z*;WV?CZ84U4bNfM1;{$$45}()umD+sT!dVLd<*%`qce_~1)Az|;#WSD>QotLm`bG_ z*R&Pc_FzCCw=DK$sz!z^~7%54hLR=;I>l^Uj{n5~<|Pqx_wVHNScLwvDT9{JmNZ6PsWyubn#c zS|8+0Ys={4stQIWl7e4+`ZifF>mK`-D$Xyqk>}0yE%vRUpY zMoE^VZa^~37of8)^Z8u2SEnD2Z>{q)xw;^ukAqsQ;~=aL$lny;vcNA9?S+8158(O1 z9upOClp&d~%uDl(a7CY|Ix1p3`C9sb6wa!Y%8dpC%Y5Cu73|k;*68CZ7wfoU-LDNx zB>>i0fmV*e#jL2J`hKK zAFYBz?n^?bSM3^!3(^ zbzDV{M. +# +################################################################################ + +from pytriqs.archive import * +from numpy import * + + +d = {'a' : 1.0, 'b' : [1,2,3]} + +h = HDFArchive('hdf5_io.output.h5','w', init = d.items()) + +h['c'] = 100 +h['d'] = array([[1,2,3],[4,5,6]]) +h['e'] = (1,2,3) +h['f'] = { 'a':10, 'b': 20} +h.create_group('g') +g = h['g'] +g['a'] = 98 +g['b'] = (1,2,3) +g['c'] = 200 + +del h + +h = HDFArchive('hdf5_io.output.h5') + +dd = h['f'] +dd['a'] = 25 +h['f'] = dd + +del h diff --git a/test/pytriqs/base/pade.output.h5 b/test/pytriqs/base/pade.output.h5 new file mode 100644 index 0000000000000000000000000000000000000000..56e4c361a3ce16526ba1e4337e96c997b568679c GIT binary patch literal 28512 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. +# +################################################################################ + +from numpy import array, arange +from math import pi +from cmath import sqrt, log +from pytriqs.gf.local import GfImFreq, GfReFreq +from pytriqs.gf.local.descriptors import Function + +beta = 100 # Inverse temperature +L = 10 # Number of Matsubara frequencies used in the Pade approximation +eta = 0.01 # Imaginary frequency shift + +## Test Green's functions ## + +# Two Lorentzians +def GLorentz(z): + return 0.7/(z-2.6+0.3*1j) + 0.3/(z+3.4+0.1*1j) + +# Semicircle +def GSC(z): + return 2.0*(z + sqrt(1-z**2)*(log(1-z) - log(-1+z))/pi) + +# A superposition of GLorentz(z) and GSC(z) with equal weights +def G(z): + return 0.5*GLorentz(z) + 0.5*GSC(z) + +# Matsubara GF +gm = GfImFreq(indices = [0], beta = beta, name = "gm") +gm <<= Function(G) +gm.tail.zero() +gm.tail[1] = array([[1.0]]) + +# Analytic continuation of gm +g_pade = GfReFreq(indices = [0], window = (-5.995, 5.995), n_points = 1200, name = "g_pade") +g_pade.set_from_pade(gm, n_points = L, freq_offset = eta) + +from pytriqs.archive import HDFArchive +R = HDFArchive('pade.output.h5','w') +R['g_pade'] = g_pade diff --git a/test/pytriqs/base/test_example.output b/test/pytriqs/base/test_example.output new file mode 100644 index 00000000..1cd909e0 --- /dev/null +++ b/test/pytriqs/base/test_example.output @@ -0,0 +1 @@ +bonjour diff --git a/test/pytriqs/base/test_example.py b/test/pytriqs/base/test_example.py new file mode 100644 index 00000000..51dac652 --- /dev/null +++ b/test/pytriqs/base/test_example.py @@ -0,0 +1,28 @@ + +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2011 by M. Ferrero, 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 . +# +################################################################################ + +import sys + +print "bonjour" + +sys.exit(0) + diff --git a/test/pytriqs/parameters/test.py b/test/pytriqs/parameters/test.py new file mode 100644 index 00000000..4a2d1153 --- /dev/null +++ b/test/pytriqs/parameters/test.py @@ -0,0 +1,39 @@ +import pytriqs.parameters.parameters as P +p = P.Parameters() +p['i'] = 10 +p['d'] = 2.3 +p['s'] = "my string" + +print p + +print p['i'] +print p['d'] +print p['s'] + +d = { 'a' : 10, 'b' : "good", 'c' : -9.2} +p.update(d) +print p + +import numpy as np +a = np.array([[1,2],[3,4]]) +p['A'] = a +p['Ad'] = 2.5*a + +print " p['A'] = ", p['A'] + +p['A'][0,0] *=10 +print " p['A'] = ", p['A'] + +print p + +p2 = P.Parameters() +p2.update2( a = 4, b= "u") + +p['sub'] = p2 +p['sub2'] = { 'r' : 1, 'rrr' : 3} + +print p['sub'] +print p['sub2'] + +print p + diff --git a/test/speed/CMakeLists.txt b/test/speed/CMakeLists.txt new file mode 100644 index 00000000..1dc1f421 --- /dev/null +++ b/test/speed/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB TestList RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) +FOREACH( TestName1 ${TestList} ) + STRING(REPLACE ".cpp" "" TestName ${TestName1}) + add_executable( ${TestName} ${CMAKE_CURRENT_SOURCE_DIR}/${TestName}.cpp ) +ENDFOREACH( TestName1 ${TestList} ) + diff --git a/test/speed/apply_on_tuple_s.cpp b/test/speed/apply_on_tuple_s.cpp new file mode 100644 index 00000000..1b5ef516 --- /dev/null +++ b/test/speed/apply_on_tuple_s.cpp @@ -0,0 +1,58 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#include +#include +#include + +struct fun { double operator()(int i, double x, double y, int k) {return k + i+ x + 2*y;} }; + +const int nl_interne = 1000000; + +struct with_unpack { + double s; + ~with_unpack() { std::cout << s<< std::endl ;} + void operator()() { + //std::function F(f); + fun F; + auto t = std::make_tuple(1,2.3,4.3,8); + for (int u =0; u F(f); + fun F; + for (int u =0; u (50000); + speed_tester (50000); + return 0; +} + + + diff --git a/test/speed/array1.cpp b/test/speed/array1.cpp new file mode 100644 index 00000000..57225345 --- /dev/null +++ b/test/speed/array1.cpp @@ -0,0 +1,171 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include +#include +#include +#include +#include +#include + +using namespace triqs::arrays; +using namespace triqs; +const int N1= 200, N2 = 300; + +struct plain_for_no_ptr_const { + void operator()() { + triqs::arrays::array A (N1,N2,FORTRAN_LAYOUT); + for (int u =0; u<5000; ++u) + for (int j=0; j A (N1,N2,FORTRAN_LAYOUT); + auto V = make_view(A); + for (int u =0; u<5000; ++u) + //make_view(A) = 1867; + V= 1867; + } +}; + +struct plain_for_no_ptr { + void operator()() { + triqs::arrays::matrix A (N1,N2, FORTRAN_LAYOUT); + for (int u =0; u<3000; ++u) + for (int i =0; i::indexmap_type::domain_type::index_value_type index_value_type; +struct F { + triqs::arrays::matrix & a; + F(triqs::arrays::matrix & a_): a(a_){} + //void operator()(value_type & p, index_value_type const & key) const { p=key[0]*10 + key[1] ;} + //void operator()(value_type & p, value_type const & x0, value_type const & x1) const { p=x0*10 + x1 ;} + template void operator()( X0 const & x0, X1 const & x1) const { a(x0,x1) =x0*10 + x1 ;} +}; + +struct with_foreach { + void operator()() { + triqs::arrays::matrix A (N1,N2,FORTRAN_LAYOUT); + // triqs::arrays::indexmaps:: + for (int u =0; u<3000; ++u) foreach(A,F(A)); + // for (int u =0; u<5000; ++u) make_view(A) = 1867; + } +}; + +struct iterators { + void operator()() { + typedef triqs::arrays::matrix MM; + MM A (N1,N2,FORTRAN_LAYOUT); + for (int u =0; u<3000; ++u) + { + for (auto it = A.begin(); it; ++it) { + *it =10*it.indices()[0] + it.indices()[1] ; + } + } + } +}; + +template +struct pointer_generic_form { + void operator()() { + triqs::arrays::matrix A (N1,N2, FORTRAN_LAYOUT); + const int_type s0 = A.indexmap().strides()[0]; + const int_type s1 = A.indexmap().strides()[1]; + + const int_type l0 = A.indexmap().lengths()[0]; + const int_type l1 = A.indexmap().lengths()[1]; + for (int u =0; u<1000; ++u) { + double * restrict p= &(A(0,0)); + //typedef int int_type; + + //assert(s0==1); assert(s1==N1); + //assert(l0==N1); assert(l1==N2); + for (int_type i0 =0; i0 MM; + MM A (N1,N2,FORTRAN_LAYOUT); + for (int u =0; u<5000; ++u) + { + for (MM::iterator it = A.begin(); it; ++it) { + *it = 1876; + } + } + } +}; + + +struct foreach_manual_simple { + void operator()() { + triqs::arrays::array A (N1,N2,FORTRAN_LAYOUT); + mini_vector t; + const int u[2] = {1,0}; //=1, u1=0; + //int u[2]; for (int i=0; i<2; ++i) u[i] = 1-i; + for (int k =0; k<5000; ++k) + for (t[u[0]]=0; t[u[0]] (l); + speed_tester (l); + + std::cout << "----------- Comparing manual loop and foreach for A(i,j) = 10 *i + j--------------------"<< std::endl ; + speed_tester (l); + speed_tester (l); + //speed_tester > (l); + //speed_tester > (l); + + //speed_tester(l); + std::cout << "----------- Comparing manual loop and foreach for A(i,j) = 10 *i + j--------------------"<< std::endl ; + + speed_tester (l); + speed_tester (l); + return 0; +} + diff --git a/test/speed/array2.cpp b/test/speed/array2.cpp new file mode 100644 index 00000000..b0226b5e --- /dev/null +++ b/test/speed/array2.cpp @@ -0,0 +1,140 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include +#include +using namespace std; +using namespace triqs::arrays; +typedef triqs::arrays::matrix MM; +//typedef triqs::arrays::array MM; + +struct bare_loop_with_access { + void operator()() { + + MM A (20,30);//, FORTRAN_LAYOUT); + for (int i =0; i<20; ++i) + for (int j=0; j<30; ++j) + A(i,j) = 10*i+ j; + + MM B(A), C(A), D(A); + + for (int u =0; u<5000; ++u) + for (int i =0; i<20; ++i) + for (int j=0; j<30; ++j) + A(i,j) = B(i,j) + 3* C(i,j) + D(i,j); + } +}; +struct expression_template { + void operator()() { + MM A (20,30); + for (int i =0; i<20; ++i) + for (int j=0; j<30; ++j) + A(i,j) = 10*i+ j; + + MM B(A), C(A), D(A); + + auto ex = B + 3* C+ D; + for (int u =0; u<5000; ++u) + A = B + 3*C + D; + } +}; + +struct bare_loop_with_access_big { + void operator()() { + + MM A (200,300);//, FORTRAN_LAYOUT); + for (int i =0; i<200; ++i) + for (int j=0; j<300; ++j) + A(i,j) = 10*i+ j; + + MM B(A), C(A), D(A); + + //auto ex = A+B; + //typename decltype(ex)::domain_type D; + + for (int u =0; u<500; ++u) + for (int i =0; i<200; ++i) + for (int j=0; j<300; ++j) + A(i,j) = B(i,j) + 3* C(i,j) + D(i,j); + } +}; +struct expression_template_big { + void operator()() { + MM A (200,300); + for (int i =0; i<200; ++i) + for (int j=0; j<300; ++j) + A(i,j) = 10*i+ j; + + MM B(A), C(A), D(A); + + auto ex = B + 3* C+ D; + for (int u =0; u<500; ++u) + A = B + 3*C + D; + } +}; + + +/* +struct pointer_and_expression_template { + MM A,B,C; + + pointer_and_expression_template():A(20,30) {} + double f(size_t i, size_t j) const { return B(i,j) + 3*C(i,j);} + +inline void F(double * restrict p, size_t sh,double const & rhs) { p[sh]=rhs;} +inline void F2(double & r,double const & rhs) { r=rhs;} + + void operator()() { + + for (int i =0; i<20; ++i) + for (int j=0; j<30; ++j) + A(i,j) = 10*i+ j; + + B = A; C=A; + + double * p = &A(0,0); + double * restrict pB = &B(0,0); + + MM const & BB(B); + size_t s1=1, s2 = 20; + boost::tuple t; + for (int u =0; u<5000; ++u) + for (int j=0; j<30; ++j) { + for (int i =0; i<20; ++i ) { + p[i*s1 + j*s2] = (B + 3* C)(i,j); + //F(p,i*s1 + j*s2, (B + 3* C)(i,j)); + //F2(p[i*s1 + j*s2], (B + 3* C)(i,j)); + + } + } + } +}; +*/ + +#include "./speed_tester.hpp" +int main() { + speed_tester (5000); + //speed_tester (5000); + speed_tester (5000); + speed_tester (500); + speed_tester (500); + return 0; +} + diff --git a/test/speed/array_lazy_assign.cpp b/test/speed/array_lazy_assign.cpp new file mode 100644 index 00000000..22c7a5bc --- /dev/null +++ b/test/speed/array_lazy_assign.cpp @@ -0,0 +1,67 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include +#include + +using namespace triqs::arrays; +using namespace triqs; +const int N1= 200, N2 = 300; +namespace tqa=triqs::arrays; namespace tql=triqs::clef; + +struct plain { + void operator()() { + triqs::arrays::array A (N1,N2,FORTRAN_LAYOUT); + for (int u =0; u<5000; ++u) + { + for (int j=0; j i_; tql::placeholder<1> j_; + triqs::arrays::array A (N1,N2,FORTRAN_LAYOUT); + for (int u =0; u<5000; ++u) + A(i_,j_) << i_+ 2*j_; + } +}; + +struct foreach_lambda { + void operator()() { + triqs::arrays::array A (N1,N2,FORTRAN_LAYOUT); + for (int u =0; u<5000; ++u) + //assign_foreach(A, [](size_t i, size_t j) { return i + 2.0*j;}); + assign_foreach(A, [](long i, long j) { return i + 2.0*j;}); + } +}; + +#include "./speed_tester.hpp" +int main() { + const int l = 100; + speed_tester (l); + speed_tester (l); + speed_tester (l); + return 0; +} + diff --git a/test/speed/array_short1.cpp b/test/speed/array_short1.cpp new file mode 100644 index 00000000..474795c5 --- /dev/null +++ b/test/speed/array_short1.cpp @@ -0,0 +1,171 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include +#include +#include +#include +#include +#include + +using namespace triqs::arrays; +using namespace triqs; +const int N1= 10, N2 = 10; + +struct plain_for_no_ptr_const { + void operator()() { + triqs::arrays::array A (N1,N2,FORTRAN_LAYOUT); + for (int u =0; u<2500000; ++u) + for (int j=0; j A (N1,N2,FORTRAN_LAYOUT); + auto V = make_view(A); + for (int u =0; u<2500000; ++u) + //make_view(A) = 1867; + V= 1867; + } +}; + +struct plain_for_no_ptr { + void operator()() { + triqs::arrays::matrix A (N1,N2, FORTRAN_LAYOUT); + for (int u =0; u<2500000; ++u) + for (int i =0; i::indexmap_type::domain_type::index_value_type index_value_type; +struct F { + triqs::arrays::matrix & a; + F(triqs::arrays::matrix & a_): a(a_){} + //void operator()(value_type & p, index_value_type const & key) const { p=key[0]*10 + key[1] ;} + //void operator()(value_type & p, value_type const & x0, value_type const & x1) const { p=x0*10 + x1 ;} + template void operator()( X0 const & x0, X1 const & x1) const { a(x0,x1) =x0*10 + x1 ;} +}; + +struct with_foreach { + void operator()() { + triqs::arrays::matrix A (N1,N2,FORTRAN_LAYOUT); + // triqs::arrays::indexmaps:: + for (int u =0; u<2500000; ++u) foreach(A,F(A)); + // for (int u =0; u<5000; ++u) make_view(A) = 1867; + } +}; + +struct iterators { + void operator()() { + typedef triqs::arrays::matrix MM; + MM A (N1,N2,FORTRAN_LAYOUT); + for (int u =0; u<3000; ++u) + { + for (auto it = A.begin(); it; ++it) { + *it =10*it.indices()[0] + it.indices()[1] ; + } + } + } +}; + +template +struct pointer_generic_form { + void operator()() { + triqs::arrays::matrix A (N1,N2, FORTRAN_LAYOUT); + const int_type s0 = A.indexmap().strides()[0]; + const int_type s1 = A.indexmap().strides()[1]; + + const int_type l0 = A.indexmap().lengths()[0]; + const int_type l1 = A.indexmap().lengths()[1]; + for (int u =0; u<1000; ++u) { + double * restrict p= &(A(0,0)); + //typedef int int_type; + + //assert(s0==1); assert(s1==N1); + //assert(l0==N1); assert(l1==N2); + for (int_type i0 =0; i0 MM; + MM A (N1,N2,FORTRAN_LAYOUT); + for (int u =0; u<5000; ++u) + { + for (MM::iterator it = A.begin(); it; ++it) { + *it = 1876; + } + } + } +}; + + +struct foreach_manual_simple { + void operator()() { + triqs::arrays::array A (N1,N2,FORTRAN_LAYOUT); + mini_vector t; + const int u[2] = {1,0}; //=1, u1=0; + //int u[2]; for (int i=0; i<2; ++i) u[i] = 1-i; + for (int k =0; k<5000; ++k) + for (t[u[0]]=0; t[u[0]] (l); + speed_tester (l); + + std::cout << "----------- Comparing manual loop and foreach for A(i,j) = 10 *i + j--------------------"<< std::endl ; + speed_tester (l); + speed_tester (l); + //speed_tester > (l); + //speed_tester > (l); + + //speed_tester(l); + std::cout << "----------- Comparing manual loop and foreach for A(i,j) = 10 *i + j--------------------"<< std::endl ; + + speed_tester (l); + speed_tester (l); + return 0; +} + diff --git a/test/speed/clef1.cpp b/test/speed/clef1.cpp new file mode 100644 index 00000000..8c659ccd --- /dev/null +++ b/test/speed/clef1.cpp @@ -0,0 +1,63 @@ +#include "./speed_tester.hpp" +#include +#include "./clef_common.hpp" + +double S =0; +struct eval_exp1 { + + void operator()() { + F1 f(2); + double y=2; + //double x=1,y=2; + + auto expr = f(x_) + 2*y_; + + double s=0; + for (int u =0; u<500000; ++u) { s+=eval( expr,x_=u/10000.0, y_=y);} + S += s/10000.0; + //std::cout<< "s =" < f7; + f7(x_) = f(x_) + 2*x_; + + triqs::clef::function f2; + f2(x_) = f(x_) + 2*x_; + + double s=0; + for (int u =0; u<500000; ++u) { s+= f2(u/10000.0);} + S += s/10000.0; + //std::cout<< "s =" < "<< (X) < + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) const { return make_expr_call (std::ref(*this),args...);} + + template< typename... Args> + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) { return make_expr_call (std::ref(*this),args...);} + + template friend void triqs_clef_auto_assign (F1 & x, Fnt f) { x.v++; std::cerr<< " called triqs_clef_auto_assign "<< f(100)< v_ptr; + + F1b(double v_): v_ptr (new double(v_)) {v=v_;} // on purpose, I avoid adding a default constructor ! + F1b (F1b const & x) { v_ptr = x.v_ptr; v = x.v; std::cerr<< " F1 COPY "< + typename triqs::clef::result_of::make_expr_call::type + operator()( Args&&... args ) { return triqs::clef::make_expr_call (*this,args...);} + + template friend void triqs_clef_auto_assign (F1b & x, Fnt f) { (*(x.v_ptr))++; std::cerr<< " called triqs_clef_auto_assign "<< f(100)< + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) const { return make_expr_call (std::ref(*this),args...);} + + template< typename... Args> + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) { return make_expr_call (std::ref(*this),args...);} + + template friend void triqs_clef_auto_assign (F2 const & x, Fnt f) { std::cerr<< " called F2 triqs_clef_auto_assign "<< f(10,20)< x_; +triqs::clef::placeholder <2> y_; +triqs::clef::placeholder <3> z_; +namespace tql= triqs::clef; + diff --git a/test/speed/gemv.cpp b/test/speed/gemv.cpp new file mode 100644 index 00000000..94d436b6 --- /dev/null +++ b/test/speed/gemv.cpp @@ -0,0 +1,67 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include +#include +#include +#include +#include + +using namespace std; +using namespace triqs; +using namespace triqs::arrays; + +struct gemv_via_binder { + + triqs::arrays::matrix A; + typedef triqs::arrays::vector vector_type; + vector_type MC, MB; + static const unsigned int N =200; + + gemv_via_binder(): A(N,N,FORTRAN_LAYOUT), MC(N), MB(N) { + + for (int i =0; i (l); + speed_tester (l); + return 0; +} + diff --git a/test/speed/gf_s.cpp b/test/speed/gf_s.cpp new file mode 100644 index 00000000..7d8470aa --- /dev/null +++ b/test/speed/gf_s.cpp @@ -0,0 +1,69 @@ +//#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK + +#include +#include +#include + +namespace tql= triqs::clef; +namespace tqa= triqs::arrays; +using tqa::range; +using triqs::arrays::make_shape; +using triqs::gf::Fermion; +using triqs::gf::imfreq; +using triqs::gf::imtime; +using triqs::gf::make_gf; + +#define TEST(X) std::cout << BOOST_PP_STRINGIZE((X)) << " ---> "<< (X) < (beta, Fermion, make_shape(2,2),N); + G() =0; + + //auto slv = G.data_getter.slv; + + for (int u =0; u (beta, Fermion, make_shape(2,2),N); + G() =0; + auto V = G.data(); + + for (int u =0; u (5000); + speed_tester (5000); + //speed_tester (5000); + return 0; +} + diff --git a/test/speed/isol_array_foreach_pb.cpp b/test/speed/isol_array_foreach_pb.cpp new file mode 100644 index 00000000..379ba3c1 --- /dev/null +++ b/test/speed/isol_array_foreach_pb.cpp @@ -0,0 +1,24 @@ +#include + +void f (int * p,int i, int j, int val) { p[ i + 200*j] += val;} + +int N1 = 200, N2 = 300; + +int main() { + + int * p = new int [ 200*300]; + int t[2]; + +#ifdef STATIC + const int u[2] = {1,0}; +#else + int u[2]; for (int i=0; i<2; ++i) u[i] = 1-i; +#endif + + for (int k =0; k<500000; ++k) + for (t[u[0]]=0; t[u[0]] "<< (X) < A(L,L), B(L,L),C(L,L); + A() = 0.01; B() = 1.2; C() = 0; + + for (int u =0; u A(L,L), B(L,L),C(L,L); + A() = 0.01; B() = 1.2; C() = 0; + + for (int u =0; u A(L,L), B(L,L),C(L,L); + A() = 0.01; B() = 1.2; C() = 0; + + for (int u =0; u A(L,L), B(L,L),C(L,L); + A() = 0.01; B() = 1.2; C() = 0; + for (int u =0; u A(L,L), B(L,L),C(L,L); + A() = 0.01; B() = 1.2; C() = 0; + for (int u =0; u (5000); + speed_tester (5000); + speed_tester (5000); + speed_tester (5000); + speed_tester (5000); + return 0; +} + diff --git a/test/speed/pool.cpp b/test/speed/pool.cpp new file mode 100644 index 00000000..7e1459bd --- /dev/null +++ b/test/speed/pool.cpp @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +struct A { + double x; int i; +}; + + +typedef std::map< double, A, std::less, boost::fast_pool_allocator< std::pair>> m_t; + +template void test(M & m) { + std::clock_t start = std::clock() ; + for( int i = 0 ; i<100000 ; ++i ) {m.insert(std::make_pair( 10000*std::cos(i),A{0.5,i}));} + std::cout << ( std::clock() - start ) / double(CLOCKS_PER_SEC) << " secs.\n" ; +} + +int main() +{ + m_t m; + test(m); + + std::map m2; + test(m2); + + boost::singleton_pool)>::release_memory(); + + +} diff --git a/test/speed/speed_tester.hpp b/test/speed/speed_tester.hpp new file mode 100644 index 00000000..5a1437a9 --- /dev/null +++ b/test/speed/speed_tester.hpp @@ -0,0 +1,52 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_SPEEDTESTER_H +#define TRIQS_SPEEDTESTER_H +#include +#include "boost/date_time/posix_time/posix_time.hpp" +#include + +/** + * To measure the speed of a function. + */ +template +void speed_tester(size_t n_iter) { + + Obj x; + using namespace boost::posix_time; + using namespace boost::gregorian; + + boost::posix_time::ptime start_time = boost::posix_time::second_clock::local_time(); + + for (size_t u=0; u. + * + ******************************************************************************/ +#include "./common.hpp" +#include + +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include "./src/matrix.hpp" +#include "./src/linalg/matmul.hpp" +#include "./src/linalg/mat_vec_mul.hpp" +#include "./src/linalg/inverse.hpp" +#include "./src/linalg/determinant.hpp" +#include "./src/linalg/a_x_ty.hpp" +#include "./src/blas_lapack/dot.hpp" + +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + triqs::arrays::matrix A(5,5, FORTRAN_LAYOUT); + //triqs::arrays::matrix A(5,5); + typedef triqs::arrays::vector vector_type; + vector_type MC(5), MB(5); + A()= 0; + + for (int i =0; i<5; ++i) + { MC(i) = i;MB(i)=10*(i+1); } + + range R(1,3); + std::cout<<" MC(R) = "<. + * + ******************************************************************************/ +#include "./common.hpp" +#include +#include +#include + +namespace tqa = triqs::arrays; + +int main(int argc, char **argv) { + + tqa::matrix A(3,3, FORTRAN_LAYOUT),B(3,3,FORTRAN_LAYOUT); + + A() = -2; + + for (int i =0; i<3; ++i) + for (int j=0; j<3; ++j) + { A(i,j) = i+2*j+1; B(i,j) = i-j;} + + TEST(A); + TEST(max_element(A)); + TEST(sum(A)); + TEST(B); + TEST(min_element(B)); + TEST(sum(B)); + TEST(make_matrix(A+10*B)); + TEST(max_element(A+10*B)); + + return 0; +} diff --git a/test/triqs/arrays/algorithms.output b/test/triqs/arrays/algorithms.output new file mode 100644 index 00000000..f88e0518 --- /dev/null +++ b/test/triqs/arrays/algorithms.output @@ -0,0 +1,17 @@ +(A) ---> +[[1,3,5] + [2,4,6] + [3,5,7]] +(max_element(A)) ---> 7 +(sum(A)) ---> 36 +(B) ---> +[[0,-1,-2] + [1,0,-1] + [2,1,0]] +(min_element(B)) ---> -2 +(sum(B)) ---> 0 +(make_matrix(A+10*B)) ---> +[[1,-7,-15] + [12,4,-4] + [23,15,7]] +(max_element(A+10*B)) ---> 23 diff --git a/test/triqs/arrays/alias_matmul.cpp b/test/triqs/arrays/alias_matmul.cpp new file mode 100644 index 00000000..236d7ce2 --- /dev/null +++ b/test/triqs/arrays/alias_matmul.cpp @@ -0,0 +1,40 @@ +#include + +using namespace triqs::arrays; + +int main() { + + typedef std::complex dcomplex; + + array A(10,2,2); A() = -1; + + A(4,range(),range()) = 1; + A(5,range(),range()) = 2; + + matrix_view M1 = A(4,range(),range()); + matrix_view M2 = A(5,range(),range()); + + std::cout << M1 << std::endl; + std::cout << M2 << std::endl; + + M1 = M1*M2; + + // aie! M1 is zero! + std::cout << M1 << std::endl; + std::cout << M2 << std::endl; + + matrix B1(2,2), B2(2,2); + B1() = 2; B2() = 3; + + std::cout << "----------" << std::endl; + std::cout << B1 << std::endl; + std::cout << B2 << std::endl; + + //make_cache(B1).view() = B1 * B2; + //B1 = matrix(B1) * B2; + B1 = make_clone(B1) * B2; + + std::cout << B1 << std::endl; + +} + diff --git a/test/triqs/arrays/array_algebra.cpp b/test/triqs/arrays/array_algebra.cpp new file mode 100644 index 00000000..d6816cf8 --- /dev/null +++ b/test/triqs/arrays/array_algebra.cpp @@ -0,0 +1,53 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ + +#include "./common.hpp" +#include "./src/array.hpp" +#include +#include + +using namespace triqs::arrays; + +int main() { + + array A(3), B(3),C; + array D; + + B() = 2; A() = 3; + + + C = A+B; std::cout << A + B<< " = "<< C << std::endl; + C = A*B; std::cout << A * B<< " = "<< C << std::endl; + C = 2*B; std::cout << 2 * B<< " = "<< C << std::endl; + C = B*2; std::cout << 2 * B<< " = "<< C << std::endl; + D = 2.3*B; std::cout << 2.3 * B<< " = "<< D << std::endl; + D = A + B/1.2; std::cout << A + B/1.2<< " = "<< D << std::endl; + + + auto x = A + B + 2*A; + + C = A+2*A+3*A - 2*A+A -A+A+A*3+A+A+A+A+A+A+A+A+A+A+A+A+A; + std::cout << C << std::endl ; + array D2 (2,2); +// auto y = A+D/2 + (D2 + 2*D2);// should not and does not compile +} + + diff --git a/test/triqs/arrays/array_cache2.cpp b/test/triqs/arrays/array_cache2.cpp new file mode 100644 index 00000000..3aa8b815 --- /dev/null +++ b/test/triqs/arrays/array_cache2.cpp @@ -0,0 +1,94 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ + +#include "./common.hpp" + +#include "./src/array.hpp" +#define TRIQS_ARRAYS_CACHE_COPY_VERBOSE +#include "./src/cache.hpp" +#include + +using namespace triqs::arrays; + +void f( array_view & A, long u) { + A(0,0) = u; +} + +int main(int argc, char **argv) { + + + array A (2,3, FORTRAN_LAYOUT); + + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + A(i,j) = 10*i+ j; + + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + std::cout<<"A "< Ac (A); + + std::cout<<"A = "<C = "<< make_const_cache(A).view() <C = "<< make_const_cache(Ac).view() < +#include +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; +namespace mpi=boost::mpi; + +int main(int argc, char* argv[]) +{ + + + mpi::environment env(argc, argv); + mpi::communicator world; + + array A (2,2), B(2,2),C(2,2); + for (int i =0; i<2; ++i) + for (int j=0; j<2; ++j) + { A(i,j) = (1+world.rank())*(10*i+ j);} + + if (world.rank() ==0) std::cout<<" A = "< >(),0); + + int s= world.size(); + if (world.rank() ==0) std::cout<<" C = "<( (s*(s+1)/2) * A) <1)) { + if (world.rank() == 0) { + world.send(1, 0, A); + } else { + world.recv(0, 0, C); + } + world.barrier(); + if (world.rank() ==1) std::cerr<<" node "< + +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + triqs::arrays::vector V; array Va(5); + for (int i =0; i<5; ++i) Va(i) = i+2; + V = Va/2.0; + std::cout<<" V = VA/2 : "<< V<< Va<. + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include "./src/matrix.hpp" +#include + +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + array A (2,3); + //array Af (2,3, "F" ); + array Af (2,3, FORTRAN_LAYOUT ); + //array Af (2,3, memory_layout<2>('F')); + + std::cout <<"Filling Af...."< A = "< B(Af); + + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + std::cout<<"B "< B2; + B2 = A; + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + std::cout<<"B2 "< F = A; + std::cout<<" F = A"< > M1(2,2), M2(2,2); + M1() = 0; + A()=0; + std::cerr<< " is scalar "<< is_scalar_for< int, matrix > >::type::value<< std::endl; + + return 0; +} + diff --git a/test/triqs/arrays/assignment.output b/test/triqs/arrays/assignment.output new file mode 100644 index 00000000..8b05a05d --- /dev/null +++ b/test/triqs/arrays/assignment.output @@ -0,0 +1,27 @@ +Filling Af.... +A= Af --- > A = +[[0,1,2] + [10,11,12]] + i,j = 0 0 A=0 should be 0 + i,j = 0 1 A=1 should be 1 + i,j = 0 2 A=2 should be 2 + i,j = 1 0 A=10 should be 10 + i,j = 1 1 A=11 should be 11 + i,j = 1 2 A=12 should be 12 + copy construction B(A) +B 0 +B 1 +B 2 +B 10 +B 11 +B 12 + B2 = A +B2 0 +B2 1 +B2 2 +B2 10 +B2 11 +B2 12 + F = A +[[0,1,2] + [10,11,12]] diff --git a/test/triqs/arrays/blas_lapack.cpp b/test/triqs/arrays/blas_lapack.cpp new file mode 100644 index 00000000..d1e7dd44 --- /dev/null +++ b/test/triqs/arrays/blas_lapack.cpp @@ -0,0 +1,98 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" + +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include "./src/matrix.hpp" +#include "./src/linalg/matmul.hpp" +#include "./src/linalg/mat_vec_mul.hpp" +#include "./src/linalg/inverse.hpp" +#include "./src/linalg/determinant.hpp" + +#include "./src/blas_lapack/gemm.hpp" +#include "./src/blas_lapack/gemv.hpp" +#include "./src/blas_lapack/ger.hpp" +#include "./src/blas_lapack/axpy.hpp" + +#include +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + typedef std::complex T; + triqs::arrays::vector V(5),V2(5); + + for (int i =0; i<5; ++i) {V(i) = i; V2(i) = -1;} + + std::cout<<"V = "< + +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + array A (2,3); + array B (2,3); + array C(2); + array Af (2,3, FORTRAN_LAYOUT); + + try { + + for (int i =0; i<2; ++i) + for (int j=0; j<4; ++j) + B(i,j) = 10*i+ j; + } + + catch ( triqs::arrays::key_error & e) { + std::cout<< " catching key error in B "<< std::endl ; + std::cerr << e.what() < + +using namespace triqs::arrays; + +int main() { + + typedef std::complex dcomplex; + + array A(10,2,2); A() = 0; + + A(4,range(),range()) = 1; + A(5,range(),range()) = 2; + + matrix_view M1 = A(4,range(),range()); + matrix_view M2 = A(5,range(),range()); + + std::cout << M1 << std::endl; + std::cout << M2 << std::endl; + + std::cout << M1.data_start() << std::endl; + std::cout << M2.data_start() << std::endl; + + + M1 = M2; + //M1 = M1*M2; + + // aie! M1 is zero! + std::cout << M1 << std::endl; + std::cout << M2 << std::endl; + +} + + diff --git a/test/triqs/arrays/bug3.cpp b/test/triqs/arrays/bug3.cpp new file mode 100644 index 00000000..5cb8dd12 --- /dev/null +++ b/test/triqs/arrays/bug3.cpp @@ -0,0 +1,21 @@ + +#include + +using namespace triqs::arrays; + +template +void f(array const & M) { std::cout << M << std::endl ;} + +void g(array const & M) { f(M);} + +int main() { + + array A = {1,2,3}; + + f(A); + + g(2*A); + +} + + diff --git a/test/triqs/arrays/common.hpp b/test/triqs/arrays/common.hpp new file mode 100644 index 00000000..3e6084df --- /dev/null +++ b/test/triqs/arrays/common.hpp @@ -0,0 +1,34 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef COMMON_TEST_ARRAY_H +#define COMMON_TEST_ARRAY_H +#include + +#define TEST(X) std::cout << BOOST_PP_STRINGIZE((X)) << " ---> "<< (X) <. + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include + +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + array A (2,3); + array Af (2,3,FORTRAN_LAYOUT); + + std::cout <<"Filling Af...."< A = "< A = +[[0,1,2] + [10,11,12]] + 2* A= +[[0,2,4] + [20,22,24]] + Af/2 = +[[0,0,1] + [5,5,6]] +2 + B= A/4 = +[[0,0.5,1] + [5,5.5,6]] diff --git a/test/triqs/arrays/create.cpp b/test/triqs/arrays/create.cpp new file mode 100644 index 00000000..59f1c2db --- /dev/null +++ b/test/triqs/arrays/create.cpp @@ -0,0 +1,47 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ + +#include "./common.hpp" +#include "./src/array.hpp" +#include "./src/matrix.hpp" +#include + + +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + array A ; + A.resize(make_shape(3,3)); + + std::cout << A.shape() < M; + M.resize( 3,3); + triqs::arrays::vector V; + V.resize(10); + + + return 0; +} + diff --git a/test/triqs/arrays/create.output b/test/triqs/arrays/create.output new file mode 100644 index 00000000..5a64581d --- /dev/null +++ b/test/triqs/arrays/create.output @@ -0,0 +1 @@ +(3 3) diff --git a/test/triqs/arrays/cross_construct.cpp b/test/triqs/arrays/cross_construct.cpp new file mode 100644 index 00000000..631729ec --- /dev/null +++ b/test/triqs/arrays/cross_construct.cpp @@ -0,0 +1,60 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include "./src/matrix.hpp" +#include "./src/vector.hpp" +#include + +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + array A (2,3); + + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + A(i,j) = 10*i+ j; + + array B(A); + std::cerr << "B = " << B < Vi(3); Vi() = 3; + vector Vd(Vi); + std::cerr << "V = "<< Vd << std::endl; + + std::vector > V(3, A); + + std::vector > W; + for (auto & x : V) W.push_back(x); + + std::vector > W2(W); + long i=1; for (auto & x : V) x *=i++; + + for (auto & x : V) { std::cout <. + * + ******************************************************************************/ +#include "./common.hpp" +#include + +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include "./src/matrix.hpp" +#include "./src/blas_lapack/dot.hpp" +#include "./src/asserts.hpp" + +using namespace triqs::arrays; + +template +void test() { + Vd a(2),aa(2),c(2) ;a()=2.0; c() = 1; + Vi b(2);b()=3; + std::cout << blas::dot(a,b) << std::endl; + + aa = 2*a; + + assert_close( dot(a,b), 12); + assert_close( dot(aa,a), 16); + assert_close( dot(aa,b), 24); + assert_close( dot(aa-a,b), 12); + + std::cerr << dot(aa,a) << std::endl ; + std::cerr << dot(aa,b) << std::endl ; + std::cerr << dot(aa-a, b) << std::endl; + std::cerr<< "---------------------"< , vector >(); + + // does not work for array just because of .size() vs .len(0)... + //test , array >(); + //test , vector >(); + //test , array >(); + +} + + + diff --git a/test/triqs/arrays/eigenelements.cpp b/test/triqs/arrays/eigenelements.cpp new file mode 100644 index 00000000..7f854f2a --- /dev/null +++ b/test/triqs/arrays/eigenelements.cpp @@ -0,0 +1,75 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include "./src/matrix.hpp" +#include "./src/linalg/eigenelements.hpp" + +#include + +using namespace triqs::arrays; +using namespace triqs::arrays::linalg; + +int main(int argc, char **argv) { + + + + matrix A(3,3); + + for (int i =0; i<3; ++i) + for (int j=0; j<=i; ++j) + { A(i,j) = (i>j ? i+2*j : i-j); A(j,i) = A(i,j);} + + std::cerr<<"A = "<, true> w (A()); + w.invoke(); + std::cout<<"A = "< +#include "./src/asserts.hpp" + + +using namespace triqs::arrays; + +template +array_view sum0 (ArrayType const & A) { + array res = A(0,ellipsis()); + for (size_t u =1; u< A.shape()[0]; ++u) res += A(u,ellipsis()); + return res; +} + +int main(int argc, char **argv) { + + + + { + array A(2,3,4) ; + A() = 7; + + std::cerr<< A(0, ellipsis() ) < B(2,3,4,5) ; + B() = 8; + + std::cerr<< B(0, ellipsis(), 3 ) < A(5,2); A() =2; + array B(5,2,3); B() = 3; + std::cerr<< sum0(A) << sum0(B) <. + * + ******************************************************************************/ + +#include "./python_stuff.hpp" +#include "./src/array.hpp" +#include + +using namespace triqs::arrays; +using namespace indexmaps; +using namespace storages; + +#include "./src/array.hpp" +#include "./src/matrix.hpp" +//#include "./src/vector.hpp" +#include + +namespace ExpressionTools { + + /** + * Map any callable object to an array expression, elementwise + */ + namespace details { + template + struct map_impl : TRIQS_MODEL_CONCEPT(ImmutableArray) { + typedef typename Expr::value_type value_type; + typedef typename Expr::domain_type domain_type; + Expr const & a;Obj const & obj;std::string name; + map_impl( Obj const & obj_, Expr const & a_,std::string const & name_):a(a_),obj(obj_),name(name_){} + domain_type domain() const { return a.domain();} + template + value_type operator()(Args const & ... args) const { return obj(a (args...)); } + //value_type operator[] (typename Expr::domain_type::index_value_type const & key) const { return obj(a [key]); } + }; + template + std::ostream & operator<<(std::ostream & out, map_impl const & x){ return out< + details::map_impl map_expr (Obj const & obj, Expr const & x,std::string const & name="Unknown") { + return details::map_impl(obj,x,name); + } + + /** + * Transpose any array expression + */ + namespace details { + + template + struct transpose_impl : TRIQS_MODEL_CONCEPT(ImmutableCuboidArray) { + typedef typename Expr::value_type value_type; + typedef typename Expr::domain_type domain_type; + Expr const & a; + transpose_impl( Expr const & a_):a(a_){} + domain_type domain() const { return domain_type(mini_vector(a.domain().lengths()[1], a.domain().lengths()[0])); } + typedef typename Expr::domain_type::index_value_type K; + template value_type operator()(Args const & ... args) const { return a [ K(args...) ]; } + // value_type operator[] (K const & key) const { return a [ K( key[1], key[0]) ]; } + }; + + template + std::ostream & operator<<(std::ostream & out, transpose_impl const & x){ return out<<"Transpose("< class Transfo> + struct transfo_impl : TRIQS_MODEL_CONCEPT(ImmutableCuboidArray) ,Transfo { //, Tag::expression, Tag::array_algebra_expression_terminal { + Expr const & a; transfo_impl( Expr const & a_):a(a_){} + typedef Transfo T; + typename T::domain_type domain() const { return T::domain(a);} + typename T::value_type operator[] (typename T::domain_type::index_value_type const & key) const { return T::eval(a,key); } + }; + + template class Transfo> + std::ostream & operator<<(std::ostream & out, transfo_impl const & x){ return out<::name()<<"("< details::transpose_impl Transpose (Expr const & x) { return details::transpose_impl(x);} + + template + struct transpose_ { + static_assert( ImmutableArray::value, "transpose_ : the type of the template argument is incorrect, it does not model ImmutableArray"); + // static checks here on Expr + static std::string name() { return "Transpose";} + typedef typename Expr::value_type value_type; + typedef typename Expr::domain_type domain_type; + static domain_type domain(Expr const & a) { return domain_type(mini_vector(a.domain().lengths()[1], a.domain().lengths()[0])); } + static value_type eval (Expr const & a, typename domain_type::index_value_type const & key) { + return a [ typename domain_type::index_value_type ( key[1], key[0]) ]; + } + }; + + +#define TRIQS_ARRAYS_NAME_APPLY_ARRAY_FUNCTION(Name, ArrayFunction)\ + namespace result_of { template struct Name { typedef details::transfo_impl type; }; }\ + template typename result_of::Name::type Name (Expr const & x) { return typename result_of::Name::type (x);}\ + + TRIQS_ARRAYS_NAME_APPLY_ARRAY_FUNCTION (Transpose, transpose_) + + } + + using namespace ExpressionTools; + + int sqr(int x) { return x*x;} + + //DEFINE_ARRAY_FUNCTION1( Transpose, transpose_impl); + + int main(int argc, char **argv) { + + init_python_stuff(argc,argv); + + { + array A(3),B(3),C(3); + array F(3); + for (int i =0; i<3; ++i) { + A(i) = i; + B(i) = 1; + C(i) = 10 *i; + F(i) = 2.5 + i; + } + + std::cout<<" A = "< Af (2,2), Bf(2,2),Cf(2,2); + Af = A; Bf = B; Bf(0,0) = 1; + std::cout<<" Af = "< F( 0.5 * A); + std::cout << " 0.5 * A = "< R(2,3),Rt(3,2); + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + { R(i,j) = 10*i+ j;} + + //std::cout<<" R = "<< 1 + R< +#include +#include + +using namespace triqs::arrays; +namespace tqa = triqs::arrays; +using namespace indexmaps; +using namespace storages; +#include "triqs/utility/typeid_name.hpp" + +int main(int argc, char **argv) { + + + + matrix A (2,2), B(2,2),C(2,2); + for (int i =0; i<2; ++i) + for (int j=0; j<2; ++j) + { A(i,j) = 10*i+ j;B(i,j) = i+ 2*j;} + std::cout<<" A = "< Af (2,2), Bf(2,2),Cf(2,2), id (2,2); + Af = A; Bf = B; Bf(0,0) = 1; Cf()=0; id () = 1; + std::cout<<" Af = "<(Af*Bf)<(Af*(Bf+ Cf))< V(3); V(0) = 1; V(1)= 2; V(2) = 3; + tqa::vector V2(3); V2(0) = 10; V2(1)= 20; V2(2) = 30; + TEST (tqa::make_vector( V2 + 2.0 *V)); + + // test the division by a matrix + TEST(Af); + TEST(1/Af); + TEST(make_matrix(2/Af)); + TEST(make_matrix(Af/2)); + + assert_all_close( make_matrix(Af/Af), id , 1.e-14); + //TEST(make_matrix(Af/Af)); + + // matrix AA(3,3); TEST( tqa::make_matrix(A+ 2* AA)); // exception because of size... + return 0; +} diff --git a/test/triqs/arrays/expr_matrix.output b/test/triqs/arrays/expr_matrix.output new file mode 100644 index 00000000..ac1081c1 --- /dev/null +++ b/test/triqs/arrays/expr_matrix.output @@ -0,0 +1,65 @@ + A = +[[0,1] + [10,11]] + B = +[[0,2] + [1,3]] +( +[[0,1] + [10,11]] + (2 * +[[0,2] + [1,3]])) +------- +Cuboid of rank 2 and dimensions (2 2) +----EVAL --- + C = A + 2*B = +[[0,5] + [12,17]] + C = A+B = +[[0,3] + [11,14]] + Af = +[[0,1] + [10,11]] + Bf = +[[1,2] + [1,3]] +Cuboid of rank 2 and dimensions (2 2) + computing Cf = Af * Bf + Cf = +[[1,3] + [21,53]] + matrix( Af * Bf ) +[[1,3] + [21,53]] + matrix( Af * (Bf + Cf) ) +[[22,56] + [262,666]] +(A) ---> +[[0,1] + [10,11]] +(tqa::make_matrix( 2*A )) ---> +[[0,2] + [20,22]] +(A+ 2) ---> ( +[[0,1] + [10,11]] + 2) +(tqa::make_matrix(A+2 )) ---> +[[2,1] + [10,13]] +(make_matrix(1 + A )) ---> +[[1,1] + [10,12]] +(tqa::make_vector( V2 + 2.0 *V)) ---> [12,24,36] +(Af) ---> +[[0,1] + [10,11]] +(1/Af) ---> (1 * inverse( +[[0,1] + [10,11]])) +(make_matrix(2/Af)) ---> +[[-2.2,0.2] + [2,0]] +(make_matrix(Af/2)) ---> +[[0,0.5] + [5,5.5]] diff --git a/test/triqs/arrays/fill_with_lazy.cpp b/test/triqs/arrays/fill_with_lazy.cpp new file mode 100644 index 00000000..983bbb82 --- /dev/null +++ b/test/triqs/arrays/fill_with_lazy.cpp @@ -0,0 +1,38 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include +namespace tqa=triqs::arrays; namespace tql=triqs::clef; + +int main(int argc, char **argv) { + + + tql::placeholder<0> i_; tql::placeholder<1> j_; + tqa::array A(2,2); + A(i_,j_) << i_ + 2*j_ ; + std::cout << "A = "< B(2,2); + B(i_,j_) << i_ + 2*j_ ; + std::cout << "B = "<. + * + ******************************************************************************/ +#include "./common.hpp" + +#include "./src/matrix.hpp" +#include "./src/functional/fold.hpp" +#include "./src/functional/map.hpp" +#include "./src/algorithms.hpp" +#include + +using namespace triqs::arrays; + +auto Abs = map( boost::function< double (double)> ( static_cast< double (*)(double)> (std::abs)) ); + +int main(int argc, char **argv) { + + + + triqs::arrays::matrix A(3,3,FORTRAN_LAYOUT),B(3,3,FORTRAN_LAYOUT),C(FORTRAN_LAYOUT); + triqs::arrays::matrix Ac(3,3); + + for (int i =0; i<3; ++i) + for (int j=0; j<3; ++j) + { A(i,j) = i+2*j+1; B(i,j) = i-3*j;} + + C = A+ B ; + std::cout<< " A " << A< +#include +#include + +namespace tqa=triqs::arrays; +namespace tql=triqs::clef; +namespace mpl=boost::mpl; + +using tqa::m_index; + +template void test() { + + tql::placeholder<0> i_; + tql::placeholder<1> j_; + tql::placeholder<2> k_; + tql::placeholder<3> l_; + + { // a simple test + tqa::array A(2,2,2,2); + A(i_,j_,k_,l_) << i_ + 10*j_ + 100*k_ + 1000*l_; + TEST(A); + TEST( group_indices(A, m_index<0,1>(), m_index<2,3>())); + } + + { // more complex : inversing a tensor product of matrices... + tqa::matrix B(2,2), C(3,3), Binv, Cinv; + C(i_,j_) << 1.7 /( 3.4*i_ - 2.3*j_ + 1) ; + B(i_,j_) << 2*i_ + j_; + TEST(B); TEST(C); + Binv = inverse(B); + Cinv = inverse(C); + TEST(Binv); TEST(Cinv); + + tqa::array A(2,3,2,3); + A(i_,j_,k_,l_) << B(i_,k_) * C(j_,l_); + + TEST(A); + + tqa::matrix_view M = group_indices (A, m_index<0,1>() , m_index<2,3>() ); + M = inverse(M); + + // checking + tqa::array R(A.shape()); + R(i_,j_,k_,l_) << Binv(i_,k_) * Cinv(j_,l_); + + TEST(R); + TEST(A); + assert_all_close(R,A,5.e-15); + //TEST(make_array(R-A)); + //TEST( max(abs(R-A))); + } + +} + +int main () { + test(); + test(); + + // an alternative syntax ? Why to use the npl here ?? + //auto V = tqa::group_indices( A(i_,j_,k_,l_), m_index(i_,j_), m_index(k_,l_)); + +} diff --git a/test/triqs/arrays/group_indices.output b/test/triqs/arrays/group_indices.output new file mode 100644 index 00000000..c1a989e1 --- /dev/null +++ b/test/triqs/arrays/group_indices.output @@ -0,0 +1,46 @@ +(A) ---> [0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111 ] +(group_indices(A, m_index<0,1>(), m_index<2,3>())) ---> +[[0,100,1000,1100] + [1,101,1001,1101] + [10,110,1010,1110] + [11,111,1011,1111]] +(B) ---> +[[0,1] + [2,3]] +(C) ---> +[[1.7,-1.30769,-0.472222] + [0.386364,0.809524,-8.5] + [0.217949,0.309091,0.53125]] +(Binv) ---> +[[-1.5,0.5] + [1,0]] +(Cinv) ---> +[[0.386252,0.0693273,1.45257] + [-0.259977,0.1271,1.80251] + [-0.00720283,-0.102391,0.237694]] +(A) ---> [0 3.4 0 0.772727 0 0.435897 1.7 5.1 0.386364 1.15909 0.217949 0.653846 0 -2.61538 0 1.61905 0 0.618182 -1.30769 -3.92308 0.809524 2.42857 0.309091 0.927273 0 -0.944444 0 -17 0 1.0625 -0.472222 -1.41667 -8.5 -25.5 0.53125 1.59375 ] +(R) ---> [-0.579378 0.386252 0.389966 -0.259977 0.0108043 -0.00720283 0.193126 0 -0.129989 0 -0.00360142 0 -0.103991 0.0693273 -0.19065 0.1271 0.153587 -0.102391 0.0346636 0 0.06355 0 -0.0511955 0 -2.17886 1.45257 -2.70376 1.80251 -0.35654 0.237694 0.726286 0 0.901255 0 0.118847 0 ] +(A) ---> [-0.579378 0.386252 0.389966 -0.259977 0.0108043 -0.00720283 0.193126 0 -0.129989 0 -0.00360142 0 -0.103991 0.0693273 -0.19065 0.1271 0.153587 -0.102391 0.0346636 0 0.06355 0 -0.0511955 0 -2.17886 1.45257 -2.70376 1.80251 -0.35654 0.237694 0.726286 0 0.901255 0 0.118847 0 ] +(A) ---> [0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111 ] +(group_indices(A, m_index<0,1>(), m_index<2,3>())) ---> +[[0,1000,100,1100] + [10,1010,110,1110] + [1,1001,101,1101] + [11,1011,111,1111]] +(B) ---> +[[0,1] + [2,3]] +(C) ---> +[[1.7,-1.30769,-0.472222] + [0.386364,0.809524,-8.5] + [0.217949,0.309091,0.53125]] +(Binv) ---> +[[-1.5,0.5] + [1,0]] +(Cinv) ---> +[[0.386252,0.0693273,1.45257] + [-0.259977,0.1271,1.80251] + [-0.00720283,-0.102391,0.237694]] +(A) ---> [0 3.4 0 0.772727 0 0.435897 1.7 5.1 0.386364 1.15909 0.217949 0.653846 0 -2.61538 0 1.61905 0 0.618182 -1.30769 -3.92308 0.809524 2.42857 0.309091 0.927273 0 -0.944444 0 -17 0 1.0625 -0.472222 -1.41667 -8.5 -25.5 0.53125 1.59375 ] +(R) ---> [-0.579378 0.386252 0.389966 -0.259977 0.0108043 -0.00720283 0.193126 0 -0.129989 0 -0.00360142 0 -0.103991 0.0693273 -0.19065 0.1271 0.153587 -0.102391 0.0346636 0 0.06355 0 -0.0511955 0 -2.17886 1.45257 -2.70376 1.80251 -0.35654 0.237694 0.726286 0 0.901255 0 0.118847 0 ] +(A) ---> [-0.579378 0.386252 0.389966 -0.259977 0.0108043 -0.00720283 0.193126 0 -0.129989 0 -0.00360142 0 -0.103991 0.0693273 -0.19065 0.1271 0.153587 -0.102391 0.0346636 0 0.06355 0 -0.0511955 0 -2.17886 1.45257 -2.70376 1.80251 -0.35654 0.237694 0.726286 0 0.901255 0 0.118847 0 ] diff --git a/test/triqs/arrays/h5_proxy.cpp.no-built b/test/triqs/arrays/h5_proxy.cpp.no-built new file mode 100644 index 00000000..1daf1de2 --- /dev/null +++ b/test/triqs/arrays/h5_proxy.cpp.no-built @@ -0,0 +1,127 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./python_stuff.hpp" + +#include "./src/h5/array_proxy.hpp" +#include "./src/h5/simple_read_write.hpp" +#include +#include "./src/asserts.hpp" + + +using namespace triqs::arrays; + +template < class T> +void test(std::string filename, T init) { + + h5::H5File file( filename.c_str(), H5F_ACC_TRUNC ); + + const size_t N = 12, d= 2; + + array A(d,d+1), A2(d,d+1); + array A_stack_keep(N,d,d+1), A_stack_compare(N,d,d+1); + + array B(d), B2(d); + array B_stack_keep(N,d), B_stack_compare(N,d); + + + for (size_t u = 0; u M(6,6); + for (int u = 0; u<6; ++u) + for (int v = 0; v<6; ++v) + M(u,v) = 10*u + v; + + h5_write( file, "A", A_stack_keep); + h5_write( file, "A2", A_stack_keep); + h5_write( file, "B", B_stack_keep); + h5_write( file, "M", M); + + h5::array_proxy P( file, "A2"); + P (0,range(), range()) = T(2) *A; + + h5::array_proxy Pnew( file, "Z", make_shape(2,2,3) ); + + file.close(); + + // READING + // + h5::H5File file2 ( filename.c_str(), H5F_ACC_RDONLY ); + + h5::array_proxy AA( file2, "A"); + A_stack_compare = AA; + assert_all_close (A_stack_keep, A_stack_compare, 1.e-13); + std::cerr << "A_stack_compare = "<< A_stack_compare << std::endl; + + array A3(1,1); + for (size_t u = 0; u Pm( file2, "M"); + A3 = Pm; + std::cerr << "M from file with resize = "<< A3 << std::endl; + std::cerr << " ... should be = "<< M << std::endl; + assert_all_close (M, A3, 1.e-15); + + A3 = Pm( range(1,6,2), range (1,6,2)); + array_view V = M( range(1,6,2), range (1,6,2)); + std::cerr << "M from file with resize = "<< A3 << std::endl; + std::cerr << " ... should be = "<< V << std::endl; + assert_all_close (V, A3, 1.e-15); + + std::cerr << " ... done "<< std::endl; + + file2.close(); + +} + +int main(int argc, char **argv) { + + init_python_stuff(argc,argv); + + test("proxy_d.h5", 1.0 ); + test("proxy_c.h5", std::complex(1,2) ); + +} + diff --git a/test/triqs/arrays/h5_stack.cpp b/test/triqs/arrays/h5_stack.cpp new file mode 100644 index 00000000..14edb661 --- /dev/null +++ b/test/triqs/arrays/h5_stack.cpp @@ -0,0 +1,111 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/h5/array_stack.hpp" +#include "./src/h5/simple_read_write.hpp" +#include +#include "./src/asserts.hpp" + +using std::cout; using std::endl; +using namespace triqs::arrays; +using namespace triqs; + +template < class T> +void test(std::string filename, T init) { + + H5::H5File file( filename.c_str(), H5F_ACC_TRUNC ); + h5::group top (file); + + const size_t N = 12, bufsize = 5, d= 2; + + array A(d,d+1); + array A_stack_keep(N,d,d+1), A_stack_compare(N,d,d+1); + + array B(d); + array B_stack_keep(N,d), B_stack_compare(N,d); + + T C; + array C_stack_keep(N), C_stack_compare(N); + + //h5::array_stack SA( file, "A", A.shape() , bufsize); + //h5::array_stack SB( top, "B", B.shape() , bufsize); + //h5::array_stack SC( top, "C", mini_vector() , bufsize); + array_stack< array > SA( top, "A", A.shape() , bufsize); + array_stack< array > SB( top, "B", B.shape() , bufsize); + array_stack< T> SC( top, "C", bufsize); + //h5::array_stack< T> SC( top, "C", mini_vector() , bufsize); // also valid ... + //h5::array_stack< array > SB2( top, "B", bufsize); // does not compile + + for (size_t u = 0; u(1,2) ); + +} + diff --git a/test/triqs/arrays/h5_string_arrays.cpp b/test/triqs/arrays/h5_string_arrays.cpp new file mode 100644 index 00000000..83c78c6d --- /dev/null +++ b/test/triqs/arrays/h5_string_arrays.cpp @@ -0,0 +1,65 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include +#include "./src/h5/simple_read_write.hpp" +#include "./src/asserts.hpp" +#include + +using std::cout; using std::endl; +namespace tqa = triqs::arrays; +namespace h5 = triqs::h5; +using tqa::range; +using namespace tqa; + +int main(int argc, char **argv) { + + // making some data + tqa::array A (2), B; A(0) = "Nice String"; A(1)= "another"; + std::vector V1,V2; + V1.push_back("abcd"); + V1.push_back("de"); + + // writing + H5::H5File file( "test_array_string.h5", H5F_ACC_TRUNC ); + h5::group top(file); + + h5_write(top,"A",A); + h5_write(top,"V",V1); + + // rereading + h5_read (top, "A",B); + h5_read (top, "V",V2); + + //comparing + for (auto &x : V2) std::cerr << x << std::endl ; + assert_is_true( V1 == V2); + assert_is_true( A == B); + + std::cerr << A << std::endl ; + std::cerr << B << std::endl ; + + + return 0; +} + + diff --git a/test/triqs/arrays/h5_vector_array.cpp b/test/triqs/arrays/h5_vector_array.cpp new file mode 100644 index 00000000..bccc4c5d --- /dev/null +++ b/test/triqs/arrays/h5_vector_array.cpp @@ -0,0 +1,64 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include +#include "./src/asserts.hpp" +#include + +using std::cout; using std::endl; +namespace tqa = triqs::arrays; +namespace h5 = triqs::h5; +using tqa::range; +using namespace tqa; + +int main(int argc, char **argv) { + +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + try { + + std::vector v {1.1,2.2,3.3,4.5}; + std::vector > vc {1.1,2.2,3.3,4.5}; + + std::vector v2; + std::vector > vc2; + + { + H5::H5File file1( "test_std_vector.h5", H5F_ACC_TRUNC ); + h5::group top(file1); + h5_write(top,"vdouble",v); + h5_write(top,"vcomplex",vc); + } + + H5::H5File file2( "test_std_vector.h5", H5F_ACC_RDONLY ); + h5::group top2(file2); + + h5_read(top2,"vdouble",v2); + h5_read(top2,"vcomplex",vc2); + + for (int i = 0; i . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include +#include "./src/h5/simple_read_write.hpp" + +using std::cout; using std::endl; +namespace tqa = triqs::arrays; +namespace h5 = triqs::h5; +using tqa::range; + +template +std::ostream & operator << (std::ostream & out, std::vector const & v) { +for (size_t i =0; i A (2,3),B,vc; + tqa::array D (2,3), D2; + + tqa::array Af(FORTRAN_LAYOUT),Bf(FORTRAN_LAYOUT),vf(FORTRAN_LAYOUT); + + tqa::array,1> C(5), C2; + std::complex z(1,2); + + for (int i =0; i<5; ++i) { + C(i) = std::complex(i,i); + } + + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + { + A(i,j) = 10*i+ j; + D (i,j) = A(i,j) / 10.0; + } + + Af = A; + + std::cout<<" A= "< E; h5_read (top, "A",E); std::cout<< "E = "<< E< 2.3 +(s2) ---> a nice chain diff --git a/test/triqs/arrays/init_check.cpp b/test/triqs/arrays/init_check.cpp new file mode 100644 index 00000000..600de28d --- /dev/null +++ b/test/triqs/arrays/init_check.cpp @@ -0,0 +1,43 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include "./src/matrix.hpp" +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + array A (2,2); + array B (2,2); + array ,2, NanInit > C (2,2); + + std::cerr << A << std::endl ; + std::cerr << B << std::endl ; + std::cerr << C << std::endl ; + + return 0; +} + diff --git a/test/triqs/arrays/init_check.output b/test/triqs/arrays/init_check.output new file mode 100644 index 00000000..e69de29b diff --git a/test/triqs/arrays/init_list.cpp b/test/triqs/arrays/init_list.cpp new file mode 100644 index 00000000..24539e75 --- /dev/null +++ b/test/triqs/arrays/init_list.cpp @@ -0,0 +1,52 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include + +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include "./src/matrix.hpp" + +using namespace triqs::arrays; + +int main(int argc, char **argv) { + +// only for icc 13.x +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + array A = {1,2,3,4}; + std::cout << A<< A.shape()< B = {{1,2},{3,4}, {5,6}}; + std::cout << B<< B.shape()< V = {1.1,2.0,3.2,4.0}; + std::cout << V<< V.shape()< M = {{1,2},{3,4}, {5,6}}; + std::cout << M<< M.shape()<. + * + ******************************************************************************/ +#include "./common.hpp" + +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include "./src/matrix.hpp" +#include "./src/linalg/det_and_inverse.hpp" +#include "./src/linalg/matmul.hpp" +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; +//using linalg::inverse; +//using linalg::inverse_and_compute_det; +//using linalg::determinant; + +template +matrix_view +eval_as_matrix( Expr const & e) { return matrix(e);} + +int main(int argc, char **argv) { + + + + try { + + triqs::arrays::matrix W(3,3,FORTRAN_LAYOUT),Wi(3,3,FORTRAN_LAYOUT),Wkeep(3,3,FORTRAN_LAYOUT),A(FORTRAN_LAYOUT); + for (int i =0; i<3; ++i) + for (int j=0; j<3; ++j) + W(i,j) = (i>j ? i+2.5*j : i*0.8-j); + +/*triqs::arrays::vector ipiv22(3);ipiv22()=0; + lapack::getrf(W, ipiv22); + std::cout<<"getrf W = "< (inverse(W))< ipiv2(3);ipiv2()=0; + lapack::getrf(Wi, ipiv2); + std::cerr<<"getrf W = "<. + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + array A (2,3); + + // first print the index generator + for (array::indexmap_type::domain_type::generator it = A.indexmap().domain().begin(); it; ++it) + std::cout<<" "<<*it<::indexmap_type::domain_type::gal_generator + it(A.indexmap().domain()); it; ++it) + std::cout<<" "<<*it<::indexmap_type::domain_type::gal_generator < permutations::permutation(1,0) > + it(A.indexmap().domain()); it; ++it) + std::cout<<" "<<*it<::iterator it = A.begin(); it; ++it) { + *it =it.indices()[0] + 10 *it.indices()[1] ; + std::cout<<" i,j = "<::iterator it = A.begin(); it; ++it,++u) { + *it =u; + std::cout<<" i,j = "< Af (2,3); + + for (auto it = Af.begin(); it; ++it) { + *it =it.indices()[0] + 10 *it.indices()[1] ; + std::cout<<" i,j = "< +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; +using namespace triqs::arrays; + +// to be extended to more complex case +// calling lapack on view to test cache securities.... +// +int main() { + + array,3> TMPALL (2,2,5); TMPALL()=-1; + matrix_view > TMP ( TMPALL (range(), range(), 2)); + matrix > M1(2,2), Res(2,2); + M1()=0; M1(0,0) = 2; M1(1,1) = 3.2; + Res()=0; Res(0,0) = 8; Res(1,1) = 16.64; + TMP() =0; + TMP() = M1*( M1 + 2.0 ); + assert_all_close(TMP(), Res, 1.e-10); +} diff --git a/test/triqs/arrays/lexico_vector.cpp b/test/triqs/arrays/lexico_vector.cpp new file mode 100644 index 00000000..3859e19c --- /dev/null +++ b/test/triqs/arrays/lexico_vector.cpp @@ -0,0 +1,61 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include +#include + +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include "./src/matrix.hpp" +#include "./src/asserts.hpp" + +using namespace triqs::arrays; + +int main(int argc, char **argv) { + +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + + { + vector a = { 1,3,2}, b= {2,3,1}; + assert_is_true (std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())); + assert_is_false (std::lexicographical_compare(b.begin(), b.end(), a.begin(), a.end())); + assert_is_true (a a = {1,3,2}, b= {1,2,10}; + assert_is_false (std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end())); + assert_is_true (std::lexicographical_compare(b.begin(), b.end(), a.begin(), a.end())); + assert_is_true (b a = {1,3,2}, b=a; + assert_is_false (a. + * + ******************************************************************************/ +#include "./common.hpp" +#include +#include +#include + +namespace tqa = triqs::arrays; +namespace tql = triqs::clef; +using tqa::range; + +int main(int argc, char **argv) { + + + tql::placeholder<0> i_; tql::placeholder<1> j_; + + TEST( make_immutable_array( i_ + j_, i_= range(0,2), j_=range(0,2))); + + TEST( (tqa::array(tqa::make_immutable_array( i_ + j_, i_= range(0,2), j_=range(0,2))))); + + return 0; +} diff --git a/test/triqs/arrays/make_immutables.output b/test/triqs/arrays/make_immutables.output new file mode 100644 index 00000000..45297e0a --- /dev/null +++ b/test/triqs/arrays/make_immutables.output @@ -0,0 +1,5 @@ +(make_immutable_array( i_ + j_, i_= range(0,2), j_=range(0,2))) ---> immutable_array on domain : Cuboid of rank 2 and dimensions (3 3) +((tqa::array(tqa::make_immutable_array( i_ + j_, i_= range(0,2), j_=range(0,2))))) ---> +[[0,1,2] + [1,2,3] + [2,3,4]] diff --git a/test/triqs/arrays/map_expression.cpp b/test/triqs/arrays/map_expression.cpp new file mode 100644 index 00000000..c65a2e10 --- /dev/null +++ b/test/triqs/arrays/map_expression.cpp @@ -0,0 +1,57 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/functional/map.hpp" +#include "./src/matrix.hpp" +#include +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +template T mmax(T const & x, T const & y) { return std::max(x,y);} + +int main(int argc, char **argv) { + + + + triqs::arrays::matrix A(3,3, FORTRAN_LAYOUT),B(3,3, FORTRAN_LAYOUT); + A() = -2; + + for (int i =0; i<3; ++i) + for (int j=0; j<3; ++j) + { A(i,j) = i+2*j+1; B(i,j) = i-j;} + + auto Abs = map( std::function< double (double)> ( static_cast< double (*)(double)> (std::abs)) ); + auto Max = map2( std::function(mmax) ); + + auto sqr = map( [](double x){return x*x;}); + + std::cout<< " A " << A<. + * + ******************************************************************************/ +#include "./common.hpp" + +#include "./src/mapped_functions.hpp" +#include "./src/matrix.hpp" +#include + +namespace tqa = triqs::arrays; + +template void test( T val=1 ) { + tqa::matrix A(3,3, FORTRAN_LAYOUT),B(3,3, FORTRAN_LAYOUT); + + for (int i =0; i<3; ++i) + for (int j=0; j<3; ++j) + { A(i,j) = (i+2*j+1); B(i,j) = (i-j);} + + A *=val; B*=val; + T s = 10; + TEST(A); + TEST(make_matrix(pow(A,2))); + TEST(make_matrix(cosh(A))); + TEST(B); + TEST(abs(B)); + TEST(make_matrix(abs(B))); + TEST(make_matrix(abs(B+B))); + TEST(make_matrix(A+ s*B)); + TEST(make_matrix(abs(A+s*B))); + + TEST(make_matrix(real(B))); + TEST(make_matrix(imag(B))); + +} + +int main(int argc, char **argv) { + + + test(); + test(); + test(); + test > (); + test > (std::complex(-2,3)); + + return 0; +} diff --git a/test/triqs/arrays/mapped_functions.output b/test/triqs/arrays/mapped_functions.output new file mode 100644 index 00000000..3fa85a11 --- /dev/null +++ b/test/triqs/arrays/mapped_functions.output @@ -0,0 +1,205 @@ +(A) ---> +[[1,3,5] + [2,4,6] + [3,5,7]] +(make_matrix(pow(A,2))) ---> +[[1,9,25] + [4,16,36] + [9,25,49]] +(make_matrix(cosh(A))) ---> +[[1,10,74] + [3,27,201] + [10,74,548]] +(B) ---> +[[0,-1,-2] + [1,0,-1] + [2,1,0]] +(abs(B)) ---> lazy matrix resulting of a mapping +(make_matrix(abs(B))) ---> +[[0,1,2] + [1,0,1] + [2,1,0]] +(make_matrix(abs(B+B))) ---> +[[0,2,4] + [2,0,2] + [4,2,0]] +(make_matrix(A+ s*B)) ---> +[[1,-7,-15] + [12,4,-4] + [23,15,7]] +(make_matrix(abs(A+s*B))) ---> +[[1,7,15] + [12,4,4] + [23,15,7]] +(make_matrix(real(B))) ---> +[[0,-1,-2] + [1,0,-1] + [2,1,0]] +(make_matrix(imag(B))) ---> +[[0,0,0] + [0,0,0] + [0,0,0]] +(A) ---> +[[1,3,5] + [2,4,6] + [3,5,7]] +(make_matrix(pow(A,2))) ---> +[[1,9,25] + [4,16,36] + [9,25,49]] +(make_matrix(cosh(A))) ---> +[[1,10,74] + [3,27,201] + [10,74,548]] +(B) ---> +[[0,-1,-2] + [1,0,-1] + [2,1,0]] +(abs(B)) ---> lazy matrix resulting of a mapping +(make_matrix(abs(B))) ---> +[[0,1,2] + [1,0,1] + [2,1,0]] +(make_matrix(abs(B+B))) ---> +[[0,2,4] + [2,0,2] + [4,2,0]] +(make_matrix(A+ s*B)) ---> +[[1,-7,-15] + [12,4,-4] + [23,15,7]] +(make_matrix(abs(A+s*B))) ---> +[[1,7,15] + [12,4,4] + [23,15,7]] +(make_matrix(real(B))) ---> +[[0,-1,-2] + [1,0,-1] + [2,1,0]] +(make_matrix(imag(B))) ---> +[[0,0,0] + [0,0,0] + [0,0,0]] +(A) ---> +[[1,3,5] + [2,4,6] + [3,5,7]] +(make_matrix(pow(A,2))) ---> +[[1,9,25] + [4,16,36] + [9,25,49]] +(make_matrix(cosh(A))) ---> +[[1.54308,10.0677,74.2099] + [3.7622,27.3082,201.716] + [10.0677,74.2099,548.317]] +(B) ---> +[[0,-1,-2] + [1,0,-1] + [2,1,0]] +(abs(B)) ---> lazy matrix resulting of a mapping +(make_matrix(abs(B))) ---> +[[0,1,2] + [1,0,1] + [2,1,0]] +(make_matrix(abs(B+B))) ---> +[[0,2,4] + [2,0,2] + [4,2,0]] +(make_matrix(A+ s*B)) ---> +[[1,-7,-15] + [12,4,-4] + [23,15,7]] +(make_matrix(abs(A+s*B))) ---> +[[1,7,15] + [12,4,4] + [23,15,7]] +(make_matrix(real(B))) ---> +[[0,-1,-2] + [1,0,-1] + [2,1,0]] +(make_matrix(imag(B))) ---> +[[0,0,0] + [0,0,0] + [0,0,0]] +(A) ---> +[[(1,0),(3,0),(5,0)] + [(2,0),(4,0),(6,0)] + [(3,0),(5,0),(7,0)]] +(make_matrix(pow(A,2))) ---> +[[(1,0),(9,0),(25,0)] + [(4,0),(16,0),(36,0)] + [(9,0),(25,0),(49,0)]] +(make_matrix(cosh(A))) ---> +[[(1.54308,0),(10.0677,0),(74.2099,0)] + [(3.7622,0),(27.3082,0),(201.716,0)] + [(10.0677,0),(74.2099,0),(548.317,0)]] +(B) ---> +[[(0,0),(-1,0),(-2,0)] + [(1,0),(0,0),(-1,0)] + [(2,0),(1,0),(0,0)]] +(abs(B)) ---> lazy matrix resulting of a mapping +(make_matrix(abs(B))) ---> +[[0,1,2] + [1,0,1] + [2,1,0]] +(make_matrix(abs(B+B))) ---> +[[0,2,4] + [2,0,2] + [4,2,0]] +(make_matrix(A+ s*B)) ---> +[[(1,0),(-7,0),(-15,0)] + [(12,0),(4,0),(-4,0)] + [(23,0),(15,0),(7,0)]] +(make_matrix(abs(A+s*B))) ---> +[[1,7,15] + [12,4,4] + [23,15,7]] +(make_matrix(real(B))) ---> +[[0,-1,-2] + [1,0,-1] + [2,1,0]] +(make_matrix(imag(B))) ---> +[[0,0,0] + [0,0,0] + [0,0,0]] +(A) ---> +[[(-2,3),(-6,9),(-10,15)] + [(-4,6),(-8,12),(-12,18)] + [(-6,9),(-10,15),(-14,21)]] +(make_matrix(pow(A,2))) ---> +[[(-5,-12),(-45,-108),(-125,-300)] + [(-20,-48),(-80,-192),(-180,-432)] + [(-45,-108),(-125,-300),(-245,-588)]] +(make_matrix(cosh(A))) ---> +[[(-3.72455,-0.511823),(-183.789,-83.1297),(-8366.62,-7161.77)] + [(26.2206,7.62523),(1257.75,799.751),(53734.9,61113.4)] + [(-183.789,-83.1297),(-8366.62,-7161.77),(-329351,-503083)]] +(B) ---> +[[(0,0),(2,-3),(4,-6)] + [(-2,3),(0,0),(2,-3)] + [(-4,6),(-2,3),(0,0)]] +(abs(B)) ---> lazy matrix resulting of a mapping +(make_matrix(abs(B))) ---> +[[0,3.60555,7.2111] + [3.60555,0,3.60555] + [7.2111,3.60555,0]] +(make_matrix(abs(B+B))) ---> +[[0,7.2111,14.4222] + [7.2111,0,7.2111] + [14.4222,7.2111,0]] +(make_matrix(A+ s*B)) ---> +[[(-2,3),(14,-21),(30,-45)] + [(-24,36),(-8,12),(8,-12)] + [(-46,69),(-30,45),(-14,21)]] +(make_matrix(abs(A+s*B))) ---> +[[3.60555,25.2389,54.0833] + [43.2666,14.4222,14.4222] + [82.9277,54.0833,25.2389]] +(make_matrix(real(B))) ---> +[[0,2,4] + [-2,0,2] + [-4,-2,0]] +(make_matrix(imag(B))) ---> +[[0,-3,-6] + [3,0,-3] + [6,3,0]] diff --git a/test/triqs/arrays/mat_stack.cpp b/test/triqs/arrays/mat_stack.cpp new file mode 100644 index 00000000..acd6adb6 --- /dev/null +++ b/test/triqs/arrays/mat_stack.cpp @@ -0,0 +1,89 @@ +#include "./common.hpp" +#include + +using namespace triqs::arrays; +using namespace triqs; + +int main() { + + clef::placeholder<0> i_; + clef::placeholder<1> j_; + clef::placeholder<2> k_; + + { + std::cerr<< "------------- Testing inversion ---------------"<< std::endl; + array A(4,2,2); + + A(k_,i_,j_) << clef::if_else(i_ == j_, i_ + k_+1, 0); // + 2.3* j_; + + matrix_stack_view S (std::move(A)); + + std::cout << S(0) << S(1)<< S(2) << std::endl ; + + S.invert(); + std::cout << S(0) << S(1)<< S(2)<< std::endl ; + } + + { + std::cerr<< "------------- Testing += matrix ---------------"<< std::endl; + array A(4,2,3); + matrix M(2,3); M()= 1; + + A(k_,i_,j_) << i_ + 2*j_ + k_/2.0; + + matrix_stack_view S (std::move(A)); + + std::cout << S(0) << S(1)<< S(2) << std::endl ; + + S += M; + std::cout << S(0) << S(1)<< S(2)<< std::endl ; + } + + { + std::cerr<< "------------- Testing += me---------------"<< std::endl; + array A(4,2,3); + matrix M(2,3); M()= 1; + + A(k_,i_,j_) << i_ + 2*j_ + k_/2.0; + + matrix_stack_view S (std::move(A)); + + std::cout << S(0) << S(1)<< S(2) << std::endl ; + + S += S; + std::cout << S(0) << S(1)<< S(2)<< std::endl ; + } +{ + std::cerr<< "------------- Testing *= 2---------------"<< std::endl; + array A(4,2,3); + matrix M(2,3); M()= 1; + + A(k_,i_,j_) << i_ + 2*j_ + k_/2.0; + + matrix_stack_view S (std::move(A)); + + std::cout << S(0) << S(1)<< S(2) << std::endl ; + + S *= 2; + std::cout << S(0) << S(1)<< S(2)<< std::endl ; + } + + +{ + std::cerr<< "------------- Testing R, L mul ---------------"<< std::endl; + array A(4,3,3); + matrix L(2,3); L()= 2; + matrix R(3,2); R()= 3; + + A(k_,i_,j_) << i_ + 2*j_ + k_/2.0; + + matrix_stack_view S (std::move(A)); + + std::cout << S(0) << S(1)<< S(2) << std::endl ; + + auto Sb = matmul_L_R(L,S,R); + std::cout << Sb(0) << Sb(1)<< Sb(2)<< std::endl ; + std::cout << S(0) << std::endl ; + } + +} diff --git a/test/triqs/arrays/mat_stack.output b/test/triqs/arrays/mat_stack.output new file mode 100644 index 00000000..7c73e94e --- /dev/null +++ b/test/triqs/arrays/mat_stack.output @@ -0,0 +1,77 @@ + +[[1,0] + [0,2]] +[[2,0] + [0,3]] +[[3,0] + [0,4]] + +[[1,0] + [0,0.5]] +[[0.5,0] + [0,0.333333]] +[[0.333333,0] + [0,0.25]] + +[[0,2,4] + [1,3,5]] +[[0.5,2.5,4.5] + [1.5,3.5,5.5]] +[[1,3,5] + [2,4,6]] + +[[1,2,4] + [1,4,5]] +[[1.5,2.5,4.5] + [1.5,4.5,5.5]] +[[2,3,5] + [2,5,6]] + +[[0,2,4] + [1,3,5]] +[[0.5,2.5,4.5] + [1.5,3.5,5.5]] +[[1,3,5] + [2,4,6]] + +[[0,4,8] + [2,6,10]] +[[1,5,9] + [3,7,11]] +[[2,6,10] + [4,8,12]] + +[[0,2,4] + [1,3,5]] +[[0.5,2.5,4.5] + [1.5,3.5,5.5]] +[[1,3,5] + [2,4,6]] + +[[0,4,8] + [2,6,10]] +[[1,5,9] + [3,7,11]] +[[2,6,10] + [4,8,12]] + +[[0,2,4] + [1,3,5] + [2,4,6]] +[[0.5,2.5,4.5] + [1.5,3.5,5.5] + [2.5,4.5,6.5]] +[[1,3,5] + [2,4,6] + [3,5,7]] + +[[0,12] + [6,18]] +[[3,15] + [9,21]] +[[6,18] + [12,24]] + +[[0,2,4] + [1,3,5] + [2,4,6]] diff --git a/test/triqs/arrays/mat_vec_mul.cpp b/test/triqs/arrays/mat_vec_mul.cpp new file mode 100644 index 00000000..922ff88a --- /dev/null +++ b/test/triqs/arrays/mat_vec_mul.cpp @@ -0,0 +1,91 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" + +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include "./src/matrix.hpp" +#include "./src/linalg/inverse.hpp" +#include "./src/linalg/determinant.hpp" +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + triqs::arrays::matrix A(5,5, FORTRAN_LAYOUT); + triqs::arrays::matrix Ac(5,5); + typedef triqs::arrays::vector vector_type; + vector_type MC(5), MB(5); + + for (int i =0; i<5; ++i) + for (int j=0; j<5; ++j) + A(i,j) = i+2*j+1; + + Ac = A; + + MC() = 1;MB()=0; + range R(1,3); + std::cout<< "A = "<< A<< std::endl< Acw = A.transpose(); + + vector_type::view_type MB_w(MB(R)); + + std::cout<<" MC = "< (A(R,R) * A(R,R)) <. + * + ******************************************************************************/ +#include "./common.hpp" + +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include "./src/matrix.hpp" +#include "./src/asserts.hpp" +#include "./src/linalg/inverse.hpp" +#include "./src/linalg/determinant.hpp" +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +int main(int argc, char **argv) { + +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + + matrix Ai= {{ 1,2}, {3,4}}; + matrix A= {{ 1,2}, {3,4}}; + vector Ci, B= {1,1}; + vector Cd, Bd= {1,1}; + + Cd = A*B; + std::cout << Cd<< std::endl ; + + Ci = Ai*B; + std::cout << Ci<< std::endl ; + + assert_all_close(A*B, A*Bd, 1.e-13); + + return 0; + +#endif + +} + + + diff --git a/test/triqs/arrays/matmul.cpp b/test/triqs/arrays/matmul.cpp new file mode 100644 index 00000000..cafbf3fa --- /dev/null +++ b/test/triqs/arrays/matmul.cpp @@ -0,0 +1,90 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/matrix.hpp" +#include "./src/asserts.hpp" +#include "./src/linalg/matmul.hpp" +#include +using namespace triqs::arrays; + +template void test(O1 o1, O2 o2, O3 o3,bool all =false) { + matrix M1(2,3, o1); + matrix M2(3,4, o2); + matrix M3(o3), M4; + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + { M1(i,j) = i +j ; } + for (int i =0; i<3; ++i) + for (int j=0; j<4; ++j) + { M2(i,j) = 1 + i -j ; } + + // The central instruction : note that matmul returns a lazy object + // that has ImmutableArray interface, and defines a specialized version assignment + // As a result this is equivalent to matmul_with_lapack(M1,M2,M3) : there is NO intermediate copy. + M3 = matmul(M1,M2); + + M4 = M3; + M4() = 0; + for (int i =0; i<2; ++i) + for (int k=0; k<3; ++k) + for (int j=0; j<4; ++j) + M4(i,j) += M1(i,k)*M2(k,j); + assert_all_close(M4,M3, 1.e-13,false); + + // recheck gemm_generic + blas::gemm_generic(1, M1, M2, 0, M4); + assert_all_close(M4,M3, 1.e-13,false); + + if (all) { + std::cerr<<"M1 = "< void all_tests() { + test(C_LAYOUT , C_LAYOUT , C_LAYOUT , true); + test(C_LAYOUT , C_LAYOUT , FORTRAN_LAYOUT); + test(C_LAYOUT , FORTRAN_LAYOUT, FORTRAN_LAYOUT); + test(C_LAYOUT , FORTRAN_LAYOUT, C_LAYOUT ); + test(FORTRAN_LAYOUT, FORTRAN_LAYOUT, FORTRAN_LAYOUT); + test(FORTRAN_LAYOUT, C_LAYOUT , FORTRAN_LAYOUT); + test(FORTRAN_LAYOUT, FORTRAN_LAYOUT, C_LAYOUT ); + test(FORTRAN_LAYOUT, C_LAYOUT , C_LAYOUT ); +} + +int main(int argc, char **argv) { + all_tests(); + all_tests>(); + all_tests(); + return 0; +} + + diff --git a/test/triqs/arrays/matmul2.cpp b/test/triqs/arrays/matmul2.cpp new file mode 100644 index 00000000..b16da61e --- /dev/null +++ b/test/triqs/arrays/matmul2.cpp @@ -0,0 +1,52 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/matrix.hpp" +#include "./src/asserts.hpp" +#include "./src/linalg/matmul.hpp" +#include +using namespace triqs::arrays; + +int main(int argc, char **argv) { + +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + + matrix C, A= {{ 1.0,2.3}, {3.1,4.3}}; + matrix B= {{ 1,2}, {3,4}}; + matrix Bd= {{ 1,2}, {3,4}}; + + C = A*B; + std::cout << C<< std::endl ; + + C = A*Bd; + std::cout << C<< std::endl ; + + // check A*B is indeed in double... + //static_assert( std::is_same>::value, "oops"); + + assert_all_close(A*B, A*Bd, 1.e-13); + +#endif + + return 0; +} + + diff --git a/test/triqs/arrays/matrix_transpose.cpp b/test/triqs/arrays/matrix_transpose.cpp new file mode 100644 index 00000000..ca0b2982 --- /dev/null +++ b/test/triqs/arrays/matrix_transpose.cpp @@ -0,0 +1,57 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" + +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include "./src/matrix.hpp" +#include "./src/linalg/matmul.hpp" +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + // testing gemv + triqs::arrays::matrix A(5,5,FORTRAN_LAYOUT); + + for (int i =0; i<5; ++i) + for (int j=0; j<5; ++j) + A(i,j) = i+2*j+1; + + //A *=A;; should be rejected by compiler + + range R(1,3); + + std::cout<< "A = "<< A<< std::endl; + std::cout< Acw = A.transpose(); + +} + + + diff --git a/test/triqs/arrays/matrix_transpose.output b/test/triqs/arrays/matrix_transpose.output new file mode 100644 index 00000000..f1124880 --- /dev/null +++ b/test/triqs/arrays/matrix_transpose.output @@ -0,0 +1,18 @@ +A = +[[1,3,5,7,9] + [2,4,6,8,10] + [3,5,7,9,11] + [4,6,8,10,12] + [5,7,9,11,13]] + +[[1,2,3,4,5] + [3,4,5,6,7] + [5,6,7,8,9] + [7,8,9,10,11] + [9,10,11,12,13]] + +[[4,6] + [5,7]] + +[[4,5] + [6,7]] diff --git a/test/triqs/arrays/move.cpp b/test/triqs/arrays/move.cpp new file mode 100644 index 00000000..9688733e --- /dev/null +++ b/test/triqs/arrays/move.cpp @@ -0,0 +1,47 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include + +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + { + array A (3); A() = 9; + array B( std::move(A)); + std::cout << " A = "<< A << " B = "<< B << std::endl ; + } + + { + array A (3); A() = 9; + array B; + B = std::move(A); + std::cout << " A = "<< A << " B = "<< B << std::endl ; + } + + return 0; +} + diff --git a/test/triqs/arrays/move.output b/test/triqs/arrays/move.output new file mode 100644 index 00000000..999e786c --- /dev/null +++ b/test/triqs/arrays/move.output @@ -0,0 +1,2 @@ + A = empty B = [9,9,9] + A = empty B = [9,9,9] diff --git a/test/triqs/arrays/negate.cpp b/test/triqs/arrays/negate.cpp new file mode 100644 index 00000000..b515a37c --- /dev/null +++ b/test/triqs/arrays/negate.cpp @@ -0,0 +1,76 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include "./src/matrix.hpp" +#include "./src/vector.hpp" +#include "./src/asserts.hpp" +#include "./src/algorithms.hpp" +#include "./src/mapped_functions.hpp" +#include + +using namespace triqs::arrays; +using namespace indexmaps; +using namespace storages; + +int main(int argc, char **argv) { + + + + { + array A(3),B(3); + for (int i =0; i<3; ++i) { + A(i) = 2.6*i; + B(i) = 0; + } + + B = -A; + if ( max_element( abs( A+B)) > 1.e-15) TRIQS_RUNTIME_ERROR <<" array: A+B"; + + } + + { + matrix A(3,3),B(3,3); + for (int i =0; i<3; ++i) + for (int j =0; j<3; ++j) + A(i,j) = 2.6*i + 9*j; + B() = 0; + + B = -A; + std::cerr << A << std::endl ; + std::cerr << B << std::endl; + if ( max_element( abs( A+B)) > 1.e-15) TRIQS_RUNTIME_ERROR <<" matrix : A+B"; + } + + { + triqs::arrays::vector A(3),B(3); + for (int i =0; i<3; ++i) { + A(i) = 2.6*i; + B(i) = 0; + } + + B = -A; + if ( max_element( abs( A+B)) > 1.e-15) TRIQS_RUNTIME_ERROR <<" vector : A+B"; + + } + +} + diff --git a/test/triqs/arrays/non_numeric.cpp b/test/triqs/arrays/non_numeric.cpp new file mode 100644 index 00000000..5ce8dc4e --- /dev/null +++ b/test/triqs/arrays/non_numeric.cpp @@ -0,0 +1,91 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include "./src/matrix.hpp" +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +#include +#include +#include + +namespace BLL=boost::lambda; + +struct S { + double x,y; + int i; + S(): x(0), y(0), i(0) {} + S(double x0, double y0, int i0): x(x0), y(y0), i(i0) {} +}; + +double my_fun(double x, double y) { return x+y;} + +std::ostream & operator << (std::ostream & out, S const & s) { return out<<"("< A(2,2); + + S s0(1,2,3); + int p=0; + for (int i =0; i<2; ++i) + for (int j=0; j<2; ++j,++p) + A(i,j) = S(i,j,p); + + std::cout<<" A "<, 2> AA(2,2); + + array A0(2); + for (int i =0; i<2; ++i) + A0(i) = i; + + AA()=A0; + + std::cout<<" AA "< > F (2,2); + +for (int i =0; i<2; ++i) + for (int j=0; j<2; ++j,++p) + F(i,j) = BLL::bind(&my_fun, BLL::_1, i+j); + +for (int i =0; i<2; ++i) + for (int j=0; j<2; ++j,++p) + std::cout<. + * + ******************************************************************************/ +#include "./common.hpp" +#include +#include + +using namespace triqs::arrays; +using namespace triqs::arrays::permutations; + +template struct P { + static constexpr ull value = F; + friend std::ostream & operator <<( std::ostream & out, P const & s) { + //out << "Permutation of size " << permutations::size(s.value) << " : "<< std::hex; + out << std::hex; + s.print(out, std::integral_constant()); + return out << std::dec; + } + + template void print( std::ostream & out, std::integral_constant) const { out << apply(this->value,c); print(out, std::integral_constant());} + void print( std::ostream & out, std::integral_constant) const {} +}; + +int main(int argc, char **argv) { + + + + constexpr auto p0= permutation(0,1); + constexpr auto p= permutation(0,2,1); + constexpr auto p2= permutation(2,1,0,3); + constexpr auto pc= permutation(1,2,3,0); + + std::cout << P() << std::endl; + std::cout << P() << std::endl; + std::cout << P

    next_t; + static constexpr int n_range_ellipsis= next_t::n_range_ellipsis + is_range; + static constexpr ull_t value = ((is_range ? P+1 : 0) << (4*c)) + next_t::value; + }; + template struct _impl { static constexpr ull_t value = 0; }; + template struct _impl { + static constexpr bool is_range = std::is_base_of::value; + struct r2 { // Intel .... + static constexpr ull_t pn = permutations::apply(mo,c); + static constexpr ull_t value = (ma >> (4*(pn))) & 0xFull; + }; + static const bool r2_nozero = (r2::value!=0); + static constexpr ull_t value = (r2::value!=0 ? ( (r2::value-1) << (4*P) ) : 0)+ _impl::value; + }; + template struct sliced_memory_order { + typedef mask<0,0,Args...> mask_t; + static constexpr ull_t value = mask_t::n_range_ellipsis + 0x10* _impl::value ; + }; +#endif +}}}}}//namespace triqs::arrays +#endif diff --git a/triqs/arrays/indexmaps/permutation.hpp b/triqs/arrays/indexmaps/permutation.hpp new file mode 100644 index 00000000..d1971a45 --- /dev/null +++ b/triqs/arrays/indexmaps/permutation.hpp @@ -0,0 +1,99 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_PERMUTATIONS2_H +#define TRIQS_ARRAYS_PERMUTATIONS2_H +namespace triqs { namespace arrays { namespace permutations { + + typedef unsigned long long ull; + + constexpr ull apply(ull p, ull i) { return (p >> (4*(i+1))) & 0xFull;} + constexpr ull size( ull p) { return p & 0xFull;} + + inline ull permutation_from_array ( const int * const p, int length) { + ull res =0; + for (int i =length-1; i>=0; --i) res = p[i] + 0x10*res; + res= 0x10 * res + length; + return res; + } + + // icc 13.0 has a big bug in constexpr. +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + + // sum_{k=0}^{n-1} k a^k = ( (n-1) * a**(n+1) - n * a**n + a)/(a-1)**2 + // sum_{k=0}^{n-1} k a^(n-k-1) = ( (n-1) - n * a + a**n)/(a-1)**2 + // with a = 16, a**n = 1<<4n + constexpr ull _identity(ull n) { return ( (n-1ull)*(1ull<<(4*(n+1))) +(1ull<<4)- n *(1ull<<(4*n))) /( (1ull<<4) -1ull) /((1ull<<4) -1ull); } + constexpr ull identity(ull n) { return n + 0x10 * _identity(n);} + + constexpr ull _ridentity(ull n) { return ( (n-1ull) - n* (1ull<<4) + (1ull<<(4*n))) /( (1ull<<4) -1ull) /((1ull<<4) -1ull); } + constexpr ull ridentity(ull n) { return n + 0x10 *_ridentity(n); } + + constexpr ull make_perm_impl(){ return 0;} + template constexpr ull make_perm_impl(ull i0, T... x) { return i0 + 0x10 * make_perm_impl(x...); } + template constexpr ull permutation(T... x) { return ull(sizeof...(T)) + 0x10* make_perm_impl(x...); } + + constexpr ull compose_impl(ull p1, ull p2, ull c) { return apply(p2, apply(p1,c)) + 16ull * ( (c+1 0 ? inverse_impl(p,c-1): 0 ); } + constexpr ull inverse(ull p) { return size(p) + 0x10ull*inverse_impl(p,size(p)-1);} + +#else + + constexpr ull _identity(ull n) { return ( (n-1ull)*(1ull<<(4*(n+1))) +(1ull<<4)- n *(1ull<<(4*n))) /( (1ull<<4) -1ull) /((1ull<<4) -1ull); } + constexpr ull identity(ull n) { return n + 0x10 * _identity(n);} + + constexpr ull _ridentity(ull n) { return ( (n-1ull) - n* (1ull<<4) + (1ull<<(4*n))) /( (1ull<<4) -1ull) /((1ull<<4) -1ull); } + constexpr ull ridentity(ull n) { return n + 0x10 *_ridentity(n); } + + // todo generalize with preproc... + constexpr ull make_perm_impl(ull i0) { return i0;} + constexpr ull make_perm_impl(ull i0, ull i1) { return i0 + 0x10ull * i1;} + constexpr ull make_perm_impl(ull i0, ull i1, ull i2) { return i0 + 0x10ull *make_perm_impl(i1,i2);} + constexpr ull make_perm_impl(ull i0, ull i1, ull i2, ull i3) { return i0 + 0x10ull *make_perm_impl(i1,i2,i3);} + constexpr ull make_perm_impl(ull i0, ull i1, ull i2, ull i3, ull i4) { return i0 + 0x10ull * make_perm_impl(i1,i2,i3,i4); } + + constexpr ull permutation(ull i0) { return 1ull + 0x10ull *make_perm_impl(i0);} + constexpr ull permutation(ull i0, ull i1) { return 2ull + 0x10ull *make_perm_impl(i0,i1);} + constexpr ull permutation(ull i0, ull i1, ull i2) { return 3ull + 0x10ull *make_perm_impl(i0,i1,i2);} + constexpr ull permutation(ull i0, ull i1, ull i2, ull i3) { return 4ull + 0x10ull *make_perm_impl(i0,i1,i2,i3);} + constexpr ull permutation(ull i0, ull i1, ull i2, ull i3, ull i4) { return 5ull + 0x10ull *make_perm_impl(i0,i1,i2,i3,i4);} + + template struct _compose { static constexpr ull invoke(ull p1, ull p2) { return apply(p2, apply(p1,c)) + 16ull * _compose::invoke(p1,p2); } }; + template<> struct _compose<15> { static constexpr ull invoke(ull p1, ull p2) { return 0ull; } }; + constexpr ull compose(ull p1, ull p2) { return size(p1) + 0x10ull* (_compose<0>::invoke(p1,p2) & ((1ull<<4*size(p1)) -1ull));} + + template struct _inverse { static constexpr ull invoke(ull p) { return (ull(c) << (4*apply(p,c))) + _inverse::invoke(p);} }; + template<> struct _inverse<15> { static constexpr ull invoke(ull p) { return 0ull; } }; + constexpr ull inverse(ull p) { return size(p) + 0x10ull*( _inverse<0>::invoke(p) - 7ull*15ull + size(p)*(size(p)-1ull)/2ull);} + +#endif + + inline void print( std::ostream & out, ull perm) { + out << "("; + for (int i =0; i< permutations::size(perm); ++i) { out << (i!=0 ? " " : "") << apply(perm,i);} + out << ")"; + } +} +using permutations::permutation; +}} +#endif + diff --git a/triqs/arrays/indexmaps/range.hpp b/triqs/arrays/indexmaps/range.hpp new file mode 100644 index 00000000..bb85a4c7 --- /dev/null +++ b/triqs/arrays/indexmaps/range.hpp @@ -0,0 +1,59 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_RANGE_H +#define TRIQS_ARRAYS_RANGE_H +#include + +namespace triqs { namespace arrays { + + /** + */ + class range { + std::ptrdiff_t first_, last_, step_; + public: + + range():first_(0),last_(-1),step_(1) {} // i.e. all + range(const range& r):first_(r.first_), last_(r.last_), step_(r.step_) {} + range(std::ptrdiff_t first__, std::ptrdiff_t last__, std::ptrdiff_t step__=1):first_(first__), last_(last__), step_(step__) {} + + std::ptrdiff_t first() const { return first_;} + std::ptrdiff_t last () const { return last_;} + std::ptrdiff_t step() const { return step_;} + size_t size() const { std::ptrdiff_t r = (last_ - first_ + 1)/step_; if (r<0) TRIQS_RUNTIME_ERROR <<" range with negative size"; return size_t(r);} + + range operator+(std::ptrdiff_t shift) const { return range(first_ + shift, last_ + shift, step_); } + + friend inline std::ostream& operator<<(std::ostream& os, const range& range) { + os << "range(" << range.first() << "," << range.last() << "," << range.step() << ")"; + return os; + } + }; + + /** + */ + class ellipsis : public range { + public : + ellipsis( std::ptrdiff_t first__, std::ptrdiff_t last__, std::ptrdiff_t step__=1): range(first__, last__, step__) {} + ellipsis() : range() {} + }; + +}}//namespace triqs::arrays +#endif diff --git a/triqs/arrays/linalg/a_x_ty.hpp b/triqs/arrays/linalg/a_x_ty.hpp new file mode 100644 index 00000000..b239bd89 --- /dev/null +++ b/triqs/arrays/linalg/a_x_ty.hpp @@ -0,0 +1,88 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_EXPRESSION_A_X_TY_H +#define TRIQS_ARRAYS_EXPRESSION_A_X_TY_H +#include +#include +#include "../matrix.hpp" +#include "../vector.hpp" +#include "../blas_lapack/ger.hpp" + +namespace triqs { namespace arrays { + + /// + template class a_x_ty_lazy; + + /// + template + a_x_ty_lazy a_x_ty (ScalarType a, VectorType1 const & x, VectorType2 const & y) + { return a_x_ty_lazy(a,x,y); } + + //------------- IMPLEMENTATION ----------------------------------- + + template + class a_x_ty_lazy : TRIQS_MODEL_CONCEPT(ImmutableMatrix) { + typedef typename boost::remove_const::type V1; + typedef typename boost::remove_const::type V2; + static_assert((boost::is_same::value),"Different values : not implemented"); + + public: + typedef BOOST_TYPEOF_TPL( V1() * V2() * ScalarType()) value_type; + typedef indexmaps::cuboid::domain_t<2> domain_type; + typedef typename const_view_type_if_exists_else_type::type X_type; + typedef typename const_view_type_if_exists_else_type::type Y_type; + const ScalarType a; const X_type x; const Y_type y; + + public: + a_x_ty_lazy( ScalarType a_, VectorType1 const & x_, VectorType2 const & y_):a(a_),x(x_),y(y_){} + + domain_type domain() const { return domain_type(mini_vector(x.size(), y.size()));} + size_t dim0() const { return x.size();} + size_t dim1() const { return y.size();} + + template value_type operator() (K0 const & k0, K1 const & k1) const { return a * x(k0) * y(k1); } + + // Optimized implementation of = + template + friend void triqs_arrays_assign_delegation (LHS & lhs, a_x_ty_lazy const & rhs) { + resize_or_check_if_view(lhs,make_shape(rhs.dim0(),rhs.dim1())); + lhs()=0; + blas::ger(rhs.a,rhs.x, rhs.y, lhs); + } + + //Optimized implementation of += + template + friend void triqs_arrays_compound_assign_delegation (LHS & lhs, a_x_ty_lazy const & rhs, mpl::char_<'A'>) { + static_assert((is_matrix_or_view::value), "LHS is not a matrix or a matrix_view"); // check that the target is indeed a matrix. + blas::ger(rhs.a, rhs.x, rhs.y, lhs); + } + + //Optimized implementation of -= + template + friend void triqs_arrays_compound_assign_delegation (LHS & lhs, a_x_ty_lazy const & rhs, mpl::char_<'S'>) { + static_assert((is_matrix_or_view::value), "LHS is not a matrix or a matrix_view"); // check that the target is indeed a matrix. + blas::ger(- rhs.a, rhs.x, rhs.y, lhs); + } + + friend std::ostream & operator<<(std::ostream & out, a_x_ty_lazy const & a){ return out<<"a_x_ty("<. + * + ******************************************************************************/ + +#ifndef TRIQS_LINALG_CROSS_PRODUCT_H +#define TRIQS_LINALG_CROSS_PRODUCT_H +#include + +namespace triqs { namespace arrays { + + /** Cross product. Dim 3 only */ + template + typename VectorType::view_type cross_product (VectorType const & A, VectorType const & B) { + if (A.shape()[0] !=3) TRIQS_RUNTIME_ERROR<<"arrays::linalg::cross_product : works only in d=3 while you gave a vector of size "<::type > r(3); + r(0) = A(1)* B(2) - B(1) * A(2); + r(1) = - A(0)* B(2) + B(0) * A(2); + r(2) = A(0)*B(1) - B(0) * A(1); + return r; + } + +}}//namespace triqs::arrays + +#endif + diff --git a/triqs/arrays/linalg/det_and_inverse.hpp b/triqs/arrays/linalg/det_and_inverse.hpp new file mode 100644 index 00000000..9eda54d7 --- /dev/null +++ b/triqs/arrays/linalg/det_and_inverse.hpp @@ -0,0 +1,187 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_LINALG_DET_INV_H +#define TRIQS_ARRAYS_LINALG_DET_INV_H + +#include +#include +#include +#include "../impl/common.hpp" +#include "../matrix.hpp" +#include "../blas_lapack/getrf.hpp" +#include "../blas_lapack/getri.hpp" + +namespace triqs { namespace arrays { + + /// Error which occurs during the matrix inversion + class matrix_inverse_exception : public triqs::runtime_error {}; + + /** + * Lazy result of inverse(M) where M can be : + * * a matrix, a matrix_view + * * any matrix expression + * The object is lazy, it does not do any computation. + * It can be copied at no cost + * It keeps view of the object A if it a matrix, a copy if it is a formal expression. + */ + template struct inverse_lazy; + + /// + template struct determinant_lazy; + + /// Lazy inversion + template inverse_lazy inverse (A const & a) { return inverse_lazy(a); } + + /// Lazy computation of det + template determinant_lazy determinant (A const & a) { return determinant_lazy(a); } + + // ----------------- implementation ----------------------------------------- + + //worker takes a contiguous view and compute the det and inverse in two steps. + //it is separated in case of multiple use (no reallocation of ipvi, etc...) + //NB a view does not resize, only its elements can be changed + template class det_and_inverse_worker { + static_assert ( (is_matrix_view::value),"class must have be a view"); + typedef typename ViewType::value_type VT; + typedef matrix_view V_type; + ViewType V; + const size_t dim; + triqs::arrays::vector ipiv; + short step; + + public: + det_and_inverse_worker (ViewType const & a): V(a), dim(a.dim0()), ipiv(dim), step(0) { + if (a.dim0()!=a.dim1()) + TRIQS_RUNTIME_ERROR<<"Inverse/Det error : non-square matrix. Dimensions are : ("< V_type fortran_view (MT const &x) { return (x.indexmap().memory_layout_is_c() ? x.transpose() : x);} + + void _step1(V_type & W) { + if (step >0) return; + step=1; + info = lapack::getrf(W, ipiv); + if (info<0) throw matrix_inverse_exception() << "Inverse/Det error : failure of getrf lapack routine "; + } + + void _compute_det(V_type const & W) { + if (step>1) return; + _det =1; + for (size_t i =0; i struct inverse_lazy_impl : TRIQS_MODEL_CONCEPT(ImmutableMatrix) { + typedef typename boost::remove_const::type value_type; + typedef typename A::domain_type domain_type; + typedef typename domain_type::index_value_type index_value_type; + typedef typename const_view_type_if_exists_else_type::type A_type; + const A_type a; + inverse_lazy_impl(A const & a_):a (a_) { + if (a.dim0() != a.dim1()) TRIQS_RUNTIME_ERROR<< "Inverse : matrix is not square but of size "<< a.dim0()<<" x "<< a.dim1(); + } + domain_type domain() const { return a.domain(); } + size_t dim0() const { return a.dim0();} + size_t dim1() const { return a.dim1();} + template value_type operator() (K0 const & k0, K1 const & k1) const { activate(); return _id->M(k0,k1); } + friend std::ostream & operator<<(std::ostream & out,inverse_lazy_impl const&x){return out<<"inverse("< M_type; + typedef matrix_view M_view_type; + M_type M; + internal_data(inverse_lazy_impl const & P):M(P.a){det_and_inverse_worker worker(M); worker.inverse();} + }; + friend struct internal_data; + mutable boost::shared_ptr _id; + void activate() const { if (!_id) _id= boost::make_shared(*this);} + }; + + // The general case + template + struct inverse_lazy >::type > : inverse_lazy_impl { + inverse_lazy(A const & a):inverse_lazy_impl(a) { } + }; + + // for matrix and matrix_views, we have more optimisation possible .... + template + struct inverse_lazy >::type >:inverse_lazy_impl{ + inverse_lazy(A const & a):inverse_lazy_impl(a) { } + + template // Optimized implementation of = + friend void triqs_arrays_assign_delegation (MT & lhs, inverse_lazy const & rhs) { + static_assert(is_matrix_or_view::value, "Internal error"); + if ((lhs.indexmap().memory_indices_layout() !=rhs.a.indexmap().memory_indices_layout())|| + (lhs.data_start() != rhs.a.data_start()) || !(has_contiguous_data(lhs))) { rhs.activate(); lhs = rhs._id->M;} + else {// if M = inverse(M) with the SAME object, then we do not need to copy the data + blas_lapack_tools::reflexive_qcache C(lhs);// a reflexive cache will use a temporary "regrouping" copy if and only if needed + det_and_inverse_worker W(C());// the worker to make the inversion of the lhs... + W.inverse(); // worker is working ... + } + } + friend std::ostream & operator<<(std::ostream & out,inverse_lazy const&x){return out<<"inverse("< struct determinant_lazy { // : { Tag::expression_terminal, Tag::scalar_expression_terminal { + typedef typename A::value_type value_type; + typedef typename const_view_type_if_exists_else_type::type A_type; + A_type a; + determinant_lazy(A const & a_):a(a_){} + operator value_type() { activate(); return _id->det; } + value_type const & operator()() { activate(); return _id->det; } + friend std::ostream & operator<<(std::ostream & out, determinant_lazy const & x){ return out<<"determinant("< worker(M); det = worker.det();} + }; + friend struct internal_data; + mutable boost::shared_ptr _id; + void activate() const { if (!_id) _id= boost::make_shared(*this);} + }; + + }} // namespace triqs::arrays +#endif diff --git a/triqs/arrays/linalg/determinant.hpp b/triqs/arrays/linalg/determinant.hpp new file mode 100644 index 00000000..9eda54d7 --- /dev/null +++ b/triqs/arrays/linalg/determinant.hpp @@ -0,0 +1,187 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_LINALG_DET_INV_H +#define TRIQS_ARRAYS_LINALG_DET_INV_H + +#include +#include +#include +#include "../impl/common.hpp" +#include "../matrix.hpp" +#include "../blas_lapack/getrf.hpp" +#include "../blas_lapack/getri.hpp" + +namespace triqs { namespace arrays { + + /// Error which occurs during the matrix inversion + class matrix_inverse_exception : public triqs::runtime_error {}; + + /** + * Lazy result of inverse(M) where M can be : + * * a matrix, a matrix_view + * * any matrix expression + * The object is lazy, it does not do any computation. + * It can be copied at no cost + * It keeps view of the object A if it a matrix, a copy if it is a formal expression. + */ + template struct inverse_lazy; + + /// + template struct determinant_lazy; + + /// Lazy inversion + template inverse_lazy inverse (A const & a) { return inverse_lazy(a); } + + /// Lazy computation of det + template determinant_lazy determinant (A const & a) { return determinant_lazy(a); } + + // ----------------- implementation ----------------------------------------- + + //worker takes a contiguous view and compute the det and inverse in two steps. + //it is separated in case of multiple use (no reallocation of ipvi, etc...) + //NB a view does not resize, only its elements can be changed + template class det_and_inverse_worker { + static_assert ( (is_matrix_view::value),"class must have be a view"); + typedef typename ViewType::value_type VT; + typedef matrix_view V_type; + ViewType V; + const size_t dim; + triqs::arrays::vector ipiv; + short step; + + public: + det_and_inverse_worker (ViewType const & a): V(a), dim(a.dim0()), ipiv(dim), step(0) { + if (a.dim0()!=a.dim1()) + TRIQS_RUNTIME_ERROR<<"Inverse/Det error : non-square matrix. Dimensions are : ("< V_type fortran_view (MT const &x) { return (x.indexmap().memory_layout_is_c() ? x.transpose() : x);} + + void _step1(V_type & W) { + if (step >0) return; + step=1; + info = lapack::getrf(W, ipiv); + if (info<0) throw matrix_inverse_exception() << "Inverse/Det error : failure of getrf lapack routine "; + } + + void _compute_det(V_type const & W) { + if (step>1) return; + _det =1; + for (size_t i =0; i struct inverse_lazy_impl : TRIQS_MODEL_CONCEPT(ImmutableMatrix) { + typedef typename boost::remove_const::type value_type; + typedef typename A::domain_type domain_type; + typedef typename domain_type::index_value_type index_value_type; + typedef typename const_view_type_if_exists_else_type::type A_type; + const A_type a; + inverse_lazy_impl(A const & a_):a (a_) { + if (a.dim0() != a.dim1()) TRIQS_RUNTIME_ERROR<< "Inverse : matrix is not square but of size "<< a.dim0()<<" x "<< a.dim1(); + } + domain_type domain() const { return a.domain(); } + size_t dim0() const { return a.dim0();} + size_t dim1() const { return a.dim1();} + template value_type operator() (K0 const & k0, K1 const & k1) const { activate(); return _id->M(k0,k1); } + friend std::ostream & operator<<(std::ostream & out,inverse_lazy_impl const&x){return out<<"inverse("< M_type; + typedef matrix_view M_view_type; + M_type M; + internal_data(inverse_lazy_impl const & P):M(P.a){det_and_inverse_worker worker(M); worker.inverse();} + }; + friend struct internal_data; + mutable boost::shared_ptr _id; + void activate() const { if (!_id) _id= boost::make_shared(*this);} + }; + + // The general case + template + struct inverse_lazy >::type > : inverse_lazy_impl { + inverse_lazy(A const & a):inverse_lazy_impl(a) { } + }; + + // for matrix and matrix_views, we have more optimisation possible .... + template + struct inverse_lazy >::type >:inverse_lazy_impl{ + inverse_lazy(A const & a):inverse_lazy_impl(a) { } + + template // Optimized implementation of = + friend void triqs_arrays_assign_delegation (MT & lhs, inverse_lazy const & rhs) { + static_assert(is_matrix_or_view::value, "Internal error"); + if ((lhs.indexmap().memory_indices_layout() !=rhs.a.indexmap().memory_indices_layout())|| + (lhs.data_start() != rhs.a.data_start()) || !(has_contiguous_data(lhs))) { rhs.activate(); lhs = rhs._id->M;} + else {// if M = inverse(M) with the SAME object, then we do not need to copy the data + blas_lapack_tools::reflexive_qcache C(lhs);// a reflexive cache will use a temporary "regrouping" copy if and only if needed + det_and_inverse_worker W(C());// the worker to make the inversion of the lhs... + W.inverse(); // worker is working ... + } + } + friend std::ostream & operator<<(std::ostream & out,inverse_lazy const&x){return out<<"inverse("< struct determinant_lazy { // : { Tag::expression_terminal, Tag::scalar_expression_terminal { + typedef typename A::value_type value_type; + typedef typename const_view_type_if_exists_else_type::type A_type; + A_type a; + determinant_lazy(A const & a_):a(a_){} + operator value_type() { activate(); return _id->det; } + value_type const & operator()() { activate(); return _id->det; } + friend std::ostream & operator<<(std::ostream & out, determinant_lazy const & x){ return out<<"determinant("< worker(M); det = worker.det();} + }; + friend struct internal_data; + mutable boost::shared_ptr _id; + void activate() const { if (!_id) _id= boost::make_shared(*this);} + }; + + }} // namespace triqs::arrays +#endif diff --git a/triqs/arrays/linalg/eigenelements.hpp b/triqs/arrays/linalg/eigenelements.hpp new file mode 100644 index 00000000..64479b23 --- /dev/null +++ b/triqs/arrays/linalg/eigenelements.hpp @@ -0,0 +1,176 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAY_EIGENELEMENTS_H +#define TRIQS_ARRAY_EIGENELEMENTS_H +#include +#include "../matrix.hpp" +#include "../vector.hpp" +#include + +namespace triqs { namespace arrays { namespace linalg { + + /** + * A worker to call lapack routine with the matrices. + * + * Handles both real and complex case. + * + * Usage : + * - construct from a VIEW of a matrix, that MUST be contiguous. + * - call invoke() + * - read the eigenvalues/vectors in values and vectors resp. + * NB : the content of the matrix is destroyed by the computation (it is .vectors() in fact, if Compute_Eigenvectors is true). + * For a one shot usage, prefer eigenelements, eigenvalues functions. + */ + template struct eigenelements_worker; + template struct eigenelements_worker_base; + + template + struct eigenelements_worker_base { + private: + void operator = ( eigenelements_worker_base const & x); + protected: + matrix_view mat; + triqs::arrays::vector ev; + triqs::arrays::vector work; + int dim,info,lwork; + char uplo,compz; + bool has_run; + + eigenelements_worker_base ( matrix_view the_matrix) : mat(the_matrix) { + if (mat.is_empty()) TRIQS_RUNTIME_ERROR<<"eigenelements_worker : the matrix is empty : matrix = "< values() const { + if (!has_run) TRIQS_RUNTIME_ERROR<<"eigenelements_worker has not been invoked !"; + return ev; + } + }; + + //-------------------------------- + + template + struct eigenelements_worker_base : eigenelements_worker_base { + protected: + eigenelements_worker_base ( matrix_view the_matrix) : eigenelements_worker_base (the_matrix) {this->compz='V'; } + public: + matrix vectors() const { + if (!this->has_run) TRIQS_RUNTIME_ERROR<<"eigenelements_worker has not been invoked !"; + return this->mat; + } + }; + + //-------------------------------- + extern "C" { + void TRIQS_FORTRAN_MANGLING(dsyev)(char*,char*, // JOBZ and UPLO + int &, // Matrix Size + double[], // matrix + int&, // LDA of the matrix + double[], // Eigenvalues array + double[], // WORK + int&, // LWORK + int & // INFO + ); + + + void TRIQS_FORTRAN_MANGLING(zheev)(char*,char*, // JOBZ and UPLO + int &, // Matrix Size + std::complex [], // matrix + int&, // LDA of the matrix + double[], // Eigenvalues array + std::complex[], // WORK + int &, // LWORK + double[], // WORK2 + int & // INFO + ); + } + + //-------------------------------- + + template + struct eigenelements_worker< matrix_view ,Compute_Eigenvectors > :eigenelements_worker_base { + eigenelements_worker ( matrix_view the_matrix) : eigenelements_worker_base (the_matrix) {} + void invoke() { + int info; + //fortran_int_t info; + TRIQS_FORTRAN_MANGLING(dsyev) (&this->compz,&this->uplo,this->dim,this->mat.data_start(),this->dim,this->ev.data_start(),this->work.data_start(),this->lwork,info); + if (info) TRIQS_RUNTIME_ERROR<<"eigenelements_worker :error code dsyev : "<mat; + this->has_run = true; + } + }; + + //-------------------------------- + + template + struct eigenelements_worker< matrix_view, Opt>,Compute_Eigenvectors > :eigenelements_worker_base,Opt,Compute_Eigenvectors> { + triqs::arrays::vector work2; + public : + eigenelements_worker ( matrix_view ,Opt> the_matrix) : eigenelements_worker_base,Opt,Compute_Eigenvectors> (the_matrix) { work2.resize(this->lwork);} + void invoke() { + int info; + TRIQS_FORTRAN_MANGLING(zheev) (&this->compz,&this->uplo,this->dim,this->mat.data_start(), + this->dim,this->ev.data_start(),this->work.data_start(),this->lwork,this->work2.data_start(),info); + if (info) TRIQS_RUNTIME_ERROR<<"eigenelements_worker :error code zheev : "<mat; + this->has_run = true; + } + }; + + //-------------------------------- + + /** + * Simple diagonalization call, return all eigenelements. + * Handles both real and complex case. + * @param M : the matrix VIEW : it MUST be contiguous + * @param take_copy : makes a copy of the matrix before calling lapack, so that the original is preserved. + * if false : no copy is made and the content of the matrix M is destroyed (it is equal to vectors()). + * if true : a copy is made, M is preserved, but of course it is slower... + */ + template + std::pair, typename MatrixViewType::non_view_type> eigenelements( MatrixViewType M, bool take_copy =false) { + eigenelements_worker W(take_copy ? make_clone(M)() : M()); W.invoke(); return std::make_pair(W.values(),W.vectors()); + } + + //-------------------------------- + + /** + * Simple diagonalization call, returning only the eigenvalues. + * Handles both real and complex case. + * @param M : the matrix VIEW : it MUST be contiguous + * @param take_copy : makes a copy of the matrix before calling lapack, so that the original is preserved. + * if false : no copy is made and the content of the matrix M is destroyed. + * if true : a copy is made, M is preserved, but of course it is slower... + */ + template + triqs::arrays::vector_view eigenvalues( MatrixViewType M, bool take_copy = false) { + eigenelements_worker W(take_copy ? make_clone(M)() : M()); W.invoke(); return W.values(); + } + +}}} // namespace triqs::arrays::linalg +#endif + diff --git a/triqs/arrays/linalg/inverse.hpp b/triqs/arrays/linalg/inverse.hpp new file mode 100644 index 00000000..9eda54d7 --- /dev/null +++ b/triqs/arrays/linalg/inverse.hpp @@ -0,0 +1,187 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_LINALG_DET_INV_H +#define TRIQS_ARRAYS_LINALG_DET_INV_H + +#include +#include +#include +#include "../impl/common.hpp" +#include "../matrix.hpp" +#include "../blas_lapack/getrf.hpp" +#include "../blas_lapack/getri.hpp" + +namespace triqs { namespace arrays { + + /// Error which occurs during the matrix inversion + class matrix_inverse_exception : public triqs::runtime_error {}; + + /** + * Lazy result of inverse(M) where M can be : + * * a matrix, a matrix_view + * * any matrix expression + * The object is lazy, it does not do any computation. + * It can be copied at no cost + * It keeps view of the object A if it a matrix, a copy if it is a formal expression. + */ + template struct inverse_lazy; + + /// + template struct determinant_lazy; + + /// Lazy inversion + template inverse_lazy inverse (A const & a) { return inverse_lazy(a); } + + /// Lazy computation of det + template determinant_lazy determinant (A const & a) { return determinant_lazy(a); } + + // ----------------- implementation ----------------------------------------- + + //worker takes a contiguous view and compute the det and inverse in two steps. + //it is separated in case of multiple use (no reallocation of ipvi, etc...) + //NB a view does not resize, only its elements can be changed + template class det_and_inverse_worker { + static_assert ( (is_matrix_view::value),"class must have be a view"); + typedef typename ViewType::value_type VT; + typedef matrix_view V_type; + ViewType V; + const size_t dim; + triqs::arrays::vector ipiv; + short step; + + public: + det_and_inverse_worker (ViewType const & a): V(a), dim(a.dim0()), ipiv(dim), step(0) { + if (a.dim0()!=a.dim1()) + TRIQS_RUNTIME_ERROR<<"Inverse/Det error : non-square matrix. Dimensions are : ("< V_type fortran_view (MT const &x) { return (x.indexmap().memory_layout_is_c() ? x.transpose() : x);} + + void _step1(V_type & W) { + if (step >0) return; + step=1; + info = lapack::getrf(W, ipiv); + if (info<0) throw matrix_inverse_exception() << "Inverse/Det error : failure of getrf lapack routine "; + } + + void _compute_det(V_type const & W) { + if (step>1) return; + _det =1; + for (size_t i =0; i struct inverse_lazy_impl : TRIQS_MODEL_CONCEPT(ImmutableMatrix) { + typedef typename boost::remove_const::type value_type; + typedef typename A::domain_type domain_type; + typedef typename domain_type::index_value_type index_value_type; + typedef typename const_view_type_if_exists_else_type::type A_type; + const A_type a; + inverse_lazy_impl(A const & a_):a (a_) { + if (a.dim0() != a.dim1()) TRIQS_RUNTIME_ERROR<< "Inverse : matrix is not square but of size "<< a.dim0()<<" x "<< a.dim1(); + } + domain_type domain() const { return a.domain(); } + size_t dim0() const { return a.dim0();} + size_t dim1() const { return a.dim1();} + template value_type operator() (K0 const & k0, K1 const & k1) const { activate(); return _id->M(k0,k1); } + friend std::ostream & operator<<(std::ostream & out,inverse_lazy_impl const&x){return out<<"inverse("< M_type; + typedef matrix_view M_view_type; + M_type M; + internal_data(inverse_lazy_impl const & P):M(P.a){det_and_inverse_worker worker(M); worker.inverse();} + }; + friend struct internal_data; + mutable boost::shared_ptr _id; + void activate() const { if (!_id) _id= boost::make_shared(*this);} + }; + + // The general case + template + struct inverse_lazy >::type > : inverse_lazy_impl { + inverse_lazy(A const & a):inverse_lazy_impl(a) { } + }; + + // for matrix and matrix_views, we have more optimisation possible .... + template + struct inverse_lazy >::type >:inverse_lazy_impl{ + inverse_lazy(A const & a):inverse_lazy_impl(a) { } + + template // Optimized implementation of = + friend void triqs_arrays_assign_delegation (MT & lhs, inverse_lazy const & rhs) { + static_assert(is_matrix_or_view::value, "Internal error"); + if ((lhs.indexmap().memory_indices_layout() !=rhs.a.indexmap().memory_indices_layout())|| + (lhs.data_start() != rhs.a.data_start()) || !(has_contiguous_data(lhs))) { rhs.activate(); lhs = rhs._id->M;} + else {// if M = inverse(M) with the SAME object, then we do not need to copy the data + blas_lapack_tools::reflexive_qcache C(lhs);// a reflexive cache will use a temporary "regrouping" copy if and only if needed + det_and_inverse_worker W(C());// the worker to make the inversion of the lhs... + W.inverse(); // worker is working ... + } + } + friend std::ostream & operator<<(std::ostream & out,inverse_lazy const&x){return out<<"inverse("< struct determinant_lazy { // : { Tag::expression_terminal, Tag::scalar_expression_terminal { + typedef typename A::value_type value_type; + typedef typename const_view_type_if_exists_else_type::type A_type; + A_type a; + determinant_lazy(A const & a_):a(a_){} + operator value_type() { activate(); return _id->det; } + value_type const & operator()() { activate(); return _id->det; } + friend std::ostream & operator<<(std::ostream & out, determinant_lazy const & x){ return out<<"determinant("< worker(M); det = worker.det();} + }; + friend struct internal_data; + mutable boost::shared_ptr _id; + void activate() const { if (!_id) _id= boost::make_shared(*this);} + }; + + }} // namespace triqs::arrays +#endif diff --git a/triqs/arrays/linalg/mat_vec_mul.hpp b/triqs/arrays/linalg/mat_vec_mul.hpp new file mode 100644 index 00000000..044eb23c --- /dev/null +++ b/triqs/arrays/linalg/mat_vec_mul.hpp @@ -0,0 +1,97 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_EXPRESSION_MAT_VEC_MUL_H +#define TRIQS_ARRAYS_EXPRESSION_MAT_VEC_MUL_H +#include +#include +#include "../matrix.hpp" +#include "../vector.hpp" +#include "../blas_lapack/gemv.hpp" + +namespace triqs { namespace arrays { + + /// + template class mat_vec_mul_lazy; + + /// + template mat_vec_mul_lazy mat_vec_mul (MT const & a, VT const & b) { return mat_vec_mul_lazy(a,b); } + + // ----------------- implementation ----------------------------------------- + + template + class mat_vec_mul_lazy : TRIQS_MODEL_CONCEPT(ImmutableVector) { + + typedef typename MT::value_type V1; + typedef typename VT::value_type V2; + //static_assert((boost::is_same::value),"Different values : not implemented"); + + public: + typedef BOOST_TYPEOF_TPL( V1() * V2()) value_type; + typedef typename VT::domain_type domain_type; + typedef typename const_view_type_if_exists_else_type::type M_type; + typedef typename const_view_type_if_exists_else_type::type V_type; + const M_type M; const V_type V; + + private: + typedef vector vector_type; + + struct internal_data { + vector_type R; + internal_data(mat_vec_mul_lazy const & P): R(P.M.dim0()) { blas::gemv(1,P.M,P.V,0,R); } + }; + friend struct internal_data; + mutable boost::shared_ptr _id; + void activate() const { if (!_id) _id= boost::make_shared(*this);} + + public: + mat_vec_mul_lazy( MT const & M_, VT const & V_):M(M_),V(V_){ + if (M.dim1() != V.size()) TRIQS_RUNTIME_ERROR<< "Matrix product : dimension mismatch in Matrix*Vector "<< M<<" "<< V; + } + + domain_type domain() const { return mini_vector(size());} + //domain_type domain() const { return indexmaps::cuboid::domain_t<1>(mini_vector(size()));} + size_t size() const { return M.dim0();} + + template value_type operator() (KeyType const & key) const { activate(); return _id->R (key); } + + template // Optimized implementation of = + friend void triqs_arrays_assign_delegation (LHS & lhs, mat_vec_mul_lazy const & rhs) { + static_assert((is_vector_or_view::value), "LHS is not a vector or a vector_view"); + resize_or_check_if_view(lhs,make_shape(rhs.size())); + blas::gemv(1,rhs.M,rhs.V,0,lhs); + } + + template + friend void triqs_arrays_compound_assign_delegation (LHS & lhs, mat_vec_mul_lazy const & rhs, mpl::char_<'A'>) { rhs.assign_comp_impl(lhs,1.0);} + template + friend void triqs_arrays_compound_assign_delegation (LHS & lhs, mat_vec_mul_lazy const & rhs, mpl::char_<'S'>) { rhs.assign_comp_impl(lhs,-1.0);} + + private: + template void assign_comp_impl (LHS & lhs, double S) const { + static_assert((is_vector_or_view::value), "LHS is not a vector or a vector_view"); + if (lhs.size() != size()) TRIQS_RUNTIME_ERROR<< "mat_vec_mul : -=/-= operator : size mismatch in M*V "<< lhs.size()<<" vs "<< size(); + blas::gemv(1,M,V,S,lhs); + } + friend std::ostream & operator<<(std::ostream & out, mat_vec_mul_lazy const & x){ return out<<"mat_vec_mul("<. + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_EXPRESSION_MATMUL_H +#define TRIQS_ARRAYS_EXPRESSION_MATMUL_H +#include +#include +#include "../blas_lapack/gemm.hpp" +namespace triqs { namespace arrays { + + /// + template class matmul_lazy; + /// + template matmul_lazy matmul (A const & a, B const & b) { return matmul_lazy(a,b); } + + // ----------------- implementation ----------------------------------------- + + template class matmul_lazy : TRIQS_MODEL_CONCEPT(ImmutableMatrix) { + typedef typename boost::remove_const::type V1; + typedef typename boost::remove_const::type V2; + //static_assert((boost::is_same::value),"Different values : not implemented"); + + public: + typedef BOOST_TYPEOF_TPL( V1() * V2()) value_type; // what is the result of multiplying a V1 by a V2 ? + typedef typename A::domain_type domain_type; + typedef typename const_view_type_if_exists_else_type::type A_type; + typedef typename const_view_type_if_exists_else_type::type B_type; + const A_type a; const B_type b; + + private: + typedef matrix matrix_type; + + struct internal_data { // implementing the pattern LazyPreCompute + matrix_type R; + internal_data(matmul_lazy const & P): R( P.a.dim0(), P.b.dim1()) { blas::gemm(1.0,P.a, P.b, 0.0, R); } + }; + friend struct internal_data; + mutable boost::shared_ptr _id; + void activate() const { if (!_id) _id= boost::make_shared(*this);} + + public: + matmul_lazy( A const & a_, B const & b_):a(a_),b(b_){ + if (a.dim1() != b.dim0()) TRIQS_RUNTIME_ERROR<< "Matrix product : dimension mismatch in A*B "<< a<<" "<< b; + } + + domain_type domain() const { return mini_vector(a.dim0(), b.dim1());} + //domain_type domain() const { return indexmaps::cuboid::domain_t<2>(mini_vector(a.dim0(), b.dim1()));} + size_t dim0() const { return a.dim0();} + size_t dim1() const { return b.dim1();} + + template value_type operator() (K0 const & k0, K1 const & k1) const { activate(); return _id->R(k0,k1); } + + // TO BE REMOVED because of the aliasing question + // Optimized implementation of =, +=, -= + template + friend void triqs_arrays_assign_delegation (LHS & lhs, matmul_lazy const & rhs) { + static_assert((is_matrix_or_view::value), "LHS is not a matrix"); + resize_or_check_if_view(lhs,make_shape(rhs.dim0(),rhs.dim1())); + blas::gemm(1.0,rhs.a, rhs.b, 0.0, lhs); + } + + template + friend void triqs_arrays_compound_assign_delegation (LHS & lhs, matmul_lazy const & rhs, mpl::char_<'A'>) { rhs.assign_comp_impl(lhs,1.0);} + template + friend void triqs_arrays_compound_assign_delegation (LHS & lhs, matmul_lazy const & rhs, mpl::char_<'S'>) { rhs.assign_comp_impl(lhs,-1.0);} + + private: + template void assign_comp_impl (LHS & lhs, double S) const { + static_assert((is_matrix_or_view::value), "LHS is not a matrix"); + if (lhs.dim0() != dim0()) + TRIQS_RUNTIME_ERROR<< "Matmul : +=/-= operator : first dimension mismatch in A*B "<< lhs.dim0()<<" vs "<< dim0(); + if (lhs.dim1() != dim1()) + TRIQS_RUNTIME_ERROR<< "Matmul : +=/-= operator : first dimension mismatch in A*B "<< lhs.dim1()<<" vs "<< dim1(); + blas::gemm(S,a, b, 1.0, lhs); + } + + friend std::ostream & operator<<(std::ostream & out, matmul_lazy const & x){return out<. + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_MAKE_IMMUTABLE_ARRAY_H +#define TRIQS_ARRAYS_MAKE_IMMUTABLE_ARRAY_H +#include "./array.hpp" +namespace triqs { namespace arrays { + + template + class immutable_array_impl : TRIQS_MODEL_CONCEPT(ImmutableCuboidArray) { + template struct _si { typedef size_t type;}; + public : + immutable_array_impl(Expr e_, clef::pair ... p): + f(clef::make_function(e_, clef::placeholder()...)), dom_(make_shape(p.rhs().size()...)) {}; + typedef typename triqs::clef::result_of::make_function... >::type function_type; + typedef typename std::result_of::type...)>::type value_type; + typedef indexmaps::cuboid::domain_t domain_type; + domain_type domain() const { return dom_;} + template value_type operator() (Args const & ... args) const { return f(args...); } + friend std::ostream & operator<<(std::ostream & out, immutable_array_impl const & x){return out<<" immutable_array on domain : "< + immutable_array_impl make_immutable_array( Expr const & expr, clef::pair ... p) { + return immutable_array_impl (expr, p...); + } + +}}//namespace triqs::arrays +#endif + diff --git a/triqs/arrays/mapped_functions.hpp b/triqs/arrays/mapped_functions.hpp new file mode 100644 index 00000000..514b82c2 --- /dev/null +++ b/triqs/arrays/mapped_functions.hpp @@ -0,0 +1,106 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_MAPPED_FNT_H +#define TRIQS_ARRAYS_MAPPED_FNT_H +#include "./functional/map.hpp" +#include +#include + +namespace triqs { namespace arrays { + + using std::abs; + struct abs_wrap { + template struct result; + template struct result { typedef A type;}; + template struct result)> { typedef A type;}; + static const int arity =1; + template typename result::type operator()( A const & a) const { return abs(a);} + }; + + template + typename std::result_of(A)>::type abs(A const & a) { return map(abs_wrap())(a); } + + using std::pow; + template TYPE_ENABLE_IF(T, std::is_integral) pow(T x, int n) { return (n==0 ? 1 : pow(x,n-1)*x);} + struct pow_wrap { + template struct result; + template struct result { typedef A type;}; + static const int arity =1; + int n; pow_wrap(int n_): n(n_){} + template typename result::type operator()( A const & a) const { return pow(a,n);} + }; + + template + typename boost::result_of(A)>::type pow(A const & a, int n) { return map(pow_wrap(n))(a); } + +#define MAP_IT(FNT) \ + using std::FNT;\ + struct FNT##_wrap {\ + template struct result;\ + template struct result { typedef A type;};\ + static const int arity =1;\ + template typename result::type operator()( A const & a) const { return FNT(a);}\ + };\ + template \ + typename boost::result_of(A)>::type FNT(A const & a) { return map(FNT##_wrap())(a); } + +#define TRIQS_ARRAYS_MATH_FNT1 (cos)(sin)(tan)(cosh)(sinh)(tanh)(acos)(asin)(atan)(exp)(log)(sqrt)(floor) + +#define AUX(r, data, elem) MAP_IT(elem) + BOOST_PP_SEQ_FOR_EACH(AUX , nil , TRIQS_ARRAYS_MATH_FNT1); +#undef AUX +#undef MAP_IT + + + using std::real; + struct real_wrap { + template struct result; + template struct result { typedef A type;}; + template struct result)> { typedef A type;}; + static const int arity =1; + // template auto operator()( A const & a) const -> decltype(real(a)) { return real(a);} + template typename result::type operator()( A const & a) const { return real(a);} + }; + + template + //auto real(A const & a) -> decltype( map(real_wrap())(a)) { return map(real_wrap())(a); } + // typename std::result_of::type real(A const & a) { return map(real_wrap())(a); } + typename boost::result_of(A)>::type real(A const & a) { return map(real_wrap())(a); } + + using std::imag; + struct imag_wrap { + template struct result; + template struct result { typedef A type;}; + template struct result)> { typedef A type;}; + static const int arity =1; + // template auto operator()( A const & a) const -> decltype(imag(a)) { return imag(a);} + template typename result::type operator()( A const & a) const { return imag(a);} + }; + + template + //auto imag(A const & a) -> decltype( map(imag_wrap())(a)) { return map(imag_wrap())(a); } + // typename std::result_of::type imag(A const & a) { return map(imag_wrap())(a); } + typename boost::result_of(A)>::type imag(A const & a) { return map(imag_wrap())(a); } + + +}}//namespace triqs::arrays +#endif + diff --git a/triqs/arrays/matrix.hpp b/triqs/arrays/matrix.hpp new file mode 100644 index 00000000..94afee73 --- /dev/null +++ b/triqs/arrays/matrix.hpp @@ -0,0 +1,204 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_MATRIX_H +#define TRIQS_ARRAYS_MATRIX_H +#include "indexmaps/cuboid/map.hpp" +#include "indexmaps/cuboid/slice.hpp" +#include "impl/indexmap_storage_pair.hpp" +#include "impl/assignment.hpp" +#include "vector.hpp" +namespace triqs { namespace arrays { + + template class matrix_view; + template class matrix; + + // ---------------------- matrix -------------------------------- + // +#define _IMPL_MATRIX_COMMON \ + size_t dim0() const { return this->shape()[0];}\ + size_t dim1() const { return this->shape()[1];}\ + bool is_square() const { return dim0() == dim1();}\ + \ + view_type transpose() const {\ + typename indexmap_type::lengths_type l; l[0] = this->indexmap().lengths()[1];l[1] = this->indexmap().lengths()[0];\ + typename indexmap_type::strides_type s; s[0] = this->indexmap().strides()[1];s[1] = this->indexmap().strides()[0];\ + return view_type( indexmap_type(l,s, this->indexmap().start_shift()), this->storage());\ + }\ + bool memory_layout_is_c() const { return this->indexmap().strides()[0] >= this->indexmap().strides()[1]; } \ + bool memory_layout_is_fortran() const { return this->indexmap().strides()[0] < this->indexmap().strides()[1]; } + +#define IMPL_TYPE indexmap_storage_pair < indexmaps::cuboid::map<2,Opt,TraversalOrder>, \ + storages::shared_block, Opt, TraversalOrder, Tag::matrix_view > + + template + class matrix_view : Tag::matrix_view, TRIQS_MODEL_CONCEPT(MutableMatrix), public IMPL_TYPE { + public : + typedef matrix_view view_type; + typedef matrix non_view_type; + typedef void has_view_type_tag; + + typedef typename IMPL_TYPE::indexmap_type indexmap_type; + typedef typename IMPL_TYPE::storage_type storage_type; + + /// Build from an IndexMap and a storage + template matrix_view (typename IMPL_TYPE::indexmap_type const & Ind,S const & Mem): IMPL_TYPE(Ind, Mem) {} + + /// Build from anything that has an indexmap and a storage compatible with this class + template matrix_view(const ISP & X): IMPL_TYPE(X.indexmap(),X.storage()) {} + +#ifdef TRIQS_WITH_PYTHON_SUPPORT + /// Build from a numpy.array : throws if X is not a numpy.array + explicit matrix_view (PyObject * X): IMPL_TYPE(X, false, "matrix_view "){} +#endif + + /// Copy construction + matrix_view( matrix_view const & X): IMPL_TYPE(X.indexmap(),X.storage()) {} + + matrix_view () = delete; + + // Move + matrix_view(matrix_view && X) { this->swap_me(X); } + + /// Swap + friend void swap( matrix_view & A, matrix_view & B) { A.swap_me(B);} + + /// Rebind the view + void rebind (matrix_view const & X) { this->indexmap_ = X.indexmap_; this->storage_ = X.storage_;} + + /** Assignement. The size of the array MUST match exactly. */ + template matrix_view & operator=(const RHS & X) {triqs_arrays_assign_delegation(*this,X); return *this; } + + matrix_view & operator=(matrix_view const & X) {triqs_arrays_assign_delegation(*this,X); return *this; }//cf array_view class comment + + // Move assignment not defined : will use the copy = since view must copy data + + TRIQS_DEFINE_COMPOUND_OPERATORS(matrix_view); + _IMPL_MATRIX_COMMON; + }; + + //--------------------------------------------------------------------- + // this traits is used by indexmap_storage_pair, when slicing to find the correct view type. + template < class V, int R, ull_t OptionFlags, ull_t To > struct ViewFactory< V, R, OptionFlags, To, Tag::matrix_view> { + typedef typename std::conditional , matrix_view >::type type; + }; + + // ---------------------- matrix -------------------------------- + + template + class matrix: Tag::matrix, TRIQS_MODEL_CONCEPT(MutableMatrix), public IMPL_TYPE { + public : + typedef typename IMPL_TYPE::value_type value_type; + typedef typename IMPL_TYPE::storage_type storage_type; + typedef typename IMPL_TYPE::indexmap_type indexmap_type; + typedef matrix_view view_type; + typedef matrix non_view_type; + typedef void has_view_type_tag; + + /// Empty matrix. + matrix(memory_layout<2> ml = memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order) ): IMPL_TYPE(indexmap_type(ml)) {} + + /// Move + explicit matrix(matrix && X) { this->swap_me(X); } + + /// + matrix(size_t dim1, size_t dim2, memory_layout<2> ml = memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order) ) : + IMPL_TYPE(indexmap_type(mini_vector(dim1,dim2),ml)) {} + + /// + matrix(mini_vector const & sha, memory_layout<2> ml = memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order)) : + IMPL_TYPE(indexmap_type(sha,ml)) {} + + /** Makes a true (deep) copy of the data. */ + matrix(const matrix & X): IMPL_TYPE(X.indexmap(),X.storage().clone()) {} + + /// Build a new matrix from X.domain() and fill it with by evaluating X. X can be : + template + matrix(const T & X, TYPE_ENABLE_IF(memory_layout<2>, ImmutableArray) ml = memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order)): + IMPL_TYPE(indexmap_type(X.domain(),ml)) { triqs_arrays_assign_delegation(*this,X); } + +#ifdef TRIQS_WITH_PYTHON_SUPPORT + ///Build from a numpy.array X (or any object from which numpy can make a numpy.array). Makes a copy. + explicit matrix (PyObject * X): IMPL_TYPE(X, true, "matrix "){} +#endif + + // build from a init_list + template + matrix (std::initializer_list> const & l): + IMPL_TYPE(memory_layout<2>(IMPL_TYPE::indexmap_type::traversal_order)) { + size_t i=0,j=0; int s=-1; + for (auto const & l1 : l) { if (s==-1) s= l1.size(); else if (s != l1.size()) TRIQS_RUNTIME_ERROR << "initializer list not rectangular !";} + IMPL_TYPE::resize(typename IMPL_TYPE::domain_type (mini_vector(l.size(),s))); + for (auto const & l1 : l) { + for (auto const & x : l1) { (*this)(i,j++) = x;} + j=0; ++i; + } + } + + /** + * Resizes the matrix. NB : all references to the storage is invalidated. + * Does not initialize the matrix by default + */ + matrix & resize (size_t n1, size_t n2) { IMPL_TYPE::resize(typename IMPL_TYPE::domain_type (mini_vector(n1,n2))); return *this;} + + /** + * Resizes the matrix. NB : all references to the storage is invalidated. + * Does not initialize the matrix by default + */ + matrix & resize (const indexmaps::cuboid::domain_t & l) { IMPL_TYPE::resize(l); return *this; } + + /// Assignement resizes the matrix. All references to the storage are therefore invalidated. + matrix & operator=(const matrix & X) { IMPL_TYPE::resize_and_clone_data(X); return *this; } + + /// Move assignment + matrix & operator=(matrix && X) { this->swap_me(X); return *this;} + + /// Swap + friend void swap( matrix & A, matrix & B) { A.swap_me(B);} + + /** + * Assignement resizes the matrix. All references to the storage are therefore invalidated. + * NB : to avoid that, do make_view(A) = X instead of A = X + */ + template + matrix & operator=(const RHS & X) { + static_assert( ImmutableArray::value, "Assignment : RHS not supported"); + IMPL_TYPE::resize(X.domain()); + triqs_arrays_assign_delegation(*this,X); + return *this; + } + + TRIQS_DEFINE_COMPOUND_OPERATORS(matrix); + _IMPL_MATRIX_COMMON; + };//matrix class +#undef _IMPL_MATRIX_COMMON +#undef IMPL_TYPE + +}}//namespace triqs::arrays + +// The std::swap is WRONG for a view because of the copy/move semantics of view. +// Use swap instead (the correct one, found by ADL). +namespace std { + template + void swap( triqs::arrays::matrix_view & a , triqs::arrays::matrix_view & b)= delete; +} +#include "./expression_template/matrix_algebra.hpp" +#endif + diff --git a/triqs/arrays/matrix_stack_view.hpp b/triqs/arrays/matrix_stack_view.hpp new file mode 100644 index 00000000..ae4384d9 --- /dev/null +++ b/triqs/arrays/matrix_stack_view.hpp @@ -0,0 +1,85 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_MATRIX_STACK_VIEW_H +#define TRIQS_ARRAYS_MATRIX_STACK_VIEW_H +#include "./array.hpp" +#include "./matrix.hpp" +#include "./matrix_view_proxy.hpp" +#include + +namespace triqs { namespace arrays { + + template class matrix_stack_view { + public: + typedef array_view array_view_t; + + matrix_stack_view( typename array_view_t::view_type const & a_):a(a_) {} + matrix_stack_view( array_view_t && a_):a(std::move(a_)) {} + +#ifdef TRIQS_WITH_PYTHON_SUPPORT + /// Build from a numpy.array (X is a borrowed reference) : throws if X is not a numpy.array + explicit matrix_stack_view (PyObject * X):a(typename array_view_t::view_type (X)){} +#endif + + matrix_view_proxy operator()(size_t i) { return matrix_view_proxy (a,i);} + const_matrix_view_proxy operator()(size_t i) const { return const_matrix_view_proxy (a,i);} + + matrix_view view(size_t i) const { return a(i,range(),range());} + + size_t size() const { return a.len(0);} + size_t dim0() const { return a.len(1);} + size_t dim1() const { return a.len(2);} + + matrix_stack_view & operator +=(matrix_stack_view const & arg) { a += arg.a; return *this; } + matrix_stack_view & operator -=(matrix_stack_view const & arg) { a -= arg.a; return *this; } + + template + typename std::enable_if::type + operator +=(RHS const & arg) { for (size_t i=0; i + typename std::enable_if::type + operator -=(RHS const & arg) { for (size_t i=0; i matrix_stack_view & operator *=(RHS const & arg) { a*= arg; return *this; } + template matrix_stack_view & operator /=(RHS const & arg) { a/= arg; return *this; } + + void invert() {for (size_t i=0; i const & L, matrix_stack_view const & M, matrix_view const & R) { + matrix_stack_view res (typename array_view_t::non_view_type (M.size(), L.dim0(), R.dim1())); + for (size_t i=0; i const & L, matrix_stack_view const & M, matrix_view const & R) { + if ((dim0() != L.dim0()) || (dim1() != R.dim1()) || (L.dim1() != R.dim0())) + TRIQS_RUNTIME_ERROR << "dimensions do not match!"; + for (size_t i=0; i. + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_MATRIX_VIEW_PROXY_H +#define TRIQS_ARRAYS_MATRIX_VIEW_PROXY_H +#include "./array.hpp" +#include "./matrix.hpp" +#include +#include +#include + +namespace triqs { namespace arrays { + + template class matrix_view_proxy; + template class const_matrix_view_proxy; + + // to do : separate the array and the matrix case. + // generalize with preprocessor (draft below) + + // write concept mutable down and clean it (dim0, dim1, len(i), ...) +#ifdef DO_NOT_DEFINE_ME + // human version of the class, the preprocessor generalisation is next.. + template class const_matrix_view_proxy : TRIQS_MODEL_CONCEPT(ImmutableMatrix) { + ArrayType const * A; size_t n; + public : + typedef typename ArrayType::value_type value_type; + const_matrix_view_proxy (ArrayType const & A_, size_t n_=0) : A(&A_), n(n_){} + typedef indexmaps::slicer slicer_t; + typedef typename slicer_t::r_type indexmap_type; + typedef typename indexmap_type::domain_type domain_type; + indexmap_type indexmap() const { return slicer_t::invoke(A->indexmap() , range() , range(),n, ellipsis()); } + domain_type domain() const { return indexmap().domain();} + size_t len(int i) const { return A->len(i);} + size_t dim0() const { return A->len(0);} + size_t dim1() const { return A->len(1);} + typename ArrayType::storage_type const & storage() const { return A->storage();} + TRIQS_DELETE_COMPOUND_OPERATORS(const_matrix_view_proxy); + template< typename A0 , typename A1 , typename ... Args> value_type const & operator() ( A0 &&a0 , A1 &&a1 , Args && ... args) const + { return (*A)( std::forward(a0) , std::forward(a1) , n,std::forward(args)...);} + }; + + template class matrix_view_proxy : TRIQS_MODEL_CONCEPT(MutableMatrix) { + ArrayType * A; size_t n; + public : + typedef typename ArrayType::value_type value_type; + matrix_view_proxy (ArrayType & A_, size_t n_=0) : A(&A_), n(n_){} + typedef indexmaps::slicer slicer_t; + typedef typename slicer_t::r_type indexmap_type; + typedef typename indexmap_type::domain_type domain_type; + indexmap_type indexmap() const { return slicer_t::invoke(A->indexmap() , range() , range(),n, ellipsis()); } + domain_type domain() const { return indexmap().domain();} + size_t len(int i) const { return A->len(i);} + size_t dim0() const { return A->len(0);} + size_t dim1() const { return A->len(1);} + typename ArrayType::storage_type const & storage() const { return A->storage();} + template matrix_view_proxy & operator=(const RHS & X) {triqs_arrays_assign_delegation(*this,X); return *this; } + TRIQS_DEFINE_COMPOUND_OPERATORS(matrix_view_proxy); + template< typename A0 , typename A1 , typename ... Args> value_type & operator() ( A0 &&a0 , A1 &&a1 , Args && ... args) const + { return (*A)( std::forward(a0) , std::forward(a1) , this->n,std::forward(args)...);} +}; + +#else +#define AUX0(z,P,NNN) std::forward(a##P), +#define AUX1(z,P,NNN) A##P && a##P, +#define TEXT(z, n, text) text +#define IMPL(z, POS, unused)\ + template class const_matrix_view_proxy : TRIQS_MODEL_CONCEPT(ImmutableMatrix) {\ + static_assert(ArrayType::rank==3, "Only array of rank 3 here");\ + ArrayType const * A; size_t n;\ + public :\ + typedef typename ArrayType::value_type value_type;\ + const_matrix_view_proxy (ArrayType const & A_, size_t n_=0) : A(&A_), n(n_){}\ + typedef indexmaps::slicer slicer_t;\ + typedef typename slicer_t::r_type indexmap_type;\ + typedef typename indexmap_type::domain_type domain_type;\ + indexmap_type indexmap() const { return slicer_t::invoke(A->indexmap() BOOST_PP_ENUM_TRAILING(POS, TEXT, range()),n, ellipsis()); }\ + domain_type domain() const { return indexmap().domain();}\ + size_t len(int i) const { return A->len(i);}\ + size_t dim0() const { return A->len((POS+1)%3);}\ + size_t dim1() const { return A->len((POS+2)%3);}\ + typename ArrayType::storage_type const & storage() const { return A->storage();}\ + value_type const * restrict data_start() const { return &storage()[indexmap().start_shift()];}\ + value_type * restrict data_start() { return &storage()[indexmap().start_shift()];}\ + matrix_view operator()() const {return *this;}\ + TRIQS_DELETE_COMPOUND_OPERATORS(const_matrix_view_proxy);\ + template\ + value_type const & operator() (BOOST_PP_REPEAT(POS,AUX1,nil) Args && ... args) const \ + { return (*A)(BOOST_PP_REPEAT(POS,AUX0,nil) n,std::forward(args)...);}\ + friend std::ostream & operator <<(std::ostream & out, const_matrix_view_proxy const & x) { return out << matrix_view(x);}\ + };\ +\ + template class matrix_view_proxy : TRIQS_MODEL_CONCEPT(MutableMatrix) {\ + static_assert(ArrayType::rank==3, "Only array of rank 3 here");\ + ArrayType * A; size_t n;\ + public :\ + typedef typename ArrayType::value_type value_type;\ + matrix_view_proxy (ArrayType & A_, size_t n_=0) : A(&A_), n(n_){}\ + typedef indexmaps::slicer slicer_t;\ + typedef typename slicer_t::r_type indexmap_type;\ + typedef typename indexmap_type::domain_type domain_type;\ + indexmap_type indexmap() const { return slicer_t::invoke(A->indexmap() BOOST_PP_ENUM_TRAILING(POS, TEXT, range()),n, ellipsis()); }\ + domain_type domain() const { return indexmap().domain();}\ + size_t len(int i) const { return A->len(i);}\ + size_t dim0() const { return A->len((POS+1)%3);}\ + size_t dim1() const { return A->len((POS+2)%3);}\ + typename ArrayType::storage_type const & storage() const { return A->storage();}\ + value_type const * restrict data_start() const { return &storage()[indexmap().start_shift()];}\ + value_type * restrict data_start() { return &storage()[indexmap().start_shift()];}\ + matrix_view operator()() const {return *this;}\ + template matrix_view_proxy & operator=(const RHS & X) {triqs_arrays_assign_delegation(*this,X); return *this; }\ + TRIQS_DEFINE_COMPOUND_OPERATORS(matrix_view_proxy);\ + template\ + value_type & operator() (BOOST_PP_REPEAT(POS,AUX1,nil) Args && ... args) const\ + { return (*A)(BOOST_PP_REPEAT(POS,AUX0,nil) n,std::forward(args)...);}\ + friend std::ostream & operator <<(std::ostream & out, matrix_view_proxy const & x) { return out << matrix_view(x);}\ +}; + + BOOST_PP_REPEAT(ARRAY_NRANK_MAX , IMPL, nil); +#undef IMPL +#undef AUX0 +#undef AUX1 +#undef TEXT +#endif + + template + matrix_view_proxy make_matrix_view_proxy(ArrayType const & A) { return matrix_view_proxy (A);} + +}} +#endif + diff --git a/triqs/arrays/matrix_view_proxy_DEBUG.hpp b/triqs/arrays/matrix_view_proxy_DEBUG.hpp new file mode 100644 index 00000000..2b861530 --- /dev/null +++ b/triqs/arrays/matrix_view_proxy_DEBUG.hpp @@ -0,0 +1,151 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_MATRIX_VIEW_PROXY_H +#define TRIQS_ARRAYS_MATRIX_VIEW_PROXY_H +#include "./array.hpp" +#include "./matrix.hpp" +#include +#include +#include + +namespace triqs { namespace arrays { + + template class matrix_view_proxy; + template class const_matrix_view_proxy; + + // to do : separate the array and the matrix case. + // generalize with preprocessor (draft below) + + // write concept mutable down and clean it (dim0, dim1, len(i), ...) +#ifdef DO_NOT_DEFINE_ME + // human version of the class, the preprocessor generalisation is next.. + template class const_matrix_view_proxy : TRIQS_MODEL_CONCEPT(ImmutableMatrix) { + ArrayType const * A; size_t n; + public : + typedef typename ArrayType::value_type value_type; + const_matrix_view_proxy (ArrayType const & A_, size_t n_=0) : A(&A_), n(n_){} + typedef indexmaps::slicer slicer_t; + typedef typename slicer_t::r_type indexmap_type; + typedef typename indexmap_type::domain_type domain_type; + indexmap_type indexmap() const { return slicer_t::invoke(A->indexmap() , range() , range(),n, ellipsis()); } + domain_type domain() const { return indexmap().domain();} + size_t len(int i) const { return A->len(i);} + size_t dim0() const { return A->len(0);} + size_t dim1() const { return A->len(1);} + typename ArrayType::storage_type const & storage() const { return A->storage();} + TRIQS_DELETE_COMPOUND_OPERATORS(const_matrix_view_proxy); + template< typename A0 , typename A1 , typename ... Args> value_type const & operator() ( A0 &&a0 , A1 &&a1 , Args && ... args) const + { return (*A)( std::forward(a0) , std::forward(a1) , n,std::forward(args)...);} + }; + + template class matrix_view_proxy : TRIQS_MODEL_CONCEPT(MutableMatrix) { + ArrayType * A; size_t n; + public : + typedef typename ArrayType::value_type value_type; + matrix_view_proxy (ArrayType & A_, size_t n_=0) : A(&A_), n(n_){} + typedef indexmaps::slicer slicer_t; + typedef typename slicer_t::r_type indexmap_type; + typedef typename indexmap_type::domain_type domain_type; + indexmap_type indexmap() const { return slicer_t::invoke(A->indexmap() , range() , range(),n, ellipsis()); } + domain_type domain() const { return indexmap().domain();} + size_t len(int i) const { return A->len(i);} + size_t dim0() const { return A->len(0);} + size_t dim1() const { return A->len(1);} + typename ArrayType::storage_type const & storage() const { return A->storage();} + template matrix_view_proxy & operator=(const RHS & X) {triqs_arrays_assign_delegation(*this,X); return *this; } + TRIQS_DEFINE_COMPOUND_OPERATORS(matrix_view_proxy); + template< typename A0 , typename A1 , typename ... Args> value_type & operator() ( A0 &&a0 , A1 &&a1 , Args && ... args) const + { return (*A)( std::forward(a0) , std::forward(a1) , this->n,std::forward(args)...);} +}; + +#else +#define AUX0(z,P,NNN) std::forward(a##P), +#define AUX1(z,P,NNN) A##P && a##P, +#define TEXT(z, n, text) text +#define IMPL(z, POS, unused)\ + template class const_matrix_view_proxy : TRIQS_MODEL_CONCEPT(ImmutableMatrix) {\ + static_assert(ArrayType::rank==3, "Only array of rank 3 here");\ + ArrayType const * A; size_t n;\ + public :\ + typedef typename ArrayType::value_type value_type;\ + const_matrix_view_proxy (ArrayType const & A_, size_t n_=0) : A(&A_), n(n_), S(this->storage()), IM(this->indexmap()){}\ + typedef indexmaps::slicer slicer_t;\ + typedef typename slicer_t::r_type indexmap_type;\ + typedef typename indexmap_type::domain_type domain_type;\ + indexmap_type indexmap() const { return slicer_t::invoke(A->indexmap() BOOST_PP_ENUM_TRAILING(POS, TEXT, range()),n, ellipsis()); }\ + domain_type domain() const { return indexmap().domain();}\ + size_t len(int i) const { return A->len(i);}\ + size_t dim0() const { return A->len((POS+1)%3);}\ + size_t dim1() const { return A->len((POS+2)%3);}\ + typename ArrayType::storage_type const & storage() const { return A->storage();}\ + value_type const * restrict data_start() const { return &storage()[indexmap().start_shift()];}\ + value_type * restrict data_start() { return &storage()[indexmap().start_shift()];}\ + matrix_view operator()() const {return *this;}\ + TRIQS_DELETE_COMPOUND_OPERATORS(const_matrix_view_proxy);\ + template\ + value_type const & operator() (BOOST_PP_REPEAT(POS,AUX1,nil) Args && ... args) const \ + { return (*A)(BOOST_PP_REPEAT(POS,AUX0,nil) n,std::forward(args)...);}\ + friend std::ostream & operator <<(std::ostream & out, const_matrix_view_proxy const & x) { return out << matrix_view(x);}\ +typename ArrayType::storage_type S;\ +indexmap_type IM;\ + };\ +\ + template class matrix_view_proxy : TRIQS_MODEL_CONCEPT(MutableMatrix) {\ + static_assert(ArrayType::rank==3, "Only array of rank 3 here");\ + ArrayType * A; size_t n;\ + public :\ + typedef typename ArrayType::value_type value_type;\ + matrix_view_proxy (ArrayType & A_, size_t n_=0) : A(&A_), n(n_), IM(this->indexmap()){}\ + typedef indexmaps::slicer slicer_t;\ + typedef typename slicer_t::r_type indexmap_type;\ + typedef typename indexmap_type::domain_type domain_type;\ + indexmap_type indexmap() const { return slicer_t::invoke(A->indexmap() BOOST_PP_ENUM_TRAILING(POS, TEXT, range()),n, ellipsis()); }\ + domain_type domain() const { return indexmap().domain();}\ + size_t len(int i) const { return A->len(i);}\ + size_t dim0() const { return A->len((POS+1)%3);}\ + size_t dim1() const { return A->len((POS+2)%3);}\ + typename ArrayType::storage_type const & storage() const { return A->storage();}\ + value_type const * restrict data_start() const { return &storage()[indexmap().start_shift()];}\ + value_type * restrict data_start() { return &storage()[indexmap().start_shift()];}\ + matrix_view operator()() const {return *this;}\ + template matrix_view_proxy & operator=(const RHS & X) {triqs_arrays_assign_delegation(*this,X); return *this; }\ + TRIQS_DEFINE_COMPOUND_OPERATORS(matrix_view_proxy);\ + template\ + value_type & operator() (BOOST_PP_REPEAT(POS,AUX1,nil) Args && ... args) const\ + { return (*A)(BOOST_PP_REPEAT(POS,AUX0,nil) n,std::forward(args)...);}\ + friend std::ostream & operator <<(std::ostream & out, matrix_view_proxy const & x) { return out << matrix_view(x);}\ +typename ArrayType::storage_type S;\ +indexmap_type IM;\ + }; + + BOOST_PP_REPEAT(ARRAY_NRANK_MAX , IMPL, nil); +#undef IMPL +#undef AUX0 +#undef AUX1 +#undef TEXT +#endif + + template + matrix_view_proxy make_matrix_view_proxy(ArrayType const & A) { return matrix_view_proxy (A);} + +}} +#endif + diff --git a/triqs/arrays/python/array_view_to_python.hpp b/triqs/arrays/python/array_view_to_python.hpp new file mode 100644 index 00000000..48e1696e --- /dev/null +++ b/triqs/arrays/python/array_view_to_python.hpp @@ -0,0 +1,76 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_TO_PYTHON_H +#define TRIQS_ARRAYS_TO_PYTHON_H +#ifndef TRIQS_WITH_PYTHON_SUPPORT +#error "You must define the macro TRIQS_WITH_PYTHON_SUPPORT to use Python interface" +#endif +#include +#include "../impl/indexmap_storage_pair.hpp" +//#include "../array.hpp" + +namespace triqs { namespace arrays { namespace numpy_interface { + + template + PyObject * array_view_to_python ( ArrayViewType const & A, bool copy=false) { + _import_array(); + typedef typename ArrayViewType::value_type value_type; + static const int rank = ArrayViewType::rank; + const int elementsType (numpy_to_C_type::type>::arraytype); + npy_intp dims[rank], strides[rank]; + for(size_t i =0; ibase = A.storage().new_ref_to_guard(); + assert( arr->flags == (arr->flags & ~NPY_OWNDATA)); +#else + int r = PyArray_SetBaseObject(arr,A.storage().new_ref_to_guard()); + if (r!=0) TRIQS_RUNTIME_ERROR << "Internal Error setting the guard in numpy !!!!"; + assert( PyArray_FLAGS(arr) == (PyArray_FLAGS(arr) & ~NPY_ARRAY_OWNDATA)); +#endif + if (copy) { + PyObject * na = PyObject_CallMethod(res,(char*)"copy",NULL); + Py_DECREF(res); + // POrt this for 1.7 + //assert(((PyArrayObject *)na)->base ==NULL); + res = na; + } + return res; + } + +}}} +#endif + diff --git a/triqs/arrays/python/numpy_extractor.hpp b/triqs/arrays/python/numpy_extractor.hpp new file mode 100644 index 00000000..1d617961 --- /dev/null +++ b/triqs/arrays/python/numpy_extractor.hpp @@ -0,0 +1,172 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_NUMPY_EXTRACTOR_H +#define TRIQS_ARRAYS_NUMPY_EXTRACTOR_H + +#ifdef TRIQS_WITH_PYTHON_SUPPORT +#include "../storages/shared_block.hpp" +#include "triqs/utility/exceptions.hpp" +#include "numpy/arrayobject.h" + +namespace triqs { namespace arrays { namespace numpy_interface { + + inline std::string object_to_string (PyObject * p) { + if (!PyString_Check(p)) TRIQS_RUNTIME_ERROR<<" Internal error, expected a python string ....."; + return PyString_AsString(p); + } + + template struct numpy_to_C_type; +#define CONVERT(C,P) template <> struct numpy_to_C_type { enum {arraytype = P}; } + CONVERT(bool, NPY_BOOL); + CONVERT(char, NPY_CHAR); + CONVERT(signed char, NPY_BYTE); + CONVERT(unsigned char, NPY_UBYTE); + CONVERT(short, NPY_SHORT); + CONVERT(unsigned short, NPY_USHORT); + CONVERT(int, NPY_INT); + CONVERT(unsigned int, NPY_UINT); + CONVERT(long, NPY_LONG); + CONVERT(unsigned long, NPY_ULONG); + CONVERT(long long, NPY_LONGLONG); + CONVERT(unsigned long long, NPY_ULONGLONG); + CONVERT(float, NPY_FLOAT); + CONVERT(double, NPY_DOUBLE); + CONVERT(long double, NPY_LONGDOUBLE); + CONVERT(std::complex, NPY_CFLOAT); + CONVERT(std::complex, NPY_CDOUBLE); + CONVERT(std::complex, NPY_CLONGDOUBLE); +#undef CONVERT + + struct copy_exception : public triqs::runtime_error {}; + + // return a NEW (owned) reference + // + inline PyObject * numpy_extractor_impl ( PyObject * X, bool allow_copy, std::string type_name, + int elementsType, int rank, size_t * lengths, std::ptrdiff_t * strides, size_t size_of_ValueType) { + + PyObject * numpy_obj; + + if (X==NULL) TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is NULL !"; + if (_import_array()!=0) TRIQS_RUNTIME_ERROR <<"Internal Error in importing numpy"; + + static const char * error_msg = " A deep copy of the object would be necessary while views are supposed to guarantee to present a *view* of the python data.\n"; + + if (!allow_copy) { + if (!PyArray_Check(X)) throw copy_exception () << error_msg<<" Indeed the object was not even an array !\n"; + if ( elementsType != PyArray_TYPE((PyArrayObject*)X)) + throw copy_exception () << error_msg<<" The deep copy is caused by a type mismatch of the elements. Expected "<< type_name<< " and found XXX \n"; + PyArrayObject *arr = (PyArrayObject *)X; +#ifdef TRIQS_NUMPY_VERSION_LT_17 + if ( arr->nd != rank) throw copy_exception () << error_msg<<" Rank mismatch . numpy array is of rank "<< arr->nd << "while you ask for rank "<< rank<<". \n"; +#else + if ( PyArray_NDIM(arr) != rank) throw copy_exception () << error_msg<<" Rank mismatch . numpy array is of rank "<< PyArray_NDIM(arr) << "while you ask for rank "<< rank<<". \n"; +#endif + numpy_obj = X; Py_INCREF(X); + } + else { + // From X, we ask the numpy library to make a numpy, and of the correct type. + // This handles automatically the cases where : + // - we have list, or list of list/tuple + // - the numpy type is not the one we want. + // - adjust the dimension if needed + // If X is an array : + // - if Order is same, don't change it + // - else impose it (may provoque a copy). + // if X is not array : + // - Order = FortranOrder or SameOrder - > Fortran order otherwise C + + //bool ForceCast = false;// Unless FORCECAST is present in flags, this call will generate an error if the data type cannot be safely obtained from the object. + int flags = 0; //(ForceCast ? NPY_FORCECAST : 0) ;// do NOT force a copy | (make_copy ? NPY_ENSURECOPY : 0); + if (!(PyArray_Check(X) )) + //flags |= ( IndexMapType::traversal_order == indexmaps::mem_layout::c_order(rank) ? NPY_C_CONTIGUOUS : NPY_F_CONTIGUOUS); //impose mem order +#ifdef TRIQS_NUMPY_VERSION_LT_17 + flags |= (NPY_C_CONTIGUOUS); //impose mem order +#else + flags |= (NPY_ARRAY_C_CONTIGUOUS); //impose mem order +#endif + numpy_obj= PyArray_FromAny(X,PyArray_DescrFromType(elementsType), rank,rank, flags , NULL ); + + // do several checks + if (!numpy_obj) {// The convertion of X to a numpy has failed ! + if (PyErr_Occurred()) {PyErr_Print();PyErr_Clear();} + TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is not convertible to a numpy. "; + } + assert (PyArray_Check(numpy_obj)); assert((numpy_obj->ob_refcnt==1) || ((numpy_obj ==X))); + + PyArrayObject *arr_obj; + arr_obj = (PyArrayObject *)numpy_obj; + try { +#ifdef TRIQS_NUMPY_VERSION_LT_17 + if (arr_obj->nd!=rank) TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : dimensions do not match"; + if (arr_obj->descr->type_num != elementsType) + TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : incorrect type of element :" <descr->type_num <<" vs "<type_num != elementsType) + TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : incorrect type of element :" <type_num <<" vs "<nd; // we know that dim == rank + for (size_t i=0; i< dim ; ++i) { + lengths[i] = size_t(arr_obj-> dimensions[i]); + strides[i] = std::ptrdiff_t(arr_obj-> strides[i])/ size_of_ValueType; + } +#else + const size_t dim = PyArray_NDIM(arr_obj); // we know that dim == rank + for (size_t i=0; i< dim ; ++i) { + lengths[i] = size_t( PyArray_DIMS(arr_obj)[i]); + strides[i] = std::ptrdiff_t( PyArray_STRIDES(arr_obj)[i])/ size_of_ValueType; + } +#endif + + return numpy_obj; + } + + // a little template class + template struct numpy_extractor { + + numpy_extractor (PyObject * X, bool allow_copy) { + numpy_obj = numpy_extractor_impl (X, allow_copy, typeid(ValueType).name(), numpy_to_C_type::type>::arraytype, IndexMapType::rank, + &lengths[0], &strides[0],sizeof(ValueType)); + } + + ~numpy_extractor(){ Py_DECREF(numpy_obj);} + + IndexMapType indexmap() const { return IndexMapType (lengths,strides,0); } + + storages::shared_block storage() const { return storages::shared_block (numpy_obj,true); } + // true means borrowed : object is owned by this class, which will decref it in case of exception ... + + private: + PyObject * numpy_obj; + mini_vector lengths; + mini_vector strides; + }; +}}} +#endif +#endif diff --git a/triqs/arrays/storages/basic_block.hpp b/triqs/arrays/storages/basic_block.hpp new file mode 100644 index 00000000..b752b94b --- /dev/null +++ b/triqs/arrays/storages/basic_block.hpp @@ -0,0 +1,68 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ + +#ifndef TRIQS_ARRAYS_BASIC_BLOCK_H +#define TRIQS_ARRAYS_BASIC_BLOCK_H +#include + +// A minimal basic block : replace by a vector<> or is it quicker ? +namespace triqs { namespace arrays { namespace storages { namespace details { + + template + struct basic_block : boost::noncopyable { + typedef typename boost::remove_const::type non_const_value_type; + size_t size_; + non_const_value_type * restrict p; + + basic_block():size_(0),p(NULL){} + + basic_block (size_t s):size_(s),p(new non_const_value_type[s]) { } + + ~basic_block(){if (p) {delete[] p; } } + + void operator=(const basic_block & X) { + assert(size_==X.size_);assert(p); assert(X.p); + memcpy (p,X.p,size_ * sizeof(ValueType)); + } + + non_const_value_type & operator[](size_t i) {return p[i];} + + size_t size() const {return size_;} + + template + void save(Archive & ar, const unsigned int version) const { + ar << boost::serialization::make_nvp("size",size_); + for (size_t i=0; i + void load(Archive & ar, const unsigned int version) { + ar >> size_; + assert (p==NULL); + p = new non_const_value_type[size_]; + for (size_t i=0; i> p[i]; + } + BOOST_SERIALIZATION_SPLIT_MEMBER(); + }; +}}}}//namespace triqs::arrays ... +#endif + diff --git a/triqs/arrays/storages/mem_block.hpp b/triqs/arrays/storages/mem_block.hpp new file mode 100644 index 00000000..ad0ddd0c --- /dev/null +++ b/triqs/arrays/storages/mem_block.hpp @@ -0,0 +1,156 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_MEM_BLOCK_H +#define TRIQS_MEM_BLOCK_H +#include "../../utility/exceptions.hpp" +#include +#include +#include "./memcopy.hpp" + +#ifdef TRIQS_ARRAYS_DEBUG_TRACE_MEM +#include +#define TRACE_MEM_DEBUG(X) std::cerr<< X << std::endl; +#else +#define TRACE_MEM_DEBUG(X) +#endif + +namespace triqs { namespace arrays { namespace storages { namespace details { + + template class mem_block { + + typedef typename boost::remove_const::type non_const_value_type; + size_t size_; + non_const_value_type * restrict p; + PyObject * py_obj; + static void import_numpy_array() { if (_import_array()!=0) TRIQS_RUNTIME_ERROR <<"Internal Error in importing numpy";} + + public : + + mem_block():size_(0),p(NULL),py_obj(NULL){} + + mem_block (size_t s):size_(s),py_obj(NULL){ + //p = new non_const_value_type[s]; // check speed penalty for try ?? + try { p = new non_const_value_type[s];} + catch (std::bad_alloc& ba) { TRIQS_RUNTIME_ERROR<< "Memory allocation error : bad_alloc : "<< ba.what();} + } + + mem_block (PyObject * obj, bool borrowed ) { + TRACE_MEM_DEBUG(" construct memblock from pyobject"<p = (non_const_value_type*)PyArray_DATA(arr); + py_obj = obj; + } + + ~mem_block(){ // delete memory manually iif py_obj is not set. Otherwise the python interpreter will do that for us. + TRACE_MEM_DEBUG("deleting mem block p ="<ob_refcnt: -1)); + if (py_obj==NULL) { if (p) { delete[] p;} } + else Py_DECREF(py_obj); + } + + void operator=(const mem_block & X) { + //assert( py_obj==NULL); + assert(size_==X.size_);assert(p); assert(X.p); + storages::memcopy (p, X.p, size_); + } + + mem_block ( mem_block const & X): size_(X.size()), py_obj(NULL) { + //p = new non_const_value_type[s]; // check speed penalty for try ?? + try { p = new non_const_value_type[X.size()];} + catch (std::bad_alloc& ba) { TRIQS_RUNTIME_ERROR<< "Memory allocation error : bad_alloc : "<< ba.what();} + if ((X.py_obj==NULL) || (PyCObject_Check(X.py_obj))) { (*this) = X; } + else { + // else make a new copy of the numpy ... + import_numpy_array(); + //assert(PyArray_Check(X.py_obj)); + if (!is_scalar_or_pod::value) TRIQS_RUNTIME_ERROR << "Internal Error : memcpy on non-scalar"; +#ifdef TRIQS_NUMPY_VERSION_LT_17 + if ( ( PyArray_ISFORTRAN(X.py_obj)) || (PyArray_ISCONTIGUOUS(X.py_obj))) { + memcpy (p,PyArray_DATA(X.py_obj),size_ * sizeof(ValueType)); + } +#else + // STRANGE : uncommenting this leads to a segfault on mac ??? + // TO BE INVESTIGATED, IT IS NOT NORMAL + //if (!PyArray_Check(X.py_obj)) TRIQS_RUNTIME_ERROR<<"Internal error : is not an array"; + PyArrayObject * arr3 = (PyArrayObject *)(X.py_obj); + if ( ( PyArray_ISFORTRAN(arr3)) || (PyArray_ISCONTIGUOUS(arr3))) { + memcpy (p,PyArray_DATA(arr3),size_ * sizeof(ValueType)); + } +#endif + else { // if the X.py_obj is not contiguous, first let numpy copy it properly + PyObject * na = PyObject_CallMethod(X.py_obj,(char *)"copy",NULL); + assert(na); +#ifdef TRIQS_NUMPY_VERSION_LT_17 + assert( ( PyArray_ISFORTRAN(na)) || (PyArray_ISCONTIGUOUS(na))); + memcpy (p,PyArray_DATA(na),size_ * sizeof(ValueType)); +#else + if (!PyArray_Check(na)) TRIQS_RUNTIME_ERROR<<"Internal error : is not an array"; + PyArrayObject * arr = (PyArrayObject *)(na); + assert( ( PyArray_ISFORTRAN(arr)) || (PyArray_ISCONTIGUOUS(arr))); + memcpy (p,PyArray_DATA(arr),size_ * sizeof(ValueType)); +#endif + Py_DECREF(na); + } + } + } + + static void delete_pointeur( void *ptr ) { + TRACE_MEM_DEBUG("deleting data block"<<(non_const_value_type*) ptr); + delete [] ( (non_const_value_type*) ptr) ; + } + + PyObject * new_ref_to_guard() { + if (py_obj==NULL) { + TRACE_MEM_DEBUG(" activating python guard for C++ block"< + void load(Archive & ar, const unsigned int version) { + ar >> size_; + assert (p==NULL); + p = new non_const_value_type[size_]; + for (size_t i=0; i> p[i]; + } + BOOST_SERIALIZATION_SPLIT_MEMBER(); + }; +}}}}//namespace triqs::arrays + +#undef TRACE_MEM_DEBUG +#endif + diff --git a/triqs/arrays/storages/memcopy.hpp b/triqs/arrays/storages/memcopy.hpp new file mode 100644 index 00000000..aa629fcc --- /dev/null +++ b/triqs/arrays/storages/memcopy.hpp @@ -0,0 +1,52 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_MEMCOPY_H +#define TRIQS_MEMCOPY_H +#include "../../utility/exceptions.hpp" + +namespace triqs { namespace arrays { namespace storages { + + // beware : complex is not a pod + template struct is_scalar_or_pod : std::integral_constant::value || boost::is_complex::value || std::is_pod::value > {}; + + // copy such that it is a fast memcpy for scalar / pod objects + // when not a scalar object, loop on elements + + template + void memcopy_impl (T1 * restrict p1, const T2 * restrict p2, size_t size, std::false_type) { for (size_t i = 0; i < size; ++i) p1[i] = p2[i]; } + + template + void memcopy_impl (T * restrict p1, const T * restrict p2, size_t size, std::true_type) { + if (std::abs(p2-p1)>size) {memcpy (p1, p2, size * sizeof(T));} // guard against aliasing of data + else { memcopy_impl(p1,p2,size,std::false_type());} + } + + template + void memcopy (T1 * restrict p1, const T2 * restrict p2, size_t size) { + constexpr bool use_memcpy = std::is_pod::value && + std::is_same< typename std::remove_cv::type, typename std::remove_cv::type>::value; + memcopy_impl(p1,p2,size,std::integral_constant()); + } + +}}} +#endif + + diff --git a/triqs/arrays/storages/shared_block.hpp b/triqs/arrays/storages/shared_block.hpp new file mode 100644 index 00000000..87580579 --- /dev/null +++ b/triqs/arrays/storages/shared_block.hpp @@ -0,0 +1,149 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_STORAGE_SHARED_POINTER_H +#define TRIQS_STORAGE_SHARED_POINTER_H +#include +#include +#include +#include +#include +#include +#include +#include +#include "../impl/make_const.hpp" +#ifdef TRIQS_WITH_PYTHON_SUPPORT +#include "./mem_block.hpp" +#else +#include +//#include "basic_block.hpp" +#endif + +namespace triqs { namespace arrays { + namespace Tag {struct storage{}; struct shared_block:storage{}; } + + namespace storages { + + template struct __init_value; + template struct __init_value { static void invoke (V * data, size_t s) {}}; + template struct __init_value< V, Tag::default_init> { + static void invoke (V * restrict data, size_t s) { if (data!=NULL) for (size_t u=0; u struct __init_value< V, Tag::nan_inf_init> { + static void invoke (V * restrict data, size_t s) { + static_assert ( ( std::numeric_limits::has_quiet_NaN || std::numeric_limits::is_integer), "type has no Nan and is not integer. This init is impossible"); + if (data==NULL) return; + if (std::numeric_limits::has_quiet_NaN) for (size_t u=0; u::quiet_NaN(); + if (std::numeric_limits::is_integer) for (size_t u=0; u::max(); + } + }; + + template struct __init_value< std::complex, Tag::nan_inf_init> { + static void invoke (std::complex * restrict data, size_t s) { + static_assert ( ( std::numeric_limits::has_quiet_NaN || std::numeric_limits::is_integer), "type has no Nan and is not integer. This init is impossible"); + if (data==NULL) return; + if (std::numeric_limits::has_quiet_NaN) for (size_t u=0; u(std::numeric_limits::quiet_NaN(),std::numeric_limits::quiet_NaN()) ; + if (std::numeric_limits::is_integer) for (size_t u=0; u(std::numeric_limits::max(),std::numeric_limits::max()); + } + }; + + + /* Storage as a shared_ptr to a basic_block + * The shared pointer guarantees that the data will not be destroyed during the life of the array. + * Impl: we are not using shared_array directly because of serialization support for shared_ptr */ + template + class shared_block : Tag::shared_block { + typedef typename boost::add_const::type const_value_type; + typedef typename boost::remove_const::type non_const_value_type; +#ifdef TRIQS_WITH_PYTHON_SUPPORT + typedef details::mem_block block_type; +#else + // typedef details::basic_block block_type; + typedef std::vector block_type; +#endif + + public: + typedef triqs::arrays::Tag::shared_block tag; + typedef ValueType value_type; + typedef shared_block clone_type; + typedef shared_block const_clone_type; + + /// Construct a new block of memory of given size + template + explicit shared_block(size_t size, InitOpt opt ): sptr(size ? new block_type(size) : NULL) { + init_data(); + __init_value::invoke (this-> data_, this->size()); + } + + explicit shared_block(): sptr() { init_data(); } + +#ifdef TRIQS_WITH_PYTHON_SUPPORT + /// Construct from a numpy object + explicit shared_block(PyObject * arr, bool borrowed): sptr(new block_type(arr,borrowed)) { init_data();} +#endif + + /// Shallow copy + shared_block(const shared_block & X): sptr(X.sptr) { init_data(); } + + /// Shallow copy + shared_block(const shared_block & X): sptr(X.sptr) { init_data(); } + + void operator=(const shared_block & X) { sptr=X.sptr; init_data(); } + + /// True copy of the data + clone_type clone() const { + if (empty()) return clone_type (); +#ifdef TRIQS_WITH_PYTHON_SUPPORT + clone_type res; res.sptr = boost::make_shared (*sptr); res.init_data(); +#else + clone_type res(this->size(), Tag::no_init() ); (*res.sptr) = (*sptr); +#endif + return res; + } + + // Make a clone forced to have const value_type + const_clone_type const_clone() const {return clone();} + + value_type & operator[](size_t i) const { return data_[i];} + bool empty() const {return (sptr.get()==NULL);} + size_t size() const {return (empty () ? 0 : sptr.get()->size());} + +#ifdef TRIQS_WITH_PYTHON_SUPPORT + PyObject * new_ref_to_guard() const {return sptr->new_ref_to_guard();} +#endif + + private: + boost::shared_ptr sptr; + value_type * restrict data_; // for optimization on some compilers. + void init_data(){ data_ = (sptr ? &((*sptr)[0]) : NULL); } + friend class shared_block ; friend class shared_block ; + friend class boost::serialization::access; + template void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::make_nvp("ptr",sptr); init_data(); } + }; + } + + namespace details { + template struct make_const_type > { + typedef storages::shared_block::type> type; + }; + } +}}//namespace triqs::arrays +#endif + diff --git a/triqs/arrays/vector.hpp b/triqs/arrays/vector.hpp new file mode 100644 index 00000000..5c151e93 --- /dev/null +++ b/triqs/arrays/vector.hpp @@ -0,0 +1,299 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAY_VECTOR_H +#define TRIQS_ARRAY_VECTOR_H +#include "indexmaps/cuboid/map.hpp" +#include "indexmaps/cuboid/slice.hpp" +#include "impl/indexmap_storage_pair.hpp" +#include "impl/assignment.hpp" +#include "impl/flags.hpp" +#include + +namespace triqs { namespace arrays { + + template class vector_view; + template class vector; + + // ---------------------- vector_view -------------------------------- + +#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map<1,Opt,0> , storages::shared_block, Opt, 0, Tag::vector_view > + + /** */ + template + class vector_view : Tag::vector_view, TRIQS_MODEL_CONCEPT(MutableVector), public IMPL_TYPE { + public : + typedef vector_view view_type; + typedef vector non_view_type; + typedef void has_view_type_tag; + + typedef typename IMPL_TYPE::indexmap_type indexmap_type; + typedef typename IMPL_TYPE::storage_type storage_type; + + /// Build from an IndexMap and a storage + template vector_view (indexmaps::cuboid::map<1, Opt2,To2> const & Ind,S const & Mem): IMPL_TYPE(Ind, Mem) {} + + /// Build from anything that has an indexmap and a storage compatible with this class + template + vector_view(const ISP & X): IMPL_TYPE(X.indexmap(),X.storage()) {} + +#ifdef TRIQS_WITH_PYTHON_SUPPORT + /// Build from a numpy.array : throws if X is not a numpy.array + explicit vector_view (PyObject * X): IMPL_TYPE(X, false, "vector_view "){} +#endif + + /// Copy construction + vector_view(vector_view const & X): IMPL_TYPE(X.indexmap(),X.storage()) {} + + vector_view () = delete; + + // Move + vector_view(vector_view && X) { this->swap_me(X);} + + /// Swap + friend void swap( vector_view & A, vector_view & B) { A.swap_me(B);} + + /// Rebind the view + void rebind (vector_view const & X) { this->indexmap_ = X.indexmap_; this->storage_ = X.storage_;} + + /** Assignment. The size of the array MUST match exactly. */ + template vector_view & operator=(const RHS & X) { triqs_arrays_assign_delegation(*this,X); return *this; } + + vector_view & operator=(vector_view const & X) {triqs_arrays_assign_delegation(*this,X); return *this; }//cf array_view class comment + + // Move assignment not defined : will use the copy = since view must copy data + + size_t size() const { return this->shape()[0];} + + std::ptrdiff_t stride() const { return this->indexmap().strides()[0];} + + TRIQS_DEFINE_COMPOUND_OPERATORS(vector_view); + + // to make interface similar to std::vector : forward [] to () + template typename std::result_of::type operator[](Arg && arg) const { return (*this) (std::forward(arg));} + template typename std::result_of::type operator[](Arg && arg) { return (*this) (std::forward(arg));} + // gcc 4.6 does not like this one... + //template auto operator[](Arg && arg) const DECL_AND_RETURN((*this)(std::forward(arg))); + //template auto operator[](Arg && arg) DECL_AND_RETURN((*this)(std::forward(arg))); + }; + + template < class V, int R, ull_t OptionFlags, ull_t To > struct ViewFactory< V, R,OptionFlags,To, Tag::vector_view> { typedef vector_view type; }; + // ---------------------- vector-------------------------------- + + template + class vector: Tag::vector, TRIQS_MODEL_CONCEPT(MutableVector), public IMPL_TYPE { + public : + typedef typename IMPL_TYPE::value_type value_type; + typedef typename IMPL_TYPE::storage_type storage_type; + typedef typename IMPL_TYPE::indexmap_type indexmap_type; + typedef vector_view view_type; + typedef vector non_view_type; + typedef void has_view_type_tag; + + /// Empty vector. + vector(){} + + // Move + explicit vector(vector && X) { this->swap_me(X); } + + /// + vector(size_t dim):IMPL_TYPE(indexmap_type(mini_vector(dim))) {} + + /// to mimic std vector + template + vector(size_t dim, Arg && arg):IMPL_TYPE(indexmap_type(mini_vector(dim))) { (*this)() = std::forward(arg);} + + /** Makes a true (deep) copy of the data. */ + vector(const vector & X): IMPL_TYPE(X.indexmap(),X.storage().clone()) {} + + /** + * Build a new vector from X.domain() and fill it with by evaluating X. X can be : + * - another type of array, array_view, matrix,.... (any pair) + * - a expression : e.g. array > A( B+ 2*C); + * - ml : useless directly, since there only one ml, but used in generic code it maintains the same constructor as array, matrix + */ + template + //vector(const T & X, typename boost::enable_if< ImmutableArray >::type *dummy =0): + vector(const T & X, TYPE_ENABLE_IF(memory_layout<1>, ImmutableArray) ml = memory_layout<1>(IMPL_TYPE::indexmap_type::traversal_order)): + IMPL_TYPE(indexmap_type(X.domain(),ml)) { triqs_arrays_assign_delegation(*this,X); } + +#ifdef TRIQS_WITH_PYTHON_SUPPORT + ///Build from a numpy.array X (or any object from which numpy can make a numpy.array). Makes a copy. + explicit vector (PyObject * X): IMPL_TYPE(X, true, "vector "){} +#endif + + // build from a init_list + template + vector(std::initializer_list const & l): + IMPL_TYPE(indexmap_type(mini_vector(l.size()),memory_layout<1>(IMPL_TYPE::indexmap_type::traversal_order))) { + size_t i=0; + for (auto const & x : l) (*this)(i++) = x; + } + + /** + * Resizes the vector. NB : all references to the storage is invalidated. + * Does not initialize the vector by default: to resize and init, do resize(IND).init() + */ + vector & resize (size_t L) { IMPL_TYPE::resize(typename IMPL_TYPE::domain_type(mini_vector(L))); return *this; } + + /** + * Resizes the vector. NB : all references to the storage is invalidated. + * Does not initialize the vector by default: to resize and init, do resize(IND).init() + */ + vector & resize (const indexmaps::cuboid::domain_t & l) { IMPL_TYPE::resize(l); return *this; } + + /// Assignement resizes the vector. All references to the storage are therefore invalidated. + vector & operator=(const vector & X) { IMPL_TYPE::resize_and_clone_data(X); return *this; } + + /** + * Assignement resizes the vector. All references to the storage are therefore invalidated. + * NB : to avoid that, do make_view(A) = X instead of A = X + */ + template + vector & operator=(const RHS & X) { + static_assert( ImmutableArray::value, "Assignment : RHS not supported"); + IMPL_TYPE::resize(X.domain()); + triqs_arrays_assign_delegation(*this,X); + return *this; + } + + /// Move assignment + vector & operator=(vector && X) { this->swap_me(X); return *this;} + + /// Swap + friend void swap( vector & A, vector & B) { A.swap_me(B);} + + /// + size_t size() const { return this->shape()[0];} + + /// + std::ptrdiff_t stride() const { return this->indexmap().strides()[0];} + + TRIQS_DEFINE_COMPOUND_OPERATORS(vector); + + // to make interface similar to std::vector : forward [] to () + template typename std::result_of::type operator[](Arg && arg) const { return (*this) (std::forward(arg));} + template typename std::result_of::type operator[](Arg && arg) { return (*this) (std::forward(arg));} + //template auto operator[](Arg && arg) const DECL_AND_RETURN((*this)(std::forward(arg))); + //template auto operator[](Arg && arg) DECL_AND_RETURN((*this)(std::forward(arg))); + + };//vector class +}}//namespace triqs::arrays + +#undef IMPL_TYPE + +#include "./blas_lapack/scal.hpp" +#include "./blas_lapack/copy.hpp" +#include "./blas_lapack/swap.hpp" +#include "./blas_lapack/axpy.hpp" +namespace triqs { namespace arrays { + + // lexicographical comparison operators + template + typename std::enable_if< ImmutableVector::value && ImmutableVector::value , bool>::type + operator < (V1 const & a, V2 const & b) { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());} + + template + typename std::enable_if< ImmutableVector::value && ImmutableVector::value , bool>::type + operator > (V1 const & a, V2 const & b) { return (b + typename boost::enable_if< is_vector_or_view >::type + triqs_arrays_assign_delegation (vector & lhs, RHS const & rhs) { blas::copy(rhs,lhs); } + + template + typename boost::enable_if< is_vector_or_view >::type + triqs_arrays_compound_assign_delegation (vector & lhs, RHS const & rhs, mpl::char_<'A'>) { + T a = 1.0; blas::axpy(a,rhs,lhs); + } + + template + typename boost::enable_if< is_vector_or_view >::type + triqs_arrays_compound_assign_delegation (vector & lhs, RHS const & rhs, mpl::char_<'S'>) { + T a = -1.0; blas::axpy(a,rhs,lhs); + } + + template + typename boost::enable_if< is_scalar_for > >::type + triqs_arrays_compound_assign_delegation (vector & lhs, RHS const & rhs, mpl::char_<'M'>) { + T a = rhs; blas::scal(a,lhs); + } + + template + typename boost::enable_if< is_scalar_for > >::type + triqs_arrays_compound_assign_delegation (vector & lhs, RHS const & rhs, mpl::char_<'D'>) { + T a = 1/rhs; blas::scal(a,lhs); + } + + template + typename boost::enable_if< is_vector_or_view >::type + triqs_arrays_assign_delegation (vector_view & lhs, RHS const & rhs) { blas::copy(rhs,lhs); } + + template + typename boost::enable_if< is_vector_or_view >::type + triqs_arrays_compound_assign_delegation (vector_view & lhs, RHS const & rhs, mpl::char_<'A'>) { + T a = 1.0; blas::axpy(a,rhs,lhs); + } + + template + typename boost::enable_if< is_vector_or_view >::type + triqs_arrays_compound_assign_delegation (vector_view & lhs, RHS const & rhs, mpl::char_<'S'>) { + T a = -1.0; blas::axpy(a,rhs,lhs); + } + + template + typename boost::enable_if< is_scalar_for > >::type + triqs_arrays_compound_assign_delegation (vector_view & lhs, RHS const & rhs, mpl::char_<'M'>) { + T a = rhs; blas::scal(a,lhs); + } + + template + typename boost::enable_if< is_scalar_for > >::type + triqs_arrays_compound_assign_delegation (vector_view & lhs, RHS const & rhs, mpl::char_<'D'>) { + T a = 1/rhs; blas::scal(a,lhs); + } + + template + void triqs_arrays_assign_delegation(vector_view & av, std::vector const& vec) { + std::size_t size = vec.size(); + for(std::size_t n = 0; n < size; ++n) av(n) = vec[n]; + } + + // swapping 2 vector + template + void deep_swap(vector_view x, vector_view y) { + blas::swap(x,y); + } + + template + void deep_swap(vector & x, vector & y) { blas::swap(x,y);} + +}} + +// The std::swap is WRONG for a view because of the copy/move semantics of view. +// Use swap instead (the correct one, found by ADL). +namespace std { + template void swap( triqs::arrays::vector_view & a , triqs::arrays::vector_view & b)= delete; +} + +#include "./expression_template/vector_algebra.hpp" + +#endif + diff --git a/triqs/clef.hpp b/triqs/clef.hpp new file mode 100644 index 00000000..347f3f80 --- /dev/null +++ b/triqs/clef.hpp @@ -0,0 +1,5 @@ +#include "./clef/clef.hpp" +#include "./clef/io.hpp" +#include "./clef/adapters/vector.hpp" +#include "./clef/adapters/math.hpp" + diff --git a/triqs/clef/CMakeLists.txt b/triqs/clef/CMakeLists.txt new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/triqs/clef/CMakeLists.txt @@ -0,0 +1,2 @@ + + diff --git a/triqs/clef/adapters/math.hpp b/triqs/clef/adapters/math.hpp new file mode 100644 index 00000000..e824a4ac --- /dev/null +++ b/triqs/clef/adapters/math.hpp @@ -0,0 +1,40 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_CLEF_ADAPTER_MATH_H +#define TRIQS_CLEF_ADAPTER_MATH_H +#include "../clef.hpp" +#include +#include + +#define TRIQS_CLEF_STD_MATH_FNT_TO_MAKE_LAZY (cos)(sin)(tan)(cosh)(sinh)(tanh)(acos)(asin)(atan)(exp)(log)(sqrt)(abs)(floor)(pow) + +namespace triqs { namespace clef { + +#define TRIQS_CLEF_MAKE_STD_FNT_LAZY(name) using std::name; TRIQS_CLEF_MAKE_FNT_LAZY(name) +#define AUX(r, data, elem) TRIQS_CLEF_MAKE_STD_FNT_LAZY(elem) + BOOST_PP_SEQ_FOR_EACH(AUX , nil , TRIQS_CLEF_STD_MATH_FNT_TO_MAKE_LAZY); +#undef AUX +#undef TRIQS_CLEF_STD_MATH_FNT_TO_MAKE_LAZY + +}} + +#endif + diff --git a/triqs/clef/adapters/vector.hpp b/triqs/clef/adapters/vector.hpp new file mode 100644 index 00000000..e8fb98dc --- /dev/null +++ b/triqs/clef/adapters/vector.hpp @@ -0,0 +1,44 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_CLEF_VECTOR_ADAPTER_H +#define TRIQS_CLEF_VECTOR_ADAPTER_H +#include "../clef.hpp" +#include + +namespace triqs { namespace clef { + + template + void triqs_clef_auto_assign__std_vector_impl (T & x, RHS && rhs) { x = std::forward(rhs);} + + template< typename Expr, int... Is, typename T> + void triqs_clef_auto_assign__std_vector_impl (T &x, make_fun_impl && rhs) { triqs_clef_auto_assign_subscript( x, std::forward >(rhs)); } + + template + void triqs_clef_auto_assign_subscript (std::vector & v, Fnt f) { + for (size_t i=0; i std::ostream & triqs_clef_formal_print(std::ostream & out, std::vector const & x) { return out<<"std::vector";} + +}} + +#endif + diff --git a/triqs/clef/clef.hpp b/triqs/clef/clef.hpp new file mode 100644 index 00000000..82e153f9 --- /dev/null +++ b/triqs/clef/clef.hpp @@ -0,0 +1,429 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_CLEF_CORE_H +#define TRIQS_CLEF_CORE_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TRIQS_CLEF_MAXNARGS 8 + +namespace triqs { namespace clef { + typedef unsigned long long ull_t; + template struct remove_cv_ref : std::remove_cv< typename std::remove_reference::type> {}; + namespace tags { struct function_class{}; struct function{}; struct subscript{}; struct terminal{}; struct if_else{}; struct unary_op{}; struct binary_op{}; } + + /* --------------------------------------------------------------------------------------------------- + * Placeholder and corresponding traits + * --------------------------------------------------------------------------------------------------- */ + template struct pair { + static constexpr int p = i; + typedef typename remove_cv_ref ::type value_type; + value_type const & r; + value_type const & rhs() const { return r;} + pair (T const & t) : r(t){} + }; + + template struct placeholder { + static_assert( (N>=0) && (N<64) , "Placeholder number limited to [0,63]"); + static constexpr int index = N; + template pair operator = (RHS const & rhs) { return pair(rhs);} + }; + + template struct is_placeholder : std::false_type {}; + template struct is_placeholder > : std::true_type {}; + + template struct ph_set; + template struct ph_set{static constexpr ull_t value= ph_set::value| ph_set::value;}; + template struct ph_set {static constexpr ull_t value= 0;}; + template struct ph_set> {static constexpr ull_t value= 1ull< struct ph_set > : ph_set>{}; + + /* --------------------------------------------------------------------------------------------------- + * Detect if an object is a lazy expression + * --------------------------------------------------------------------------------------------------- */ + template struct is_any_lazy : std::false_type {}; + template struct is_any_lazy > : std::true_type {}; + template struct is_any_lazy< T > : std::false_type {}; + template struct is_any_lazy< T&& > : is_any_lazy {}; + template struct is_any_lazy< T& > : is_any_lazy {}; + template struct is_any_lazy< T const > : is_any_lazy {}; + template struct is_any_lazy : + std::integral_constant::value || is_any_lazy::value> {}; + + // a trait that checks the type are value i.e. no &, && + template struct has_no_ref : std::true_type {}; + template struct has_no_ref : std::integral_constant::value)&& has_no_ref::value> {}; + + /* --------------------------------------------------------------------------------------------------- + * Node of the expression tree + * --------------------------------------------------------------------------------------------------- */ + template struct expr { + static_assert( has_no_ref::value , "Internal error : expr childs can not be reference "); + typedef std::tuple< T ...> childs_t; + childs_t childs; + expr(expr const & x) = default; + expr(expr && x) : childs(std::move(x.childs)) {} + template explicit expr(Tag, Args&&...args) : childs(std::forward(args)...) {} + template< typename Args > + expr::type > operator[](Args && args) const + { return expr::type> (tags::subscript(), *this,std::forward(args));} + template< typename... Args > + expr::type...> operator()(Args && ... args) const + { return expr::type...>(tags::function(), *this,std::forward(args)...);} + // only f(i,j) = expr is allowed, in case where f is a clef::function + // otherwise use the << operator + template + typename std::enable_if::type>::value>::type + operator= (RHS const & rhs) { *this << rhs;} + template + typename std::enable_if::type>::value>::type + operator= (RHS const & rhs) = delete; + expr & operator= (expr const & ) = delete; // no ordinary copy + }; + template struct ph_set< expr > : ph_set {}; + template struct is_any_lazy< expr >: std::true_type {}; + + /* --------------------------------------------------------------------------------------------------- + * The basic operations put in a template.... + * --------------------------------------------------------------------------------------------------- */ + template struct operation; + + /// Terminal + template<> struct operation { template L operator()(L&& l) const { return std::forward(l);} }; + + /// Function call + template<> struct operation { + template auto operator()(F const & f, Args const & ... args) const -> decltype(f(args...)) { return f(args...);} + template auto operator()(std::reference_wrapper const &f, Args const & ... args) const -> decltype(f.get()(args...)) { return f.get()(args...);} + }; + + /// [ ] Call + template<> struct operation { + template auto operator()(F const & f, Args const & args) const -> decltype(f[args]) { return f[args];} + template auto operator()(std::reference_wrapper const &f, Args const & args) const -> decltype(f.get()[args]) { return f.get()[args];} + }; + + // all binary operators.... +#define TRIQS_CLEF_OPERATION(TAG,OP)\ + namespace tags { struct TAG : binary_op { static const char * name() { return BOOST_PP_STRINGIZE(OP);} };}\ + template<> struct operation {\ + template auto operator()(L const & l, R const & r) const -> decltype(l OP r) { return l OP r;}\ + };\ + template\ + typename std::enable_if::value, expr::type,typename remove_cv_ref::type> >::type \ + operator OP (L && l, R && r) { return expr::type,typename remove_cv_ref::type> (tags::TAG(),std::forward(l),std::forward(r));}\ + + TRIQS_CLEF_OPERATION(plus, +); + TRIQS_CLEF_OPERATION(minus, -); + TRIQS_CLEF_OPERATION(multiplies, *); + TRIQS_CLEF_OPERATION(divides, /); + TRIQS_CLEF_OPERATION(greater, >); + TRIQS_CLEF_OPERATION(less, <); + TRIQS_CLEF_OPERATION(leq, <=); + TRIQS_CLEF_OPERATION(geq, >=); + TRIQS_CLEF_OPERATION(eq, ==); +#undef TRIQS_CLEF_OPERATION + + // all unary operators.... +#define TRIQS_CLEF_OPERATION(TAG,OP)\ + namespace tags { struct TAG : unary_op { static const char * name() { return BOOST_PP_STRINGIZE(OP);} };}\ + template<> struct operation {\ + template auto operator()(L const & l) const -> decltype(OP l) { return OP l;}\ + };\ + template\ + typename std::enable_if::value, expr::type> >::type \ + operator OP (L && l) { return expr::type> (tags::TAG(),std::forward(l));}\ + + TRIQS_CLEF_OPERATION(negate, -); + TRIQS_CLEF_OPERATION(loginot, !); +#undef TRIQS_CLEF_OPERATION + + /// the only ternary node : expression if + template<> struct operation { + template auto operator()(C const & c, A const & a, B const & b) const -> decltype((c?a:b)) { + //static_assert(std::is_same::type,typename remove_cv_ref::type>::value, "Expression if : evaluation type must be the same"); + return (c ? a: b); + } + }; + // operator is : if_else( Condition, A, B) + template + expr::type,typename remove_cv_ref::type,typename remove_cv_ref::type> + if_else(C && c, A && a, B && b) { + return expr::type,typename remove_cv_ref::type,typename remove_cv_ref::type> + (tags::if_else(),std::forward(c),std::forward(a),std::forward(b));} + + /* --------------------------------------------------------------------------------------------------- + * Evaluation of the expression tree. + * --------------------------------------------------------------------------------------------------- */ + + template struct operation2; + template struct operation2 { + typedef expr::type ...> rtype; + rtype operator()(Args && ... args) const {return rtype (Tag(), std::forward(args)...);} + }; + template struct operation2 { + typedef typename std::remove_reference(Args...)>::type>::type rtype; + // remove the reference because of ternary if_else in which decltype returns a ref... + rtype operator()(Args const & ... args) const {return operation()(args...); } + }; + + // Generic case : do nothing (for the leaf of the tree except placeholder) + template struct evaluator{ + typedef T rtype; + rtype operator()( T const & k, Pairs const &... pairs) {return k;} + }; + + // placeholder + template struct evaluator< placeholder, pair, Pairs... > { + typedef evaluator< placeholder, Pairs...> eval_t; + typedef typename eval_t::rtype rtype; + rtype operator()(placeholder, pair const &, Pairs const& ... pairs) { return eval_t()(placeholder(), pairs...);} + }; + template struct evaluator< placeholder, pair, Pairs... > { + typedef typename pair::value_type const & rtype; + rtype operator()(placeholder, pair const & p, Pairs const& ...) { return p.r;} + }; + + // general expr node + template struct evaluator, Pairs...> { + typedef operation2::rtype... >::value, typename evaluator::rtype... > OPTYPE; + typedef typename OPTYPE::rtype rtype; +#define AUX(z,p,unused) eval(std::get

    (ex.childs),pairs...) +#define IMPL(z, NN, unused) \ + template< int arity = sizeof...(Childs)>\ + typename std::enable_if< arity==NN, rtype>::type\ + operator()(expr const & ex, Pairs const & ... pairs) const\ + { return OPTYPE()(BOOST_PP_ENUM(NN,AUX,nil));} + BOOST_PP_REPEAT_FROM_TO(1,BOOST_PP_INC(TRIQS_CLEF_MAXNARGS), IMPL, nil); +#undef AUX +#undef IMPL + }; + + // The general eval function for expressions + template + typename evaluator::rtype + eval (T const & ex, Pairs const &... pairs) { return evaluator()(ex, pairs...); } + +#ifdef TRIQS_SHORT_CIRCUIT_NOT_IMPLEMENTED + // A short circuit if intersection of ph and is 0, no need to evaluate the whole tree...... + template + template + typename std::enable_if< (ph_set::value & ph_set::value) !=0, typename evaluator,Pairs...>::rtype > ::type + eval (expr const & ex, Pairs const &... pairs) { return evaluator, Pairs...>()(ex, pairs...); } + + template + typename std::enable_if< (ph_set::value & ph_set::value) ==0, expr > ::type + eval (expr const & ex, Pairs const &... pairs) { return ex; } +#endif + + /* --------------------------------------------------------------------------------------------------- + * make_function : transform an expression to a function + * --------------------------------------------------------------------------------------------------- */ + + template< typename Expr, int... Is> struct make_fun_impl { + Expr ex; // keep a copy of the expression + make_fun_impl(Expr const & ex_) : ex(ex_) {} + + // gcc 4.6 crashes (!!!) on the first variant +#define TRIQS_WORKAROUND_GCC46BUG +#ifndef TRIQS_WORKAROUND_GCC46BUG + template + typename evaluator...>::rtype + operator()(Args const &... args) const + { return evaluator...>() ( ex, pair(args)...); } +#else + template struct __eval { + typedef evaluator...> eval_t; + typedef typename eval_t::rtype rtype; + rtype operator()(Expr const &ex , Args const &... args) const { return eval_t() ( ex, pair(args)...); } + }; + template + typename __eval::rtype operator()(Args const &... args) const { return __eval() ( ex, args...); } +#endif + }; + + template struct ph_filter; + template struct ph_filter { static constexpr ull_t value = ph_filter::value & (~ (1ull< struct ph_filter { static constexpr ull_t value = x; }; + + template< typename Expr, int... Is> struct ph_set > { static constexpr ull_t value = ph_filter ::value, Is...>::value;}; + template< typename Expr, int... Is> struct is_any_lazy > : std::integral_constant>::value !=0>{}; + + template< typename Expr, int... Is,typename... Pairs> struct evaluator, Pairs...> { + typedef evaluator e_t; + typedef make_fun_impl rtype; + rtype operator()(make_fun_impl const & f, Pairs const & ... pairs) const { return rtype( e_t()(f.ex, pairs...));} + }; + + template< typename Expr, typename ... Phs> + make_fun_impl::type>::type,Phs::index...> + make_function(Expr && ex, Phs...) { return {ex}; } + + namespace result_of { + template< typename Expr, typename ... Phs> struct make_function { + typedef make_fun_impl::type>::type,Phs::index...> type; + }; + } + + /* -------------------------------------------------------------------------------------------------- + * make_function + * x_ >> expression is the same as make_function(expression,x) + * --------------------------------------------------------------------------------------------------- */ + + template + make_fun_impl operator >> ( placeholder p, Expr&& ex) { return {ex}; } + + /* --------------------------------------------------------------------------------------------------- + * Auto assign for () + * --------------------------------------------------------------------------------------------------- */ + + // by default it is deleted = not implemented : every class has to define it... + template void triqs_clef_auto_assign (T,F) = delete; + + // remove the ref_wrapper, terminal ... + template void triqs_clef_auto_assign (std::reference_wrapper R ,F && f) { triqs_clef_auto_assign(R.get(),std::forward(f));} + template void triqs_clef_auto_assign (expr const & t,F && f) { triqs_clef_auto_assign(std::get<0>(t.childs),std::forward(f));} + + // auto assign of an expr ? (for chain calls) : just reuse the same operator + template + void triqs_clef_auto_assign (expr && ex, RHS const & rhs) { ex << rhs;} + + template + void triqs_clef_auto_assign (expr const & ex, RHS const & rhs) { ex << rhs;} + + // The case A(x_,y_) = RHS : we form the function (make_function) and call auto_assign (by ADL) + template + void operator<<(expr...> && ex, RHS && rhs) { + triqs_clef_auto_assign(std::get<0>(ex.childs), make_function(std::forward(rhs), placeholder()...)); + } + template + void operator<<(expr...> const & ex, RHS && rhs) { + triqs_clef_auto_assign(std::get<0>(ex.childs), make_function(std::forward(rhs), placeholder()...)); + } + + // any other case e.g. f(x_+y_) = RHS etc .... which makes no sense : compiler will stop + template + void operator<<(expr && ex, RHS && rhs) = delete; + template + void operator<<(expr const & ex, RHS && rhs) = delete; + + /* --------------------------------------------------------------------------------------------------- + * Auto assign for [] + * --------------------------------------------------------------------------------------------------- */ + + // by default it is deleted = not implemented : every class has to define it... + template void triqs_clef_auto_assign_subscript (T,F) = delete; + + // remove the ref_wrapper, terminal ... + template void triqs_clef_auto_assign_subscript (std::reference_wrapper R ,F && f) + { triqs_clef_auto_assign_subscript(R.get(),std::forward(f));} + template void triqs_clef_auto_assign_subscript (expr const & t,F && f) + { triqs_clef_auto_assign_subscript(std::get<0>(t.childs),std::forward(f));} + + // auto assign of an expr ? (for chain calls) : just reuse the same operator + template + void triqs_clef_auto_assign_subscript (expr const & ex, RHS const & rhs) { ex << rhs;} + + // Same thing for the [ ] + template + void operator<<(expr...> const & ex, RHS && rhs) { + triqs_clef_auto_assign_subscript(std::get<0>(ex.childs), make_function(std::forward(rhs), placeholder()...)); + } + template + void operator<<(expr const & ex, RHS && rhs) = delete; + + /* -------------------------------------------------------------------------------------------------- + * Create a terminal node of an object. The reference is wrapped in a reference_wrapper... + * --------------------------------------------------------------------------------------------------- */ + + template expr::type > + make_expr(T && x){ return expr::type >(tags::terminal(), std::forward(x));} + + template auto lazy (T && x) -> decltype (make_expr(std::ref(x))) { return make_expr(std::ref(x)); } + + /* -------------------------------------------------------------------------------------------------- + * Create a call node of an object + * The object can be kept as a : a ref, a copy, a view + * --------------------------------------------------------------------------------------------------- */ + + namespace result_of { + template< typename Obj, typename... Args > struct make_expr_call : + std::enable_if< is_any_lazy::value, expr::type, typename remove_cv_ref::type ...> > {}; + } + template< typename Obj, typename... Args > + typename result_of::make_expr_call::type + make_expr_call(Obj&& obj, Args &&... args) + { return typename result_of::make_expr_call::type (tags::function(),std::forward(obj), std::forward(args)...);} + + /* -------------------------------------------------------------------------------------------------- + * function class : stores any expression polymorphically + * f(x_,y_ ) = an expression associates this expression dynamically to f, which + * can then be used as a std::function of the same signature... + * --------------------------------------------------------------------------------------------------- */ + template class function; + + template class function : tags::function_class { + typedef std::function std_function_type; + mutable std::shared_ptr _exp; // CLEAN THIS MUTABLE ? + mutable std::shared_ptr < std_function_type > _fnt_ptr; + public: + function():_fnt_ptr(new std_function_type ()){} + + template + explicit function(Expr const & _e, X... x) : _exp(new Expr(_e)),_fnt_ptr(new std_function_type(make_function(_e, x...))){} + + ReturnType operator()(T const &... t) const { return (*_fnt_ptr)(t...);} + + template< typename... Args> + typename triqs::clef::result_of::make_expr_call::type + operator()( Args&&... args ) const { return triqs::clef::make_expr_call (*this,args...);} + + template friend void triqs_clef_auto_assign (function const & x, RHS rhs) { + * (x._fnt_ptr) = std_function_type (rhs); + x._exp = std::shared_ptr (new typename std::remove_cv::type (rhs.ex)); + } + + }; + /* -------------------------------------------------------------------------------------------------- + * The macro to make any function lazy + * TRIQS_CLEF_MAKE_FNT_LAZY (Arity,FunctionName ) : creates a new function in the triqs::lazy namespace + * taking expressions (at least one argument has to be an expression) + * The lookup happens by ADL, so IT MUST BE USED IN THE triqs::lazy namespace + * --------------------------------------------------------------------------------------------------- */ +#define TRIQS_CLEF_MAKE_FNT_LAZY(name)\ + struct name##_lazy_impl { \ + template auto operator()(A&&... a) const -> decltype (name(std::forward(a)...)) { return name(std::forward(a)...); }\ + };\ + template< typename... A> \ + typename triqs::clef::result_of::make_expr_call::type name( A&& ... a) { return make_expr_call(name##_lazy_impl(),a...);} + +}} // namespace triqs::clef + +#endif diff --git a/triqs/clef/io.hpp b/triqs/clef/io.hpp new file mode 100644 index 00000000..c1204b56 --- /dev/null +++ b/triqs/clef/io.hpp @@ -0,0 +1,87 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_CLEF_IO_H +#define TRIQS_CLEF_IO_H +#include "../clef.hpp" +#include + +namespace triqs { namespace clef { + + /* --------------------------------------------------------------------------------------------------- + * Printing of the expressions + * --------------------------------------------------------------------------------------------------- */ + + template std::ostream &operator <<(std::ostream &sout, placeholder ){return sout << "_"< std::ostream & operator<<(std::ostream & out, std::reference_wrapper const & x) { return out<< x.get(); } + + inline std::ostream & variadic_print(std::ostream& out) { return out; } + template std::ostream & variadic_print(std::ostream& out, T0&& t0, T&&... t) + { out<< t0<<( sizeof...(T)>0 ? ", ": ""); variadic_print (out, t...); return out;} + + template struct print_tuple_impl { + template void operator() (std::ostream& out, Tuple const & t) { out << std::get(t) << (c!=m-1 ? ", ": ""); print_tuple_impl()(out, t); } + }; + template struct print_tuple_impl { + template void operator() (std::ostream& out, Tuple const & t) {} + }; + template std::ostream & print_tuple(std::ostream& out, Tuple const & t) { + print_tuple_impl<1,std::tuple_size::value>()(out,t); return out; + } + template + typename std::enable_if::value, std::ostream &>::type + operator <<(std::ostream &sout, expr const &ex){ + return sout << "("<< Tag::name() <<" "<(ex.childs)<<")" ; + } + template + typename std::enable_if::value, std::ostream &>::type + operator <<(std::ostream &sout, expr const &ex){ + return sout << "("<(ex.childs) <<" "<< Tag::name() <<" "<(ex.childs)<<")" ; + } + template std::ostream &operator <<(std::ostream &sout, expr const &ex){ + return sout << "(" << std::get<0>(ex.childs) << "?"<< std::get<1>(ex.childs) <<" : "<< std::get<2>(ex.childs) <<")"; + } + template std::ostream &operator <<(std::ostream &sout, expr const &ex){ + sout << std::get<0>(ex.childs) << "("; print_tuple(sout,ex.childs); return sout<<")" ; + } + template std::ostream &operator <<(std::ostream &sout, expr const &ex){ + sout << std::get<0>(ex.childs) << "["; print_tuple(sout,ex.childs); return sout<<"]" ; + } + + template std::ostream &operator <<(std::ostream &sout, + expr const &ex) {return sout << std::get<0>(ex.childs) ; } + + template std::ostream &operator <<(std::ostream &sout, + expr const &ex) {return sout << std::get<0>(ex.childs) << "["<(ex.childs)<<"]" ; } + + template std::ostream &operator <<(std::ostream &sout, + expr const &ex) {return sout << "-("<(ex.childs) <<")" ; } + + template< typename Expr, int... Is> + std::ostream &operator <<(std::ostream &sout, make_fun_impl const & x) { + sout << "lazy function : ("; variadic_print(sout, placeholder()...); return sout<< ") --> "<< x.ex ; + } + + template std::ostream & operator<<(std::ostream & out, function const & x) { return out<<"function ";} + +}} + +#endif + diff --git a/triqs/det_manip/CMakeLists.txt b/triqs/det_manip/CMakeLists.txt new file mode 100644 index 00000000..d03ef558 --- /dev/null +++ b/triqs/det_manip/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../) + + diff --git a/triqs/det_manip/det_manip.hpp b/triqs/det_manip/det_manip.hpp new file mode 100644 index 00000000..c0dea051 --- /dev/null +++ b/triqs/det_manip/det_manip.hpp @@ -0,0 +1,819 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_DETMANIP_H +#define TRIQS_DETMANIP_H +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace triqs { namespace det_manip { + + /** + * \brief Standard matrix/det manipulations used in several QMC. + */ + template + class det_manip { + private: + typedef utility::function_arg_ret_type f_tr; + static_assert(f_tr::arity == 2, "det_manip : the function must take two arguments !"); + // Do we REALLY need this ? + static_assert(std::is_same< typename f_tr::template decay_arg<0>::type, typename f_tr::template decay_arg<1>::type>::value, + "det_manip : the two arguments must of the function must have the same type"); + public: + + typedef typename f_tr::template decay_arg<0>::type xy_type; + typedef typename f_tr::result_type value_type; + static_assert( std::is_floating_point::value || boost::is_complex::value, "det_manip : the function must return a floating number or a complex number"); + + typedef arrays::vector vector_type; + typedef arrays::matrix matrix_type; + typedef arrays::matrix_view matrix_view_type; + + protected: // the data + typedef std::ptrdiff_t int_type; + typedef arrays::range range; + + FunctionType f; + + // serialized data. There are all VALUES. + value_type det; + size_t Nmax,N, last_try; + std::vector row_num,col_num; + std::vector x_values,y_values; + int sign; + matrix_type mat_inv; + long long n_opts, n_opts_max_before_check; + + private: + // ------------ BOOST Serialization ------------ + // What about f ? Not serialized at the moment. + friend class boost::serialization::access; + template + void serialize(Archive & ar) { + using boost::serialization::make_nvp; + ar & make_nvp("Nmax",Nmax) & make_nvp("N",N) + & make_nvp("n_opts",n_opts) & make_nvp("n_opts_max_before_check",n_opts_max_before_check) + & make_nvp("det",det) & make_nvp("sign",sign) + & make_nvp("Minv",mat_inv) + & make_nvp("row_num",row_num) & make_nvp("col_num",col_num) + & make_nvp("x_values",x_values) & make_nvp("y_values",y_values); + } + + /// Write into HDF5 + friend void h5_write (h5::group fg, std::string subgroup_name, det_manip const & g) { + auto gr = fg.create_group(subgroup_name); + h5_write(gr,"N",g.N); + h5_write(gr,"mat_inv",g.mat_inv); + h5_write(gr,"det",g.det); + h5_write(gr,"sign",g.sign); + //h5_write(gr,"row_num",g.row_num); + //h5_write(gr,"col_num",g.col_num); + h5_write(gr,"x_values",g.x_values); + h5_write(gr,"y_values",g.y_values); + h5_write(gr,"n_opts",g.n_opts); + h5_write(gr,"n_opts_max_before_check",g.n_opts_max_before_check); + } + + /// Read from HDF5 + friend void h5_read (h5::group fg, std::string subgroup_name, det_manip & g){ + auto gr = fg.open_group(subgroup_name); + h5_read(gr,"N",g.N); + h5_read(gr,"mat_inv",g.mat_inv); + g.Nmax = g.mat_inv.dim0(); // restore Nmax + g.last_try = 0; + h5_read(gr,"det",g.det); + h5_read(gr,"sign",g.sign); + //h5_read(gr,"row_num",g.row_num); + //h5_read(gr,"col_num",g.col_num); + h5_read(gr,"x_values",g.x_values); + h5_read(gr,"y_values",g.y_values); + h5_read(gr,"n_opts",g.n_opts); + h5_read(gr,"n_opts_max_before_check",g.n_opts_max_before_check); + } + + private: + // temporary work data, not saved, serialized, etc.... + struct work_data_type1 { + xy_type x, y; + vector_type MB,MC, B, C; + value_type ksi; + size_t i,j,ireal,jreal; + void reserve(size_t s) { B.resize(s); C.resize(s); MB.resize(s); MC.resize(s); MB()=0; MC()=0; } + }; + + struct work_data_type2 { + xy_type x[2], y[2]; + matrix_type MB,MC, B, C,ksi; + size_t i[2],j[2],ireal[2],jreal[2]; + void reserve(size_t s) { MB.resize(s,2); MC.resize(2,s); B.resize(s,2), C.resize(2,s); ksi.resize(2,2); MB() = 0; MC() = 0; } + value_type det_ksi() const { return ksi(0,0) * ksi(1,1) - ksi(1,0)* ksi(0,1);} + }; + + work_data_type1 w1; + work_data_type2 w2; + value_type newdet; + int newsign; + + private: // for the move constructor, I need to separate the swap since f may not be defaulted constructed + void swap_but_f (det_manip & rhs) noexcept { + using std::swap; +#define SW(a) swap(this->a,rhs.a) + SW(det);SW(Nmax);SW(N); SW(last_try); + SW(row_num); SW(col_num); + SW(x_values); SW(y_values); + SW(sign); SW(mat_inv); SW(n_opts); SW(n_opts_max_before_check); + SW(w1); SW(w2); SW(newdet); SW(newsign); +#undef SW + } + + friend void swap(det_manip& lhs, det_manip & rhs) noexcept { + using std::swap; + swap(lhs.f, rhs.f); + lhs.swap_but_f(rhs); + } + + public: + + /** + * Like for std::vector, reserve memory for a bigger size. + * Preserves only the matrix, not the temporary working vectors/matrices, so do NOT use it + * between a try_XXX and acomplete_operation + */ + void reserve (size_t new_size) { + if (new_size <= Nmax) return; + matrix_type Mcopy(mat_inv); + size_t N0 = Nmax; Nmax = new_size; + mat_inv.resize(Nmax,Nmax); mat_inv(range(0,N0), range(0,N0)) = Mcopy; // keep the content of mat_inv ---> into the lib ? + row_num.reserve(Nmax);col_num.reserve(Nmax); x_values.reserve(Nmax);y_values.reserve(Nmax); + w1.reserve(Nmax); w2.reserve(Nmax); + } + + private: + void _construct_common() { + last_try=0; sign =1; + n_opts=0; n_opts_max_before_check = 100; + } + + public: + /** + * \brief Constructor. + * + * \param F The function (NB : a copy is made of the F object in this class). + * \param init_size The maximum size of the matrix before a resize (like reserve in std::vector). + * Like std::vector, resize is automatic (by a factor 2) but can yield a performance penalty + * if it happens too often. + */ + det_manip(FunctionType F,size_t init_size): + f(std::move(F)), Nmax(0) , N(0){ + reserve(init_size); + mat_inv()=0; + det = 1; + _construct_common(); + } + + /** \brief Constructor. + * + * \param F The function (NB : a copy is made of the F object in this class). + * \tparam ArgumentContainer + * \param X, Y : container for X,Y. + */ + template + det_manip(FunctionType F, ArgumentContainer1 const & X, ArgumentContainer2 const & Y) : f(std::move(F)) { + if (X.size() != Y.size()) TRIQS_RUNTIME_ERROR<< " X.size != Y.size"; + _construct_common(); + N =X.size(); + if (N==0) { det = 1; reserve(30); return;} + if (N>Nmax) reserve(2*N); // put some margin.. + std::copy(X.begin(),X.end(), std::back_inserter(x_values)); + std::copy(Y.begin(),Y.end(), std::back_inserter(y_values)); + mat_inv()=0; + for (size_t i=0; iswap_but_f(rhs);} // f need not have a default constructor and we dont swap the temp data... + //det_manip& operator=(const det_manip&) = default; + det_manip& operator=(const det_manip&) = delete; + det_manip& operator=(det_manip&& rhs) noexcept { assert((last_try==0)&&(rhs.last_try==0)); swap(*this,rhs); return *this; } + + /// Put to size 0 : like a vector + void clear () { + N = 0; sign = 1;det =1; last_try = 0; + row_num.clear(); col_num.clear(); x_values.clear(); y_values.clear(); + } + + //----------------------- READ ACCESS TO DATA ---------------------------------- + + /// Current size of the matrix + size_t size() const { return N;} + + /// Returns the i-th values of x + xy_type const & get_x(size_t i) const { return x_values[row_num[i]];} + + /// Returns the j-th values of y + xy_type const & get_y(size_t j) const { return y_values[col_num[j]];} + + /** det M of the current state of the matrix. */ + value_type determinant() const {return sign*det;} + + /** Returns M^{-1}(i,j) */ + value_type inverse_matrix(size_t i,size_t j) const {return mat_inv(col_num[i],row_num[j]);} // warning : need to invert the 2 permutations. + + /// Returns the inverse matrix. Warning : this is slow, since it create a new copy, and reorder the lines/cols + matrix_view_type inverse_matrix() const { + matrix_type res(N,N); + for (size_t i=0; i + friend void foreach(det_manip const & d, LambdaType const & f) { + //for (size_t i=0; i=0); assert(j>=0); + if (N==Nmax) reserve(2*Nmax); + last_try = 1; + w1.i=i; w1.j=j; w1.x=x; w1.y = y; + + // treat empty matrix separately + if (N==0) { newdet = f(x,y); newsign = 1; return newdet; } + + // I add the row and col and the end. If the move is rejected, + // no effect since N will not be changed : Minv(i,j) for i,j>=N has no meaning. + for (size_t k= 0; k< N; k++) { + w1.B(k) = f(x_values[k],y); + w1.C(k) = f(x, y_values[k]); + } + range R(0,N); + w1.MB(R) = mat_inv(R,R) * w1.B(R);// CHANGE + w1.ksi = f(x,y) - arrays::dot( w1.C(R) , w1.MB(R) ); + newdet = det*w1.ksi; + newsign = ((i + j)%2==0 ? sign : -sign); // since N-i0 + N-j0 = i0+j0 [2] + return (newdet/det)*(newsign*sign); // sign is unity, hence 1/sign == sign + } + + //------------------------------------------------------------------------------------------ + private : + + void complete_insert () { + // store the new value of x,y. They are seen through the same permutations as rows and cols resp. + x_values.push_back(w1.x); y_values.push_back(w1.y); + row_num.push_back(0); col_num.push_back(0); + + // special empty case again + if (N==0) { N=1; mat_inv(0,0) = 1/newdet; return; } + + range R1(0,N); + w1.MC(R1) = mat_inv(R1,R1).transpose() * w1.C(R1); //CHANGE + w1.MC(N) = -1; + w1.MB(N) = -1; + + N++; + + // keep the real position of the row/col + // since we insert a col/row, we have first to push the col at the right + // and then say that col w1.i is stored in N, the last col. + // same for rows + for (int_type i =N-2; i>=int_type(w1.i); i--) row_num[i+1]= row_num[i]; + row_num[w1.i] = N-1; + for (int_type i =N-2; i>=int_type(w1.j); i--) col_num[i+1]= col_num[i]; + col_num[w1.j] = N-1; + + // Minv is ok, we need to complete + w1.ksi = 1/w1.ksi; + + // compute the change to the inverse + // M += w1.ksi w1.MB w1.MC with BLAS. first put the 0 + range R(0,N); + mat_inv(R,N-1) = 0; + mat_inv(N-1,R) = 0; + mat_inv(R,R) += triqs::arrays::a_x_ty(w1.ksi, w1.MB(R) ,w1.MC(R)) ;//mat_inv(R,R) += w1.ksi* w1.MB(R) * w1.MC(R)// CHANGE + } + + public : + //------------------------------------------------------------------------------------------ + + /** + * Double Insert operation at colum j0,j1 and row i0,i1. + * + * The operation consists in adding : + * * a column f(x_i, y_{j0}) + * * and a row f(x_{i0}, x_j) + * The new colum/row will be at col j0, row i0. + * + * 0 <= i0,i1,j0,j1 <= N+1, where N is the current size of the matrix. + * Returns the ratio of det Minv_new / det Minv. + * This routine does NOT make any modification. It has to be completed with complete_operation(). + */ + + value_type try_insert2(size_t i0, size_t i1, size_t j0, size_t j1, xy_type const & x0, xy_type const & x1, xy_type const & y0, xy_type const & y1) { + // check input and store it for complete_operation + assert(i0!=i1); assert(j0!=j1);assert(i0<=N); assert(j0<=N); assert(i0>=0); assert(j0>=0); + assert(i1<=N+1); assert(j1<=N+1); assert(i1>=0); assert(j1>=0); + + if (N >= Nmax) reserve(2*Nmax); // check this resize ... we add 2 lines + last_try = 10; + w2.i[0]=i0;w2.i[1]=i1; w2.j[0]=j0;w2.j[1]=j1; + w2.x[0] = x0;w2.y[0] = y0; w2.x[1] = x1;w2.y[1] = y1; + + // w1.ksi = Delta(x_values,y_values) - Cw.MB using BLAS + w2.ksi(0,0) = f(x0,y0); + w2.ksi(0,1) = f(x0,y1); + w2.ksi(1,0) = f(x1,y0); + w2.ksi(1,1) = f(x1,y1); + + // treat empty matrix separately + if (N==0) { + newdet = w2.det_ksi(); + newsign = 1; + return newdet; + } + + // I add the rows and cols and the end. If the move is rejected, + // no effect since N will not be changed : inv_mat(i,j) for i,j>=N has no meaning. + for (size_t k= 0; k< N; k++) { + w2.B(k,0) = f(x_values[k],y0); + w2.B(k,1) = f(x_values[k],y1); + w2.C(0,k) = f(x0, y_values[k]); + w2.C(1,k) = f(x1, y_values[k]); + } + range R(0,N), R2(0,2); + w2.MB(R,R2) = mat_inv(R,R) * w2.B(R,R2); // CHANGE + w2.ksi -= w2.C (R2, R) * w2.MB(R, R2); // CHANGE + newdet = det * w2.det_ksi(); + newsign = ((i0 + j0 + i1 + j1)%2==0 ? sign : -sign); // since N-i0 + N-j0 + N + 1 -i1 + N+1 -j1 = i0+j0 [2] + return (newdet/det)*(newsign*sign); // sign is unity, hence 1/sign == sign + } + + //------------------------------------------------------------------------------------------ + private: + void complete_insert2 () { + // store the new value of x,y. They are seen through the same permutations as rows and cols resp. + for (int k=0; k<2; ++k) { + x_values.push_back(w2.x[k]); y_values.push_back(w2.y[k]); + row_num.push_back(0); col_num.push_back(0); + } + + range R2(0,2); + if (N==0) {N=2; mat_inv(R2,R2)=inverse(w2.ksi); row_num[w2.i[1]]=1; col_num[w2.j[1]]=1; return;} + + range Ri(0,N); + w2.MC(R2,Ri) = w2.C(R2,Ri) * mat_inv(Ri,Ri);// CHANGE + w2.MC(R2, range(N, N+2) ) = -1; // identity matrix + w2.MB(range(N,N+2), R2 ) = -1; // identity matrix ! + + // keep the real position of the row/col + // since we insert a col/row, we have first to push the col at the right + // and then say that col w2.i[0] is stored in N, the last col. + // same for rows + for (int k =0; k<2; ++k) { + N++; + for (int_type i =N-2; i>=int_type(w2.i[k]); i--) row_num[i+1]= row_num[i]; + row_num[w2.i[k]] = N-1; + for (int_type i =N-2; i>=int_type(w2.j[k]); i--) col_num[i+1]= col_num[i]; + col_num[w2.j[k]] = N-1; + } + w2.ksi = inverse (w2.ksi); + range R(0,N); + mat_inv(R,range(N-2,N)) = 0; + mat_inv(range(N-2,N),R) = 0; + mat_inv(R,R) += w2.MB(R,R2) * (w2.ksi * w2.MC(R2,R)); // CHANGE + } + + public: + //------------------------------------------------------------------------------------------ + + /** + * Consider the removal the colj0 and row i0 from the matrix. + * + * Returns the ratio of det Minv_new / det Minv. + * This routine does NOT make any modification. It has to be completed with complete_operation(). + */ + value_type try_remove(size_t i, size_t j){ + assert(i=0); assert(j>=0); + w1.i=i;w1.j=j;last_try = 2; + w1.jreal = col_num[w1.j]; + w1.ireal = row_num[w1.i]; + // compute the newdet + // first we resolve the w1.ireal,w1.jreal, with the permutation of the Minv, then we pick up what + // will become the 'corner' coefficient, if the move is accepted, after the exchange of row and col. + w1.ksi = mat_inv(w1.jreal,w1.ireal); + newdet = det*w1.ksi; + newsign = ((i + j)%2==0 ? sign : -sign); + return (newdet/det)*(newsign*sign); // sign is unity, hence 1/sign == sign + } + //------------------------------------------------------------------------------------------ + private: + void complete_remove() { + if (N==1) { clear(); return; } + + // repack the matrix inv_mat + // swap the rows w1.ireal and N, w1.jreal and N in inv_mat + // Remember that for M row/col is interchanged by inversion, transposition. + { + range R(0,N); + if (w1.jreal !=N-1){ + arrays::deep_swap( mat_inv(w1.jreal,R), mat_inv(N-1,R)); + y_values[w1.jreal] = y_values[N-1]; + } + + if (w1.ireal !=N-1){ + arrays::deep_swap (mat_inv(R,w1.ireal), mat_inv(R,N-1)); + x_values[w1.ireal] = x_values[N-1]; + } + } + + N--; + + // M <- a - d^-1 b c with BLAS + w1.ksi = - 1/mat_inv(N,N); + range R(0,N); + + mat_inv(R,R) += arrays::a_x_ty(w1.ksi,mat_inv(R,N),mat_inv(N,R)); + + // modify the permutations + for (size_t k =w1.i; k=2); assert(i0!=i1); assert(j0!=j1); + assert(i0=0); assert(j0>=0); + assert(i1=0); assert(j1>=0); + + last_try =11; + + w2.i[0]=std::min(i0,i1); + w2.i[1]=std::max(i0,i1); + w2.j[0]=std::min(j0,j1); + w2.j[1]=std::max(j0,j1); + w2.ireal[0] = row_num[w2.i[0]]; + w2.ireal[1] = row_num[w2.i[1]]; + w2.jreal[0] = col_num[w2.j[0]]; + w2.jreal[1] = col_num[w2.j[1]]; + + // compute the newdet + w2.ksi(0,0) = mat_inv(w2.jreal[0],w2.ireal[0]); + w2.ksi(1,0) = mat_inv(w2.jreal[1],w2.ireal[0]); + w2.ksi(0,1) = mat_inv(w2.jreal[0],w2.ireal[1]); + w2.ksi(1,1) = mat_inv(w2.jreal[1],w2.ireal[1]); + + newdet = det * w2.det_ksi(); + newsign = ((i0 + j0+ i1 + j1)%2==0 ? sign : -sign); + + return (newdet/det)*(newsign*sign); // sign is unity, hence 1/sign == sign + } + //------------------------------------------------------------------------------------------ + private: + void complete_remove2() { + if (N==2) { clear(); return;} // put the sign to 1 also .... Change complete_remove... + + size_t i_real_max =std::max(w2.ireal[0],w2.ireal[1]); + size_t i_real_min =std::min(w2.ireal[0],w2.ireal[1]); + size_t j_real_max =std::max(w2.jreal[0],w2.jreal[1]); + size_t j_real_min =std::min(w2.jreal[0],w2.jreal[1]); + + range R(0,N); + + if (j_real_max != N-1) { + arrays::deep_swap( mat_inv(j_real_max,R), mat_inv(N-1,R)); + y_values[ j_real_max ] = y_values[N-1]; + } + if (j_real_min != N-2) { + arrays::deep_swap( mat_inv(j_real_min,R), mat_inv(N-2,R)); + y_values[ j_real_min ] = y_values[N-2]; + } + if (i_real_max != N-1) { + arrays::deep_swap (mat_inv(R,i_real_max), mat_inv(R,N-1)); + x_values[ i_real_max ] = x_values[N-1]; + } + if (i_real_min != N-2) { + arrays::deep_swap (mat_inv(R,i_real_min), mat_inv(R,N-2)); + x_values[ i_real_min ] = x_values[N-2]; + } + + N -= 2; + + // M <- a - d^-1 b c with BLAS + range Rn(0,N), Rl(N,N+2); + //w2.ksi = mat_inv(Rl,Rl); + //w2.ksi = inverse( w2.ksi); + w2.ksi = inverse( mat_inv(Rl,Rl)); + + // write explicitely the second product on ksi for speed ? + mat_inv(Rn,Rn) -= mat_inv(Rn,Rl) * (w2.ksi * mat_inv(Rl,Rn)); // CHANGE + + // modify the permutations + for (size_t k =w2.i[0]; k=0); + w1.j=j;last_try = 3; + w1.jreal = col_num[j]; + w1.y = y; + + // Compute the col B. + for (size_t i= 0; i=0); + w1.i=i;last_try = 4; + w1.ireal = row_num[i]; + w1.x = x; + + // Compute the col B. + for (size_t i= 0; i n_opts_max_before_check) { check_mat_inv(); n_opts=0;} + } + + /// + enum RollDirection {None,Up, Down,Left,Right}; + + /** + * "Cyclic Rolling" of the determinant. + * + * Right : Move the Nth col to the first col cyclically. + * Left : Move the first col to the Nth, cyclically. + * Up : Move the first row to the Nth, cyclically. + * Down : Move the Nth row to the first row cyclically. + * + * Returns -1 is the roll changes the sign of the det, 1 otherwise + * NB : this routine is not a try_xxx : it DOES make the modification and does not need to be completed... + * WHY is it like this ???? : try_roll : return det +1/-1. + */ + int roll_matrix(RollDirection roll) { + size_t tmp; + const int_type NN=N; + switch (roll) { + case(None) : + return 1; + case(Down) : + tmp = row_num[N-1]; + for (int_type i =NN-2; i>=0; i--) row_num[i+1]= row_num[i]; + row_num[0] = tmp; + break; + case(Up) : + tmp = row_num[0]; + for (int_type i =0; i=0; i--) col_num[i+1]= col_num[i]; + col_num[0] = tmp; + break; + case(Left): + tmp = col_num[0]; + for (int_type i =0; i. + * + ******************************************************************************/ +#ifndef TRIQS_GF_BLOCK_H +#define TRIQS_GF_BLOCK_H +#include "./tools.hpp" +#include "./gf.hpp" +#include "./local/tail.hpp" +#include "./meshes/discrete.hpp" + +namespace triqs { namespace gf { + + struct block_index {}; + + namespace gf_implementation { + + template struct mesh { typedef discrete_mesh type;}; + template struct h5_name { static std::string invoke(){ return "BlockGf";}}; + + /// --------------------------- h5_rw --------------------------------- + + template struct h5_ops { + + template + static void write(h5::group g, std::string const & s, DataType const & data, GF const & gf) { + auto gr = g.create_group(s); + for (size_t i =0; i + static void read(h5::group g, std::string const & s, DataType & data, GF const & gf) { + auto gr = g.create_group(s); + for (size_t i =0; i struct data_proxy : data_proxy_vector ::type>{}; + + // ------------------------------- Factories -------------------------------------------------- + + template + struct factories { + typedef typename mesh::type mesh_t; + typedef gf gf_t; + typedef gf_view gf_view_t; + + static gf_t make_gf(std::vector const & V) { return gf_t ( mesh_t(V.size()), V, nothing(), nothing() ) ; } + static gf_t make_gf(std::vector && V) { return gf_t ( mesh_t(V.size()), std::move(V), nothing(), nothing() ) ; } + + static gf_t make_gf(std::vector const & block_names, std::vector const & V) { + return gf_t(mesh_t(block_names), V, nothing(), nothing() ); + } + static gf_t make_gf(std::vector const & block_names, std::vector && V) { + return gf_t(mesh_t(block_names), std::move(V), nothing(), nothing() ); + } + + /* static gf_t make_gf(std::initializer_list const & l) { + auto v = std::vector {l}; + return make_gf(v); + } +*/ + /* template + static gf_t make_gf(size_t N, Args&& ...args) { + std::vector V; V.reserve(N); + for (size_t i=0; i(args...))); + return make_gf(V); + } + */ + static gf_t make_gf(int N, Target const & g) { + std::vector V; V.reserve(N); + for (size_t i=0; i const & block_names, Target const & g) { + std::vector V; V.reserve(block_names.size()); + for (size_t i=0; i + static gf_t make_gf(std::vector const & block_names, Args&& ...args) { + std::vector V; V.reserve(block_names.size()); + for (size_t i=0; i(args...))); + return make_gf(block_names,V); + } + */ + + template + static gf_view_t make_gf_view(std::vector const & V) { return gf_view_t ( mesh_t(V.size()), V, nothing(), nothing() ) ; } + template + static gf_view_t make_gf_view(std::vector && V) { return gf_view_t ( mesh_t(V.size()), std::move(V), nothing(), nothing() ) ; } + + }; + + } // gf_implementation + + // ------------------------------- Free function -------------------------------------------------- + + // a simple function to get the number of blocks + template size_t n_blocks (gf const & g) { return g.mesh().size();} + template size_t n_blocks (gf_view const & g) { return g.mesh().size();} + + + // template alias + //template using block_gf = gf>; + + // experimental + template + gf> make_block_gf(U && ...u) { return gf_implementation::factories,void>::make_gf(std::forward(u)...);} + +}} +#endif + + diff --git a/triqs/gf/data_proxies.hpp b/triqs/gf/data_proxies.hpp new file mode 100644 index 00000000..1afaef8d --- /dev/null +++ b/triqs/gf/data_proxies.hpp @@ -0,0 +1,97 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_DATA_PROXIES_H +#define TRIQS_GF_DATA_PROXIES_H +#include +#include +#include +#include + +namespace triqs { namespace gf { + + template struct data_proxy_array; + + //---------------------------- 3d array ---------------------------------- + + template struct data_proxy_array { + /// The storage + typedef arrays::array storage_t; + typedef typename storage_t::view_type storage_view_t; + + /// The data access + arrays::matrix_view_proxy operator()(storage_t & data, size_t i) const { return arrays::matrix_view_proxy(data,i); } + arrays::const_matrix_view_proxy operator()(storage_t const & data, size_t i) const { return arrays::const_matrix_view_proxy(data,i); } + arrays::matrix_view_proxy operator()(storage_view_t & data, size_t i) const { return arrays::matrix_view_proxy(data,i); } + arrays::const_matrix_view_proxy operator()(storage_view_t const & data, size_t i) const { return arrays::const_matrix_view_proxy(data,i); } + + template static void assign_no_resize (S & data, RHS && rhs) { data() = rhs;} + template static void assign_to_scalar (S & data, RHS && rhs) { data() = rhs;} + template static void assign_with_resize (storage_t & data, RHS && rhs) { data = rhs;} + template static void rebind (storage_view_t & data, RHS && rhs) { data.rebind(rhs.data()); } + }; + + //---------------------------- 1d array ---------------------------------- + + template struct data_proxy_array{ + /// The storage + typedef arrays::array storage_t; + typedef typename storage_t::view_type storage_view_t; + + /// The data access + auto operator()(storage_t & data,size_t i) const -> decltype(data(i)) { return data(i);} + auto operator()(storage_t const & data,size_t i) const -> decltype(data(i)) { return data(i);} + auto operator()(storage_view_t & data,size_t i) const -> decltype(data(i)) { return data(i);} + auto operator()(storage_view_t const & data,size_t i) const -> decltype(data(i)) { return data(i);} + + template static void assign_no_resize (S & data, RHS && rhs) { data() = rhs;} + template static void assign_to_scalar (S & data, RHS && rhs) { data() = rhs;} + template static void assign_with_resize (storage_t & data, RHS && rhs) { data = rhs;} + template static void rebind (storage_view_t & data, RHS && rhs) { data.rebind(rhs.data()); } + }; + + //---------------------------- vector ---------------------------------- + + template struct data_proxy_vector { + typedef typename T::view_type Tv; + + /// The storage + typedef std::vector storage_t; + typedef std::vector storage_view_t; + + /// The data access + T & operator()(storage_t & data, size_t i) { return data[i];} + T const & operator()(storage_t const & data, size_t i) const { return data[i];} + Tv & operator()(storage_view_t & data, size_t i) { return data[i];} + Tv const & operator()(storage_view_t const & data, size_t i) const { return data[i];} + + template static void assign_no_resize (S & data, RHS && rhs) { + //auto r = make_vector(rhs); + if (data.size() !=rhs.size()) TRIQS_RUNTIME_ERROR << "Size mismatch in gf assignment"; + for (size_t i =0; i static void assign_with_resize (S & data, RHS && rhs) {data = utility::factory(rhs);} + template static void assign_to_scalar (S & data, RHS && rhs) {for (size_t i =0; i static void rebind (storage_view_t & data, RHS && rhs) { data.clear(); for (auto & x : rhs.data()) data.push_back(x);} + }; + +}} +#endif + diff --git a/triqs/gf/domains/R.hpp b/triqs/gf/domains/R.hpp new file mode 100644 index 00000000..7aa0fad9 --- /dev/null +++ b/triqs/gf/domains/R.hpp @@ -0,0 +1,40 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_DOMAIN_R_H +#define TRIQS_GF_DOMAIN_R_H +#include "../tools.hpp" + +namespace triqs { namespace gf { + + /// The domain + struct R_domain { + typedef double point_t; + bool operator == (R_domain const & D) const { return true; } + friend void h5_write (h5::group fg, std::string subgroup_name, R_domain const & d) {} + friend void h5_read (h5::group fg, std::string subgroup_name, R_domain & d){ } + friend class boost::serialization::access; + template void serialize(Archive & ar, const unsigned int version) {} + }; + +}} +#endif + + diff --git a/triqs/gf/domains/discrete.hpp b/triqs/gf/domains/discrete.hpp new file mode 100644 index 00000000..96dfb902 --- /dev/null +++ b/triqs/gf/domains/discrete.hpp @@ -0,0 +1,72 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_DISCRETE_DOMAIN_H +#define TRIQS_GF_DISCRETE_DOMAIN_H +#include "../tools.hpp" + +namespace triqs { namespace gf { + + /// The domain + class discrete_domain { + size_t Nmax; + std::vector _names;// name of the points (e.g. for block) + public: + typedef long point_t; + size_t size() const { return Nmax;}; + discrete_domain (size_t Nmax_=1) : Nmax(Nmax_) { + for (size_t i =0; i && Names) : Nmax(Names.size()), _names(Names) { } + discrete_domain (std::vector const & Names) : Nmax(Names.size()), _names(Names) { } + + std::vector const & names() const { return _names;} + + bool operator == (discrete_domain const & D) const { return (Nmax == D.Nmax);} + + /// Write into HDF5 + friend void h5_write (h5::group fg, std::string subgroup_name, discrete_domain const & d) { + h5::group gr = fg.create_group(subgroup_name); + h5_write(gr,"n_max",d.Nmax); + } + + /// Read from HDF5 + friend void h5_read (h5::group fg, std::string subgroup_name, discrete_domain & d){ + h5::group gr = fg.open_group(subgroup_name); + long n; + h5_read(gr,"n_max",n); + d = discrete_domain(n); + } + + // BOOST Serialization + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) { + ar & boost::serialization::make_nvp("n_max",Nmax); + ar & boost::serialization::make_nvp("names",_names); + } + + }; + +}} +#endif + diff --git a/triqs/gf/domains/legendre.hpp b/triqs/gf/domains/legendre.hpp new file mode 100644 index 00000000..1931069f --- /dev/null +++ b/triqs/gf/domains/legendre.hpp @@ -0,0 +1,78 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_LEGENDRE_DOMAIN_H +#define TRIQS_GF_LEGENDRE_DOMAIN_H + +#include "../tools.hpp" + +namespace triqs { namespace gf { + + /// The domain + class legendre_domain { + + public: + + double beta; + statistic_enum statistic; + size_t Nmax; + + typedef long point_t; + size_t size() const { return Nmax;}; + + legendre_domain (double beta_ = 1, statistic_enum stat_ = Fermion, size_t Nmax_=1) : beta(beta_), statistic(stat_), Nmax(Nmax_) {} + + bool operator == (legendre_domain const & D) const { + return ((std::abs(beta - D.beta)<1.e-15) && (statistic == D.statistic) && (Nmax == D.Nmax)); + } + + /// Write into HDF5 + friend void h5_write (h5::group fg, std::string subgroup_name, legendre_domain const & d) { + h5::group gr = fg.create_group(subgroup_name); + h5_write(gr,"n_max",d.Nmax); + h5_write(gr,"beta",d.beta); + h5_write(gr,"statistic",(d.statistic==Fermion ? "F" : "B")); + } + + /// Read from HDF5 + friend void h5_read (h5::group fg, std::string subgroup_name, legendre_domain & d){ + h5::group gr = fg.open_group(subgroup_name); + long n; double beta; std::string statistic; + h5_read(gr,"n_max",n); + h5_read(gr,"beta",beta); + h5_read(gr,"statistic",statistic); + d = legendre_domain(beta,(statistic=="F" ? Fermion : Boson),n); + } + + // BOOST Serialization + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) { + ar & boost::serialization::make_nvp("n_max",Nmax); + ar & boost::serialization::make_nvp("beta",beta); + ar & boost::serialization::make_nvp("statistic",statistic); + } + + }; + +}} +#endif + diff --git a/triqs/gf/domains/matsubara.hpp b/triqs/gf/domains/matsubara.hpp new file mode 100644 index 00000000..c34c41eb --- /dev/null +++ b/triqs/gf/domains/matsubara.hpp @@ -0,0 +1,64 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_DOMAIN_MATSUBARA_H +#define TRIQS_GF_DOMAIN_MATSUBARA_H +#include "../tools.hpp" + +namespace triqs { namespace gf { + + /// The domain + template + struct matsubara_domain { + typedef typename mpl::if_c, double>::type point_t; + double beta; + statistic_enum statistic; + matsubara_domain (double Beta=1, statistic_enum s = Fermion): beta(Beta), statistic(s){} + bool operator == (matsubara_domain const & D) const { return ((std::abs(beta - D.beta)<1.e-15) && (statistic == D.statistic));} + + /// Write into HDF5 + friend void h5_write (h5::group fg, std::string subgroup_name, matsubara_domain const & d) { + h5::group gr = fg.create_group(subgroup_name); + h5_write(gr,"beta",d.beta); + h5_write(gr,"statistic",(d.statistic==Fermion ? "F" : "B")); + } + + /// Read from HDF5 + friend void h5_read (h5::group fg, std::string subgroup_name, matsubara_domain & d){ + h5::group gr = fg.open_group(subgroup_name); + double beta; std::string statistic; + h5_read(gr,"beta",beta); + h5_read(gr,"statistic",statistic); + d = matsubara_domain(beta,(statistic=="F" ? Fermion : Boson)); + } + + // BOOST Serialization + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) { + ar & boost::serialization::make_nvp("beta",beta); + ar & boost::serialization::make_nvp("statistic",statistic); + } + + }; + +}} +#endif + diff --git a/triqs/gf/domains/product.hpp b/triqs/gf/domains/product.hpp new file mode 100644 index 00000000..ab320224 --- /dev/null +++ b/triqs/gf/domains/product.hpp @@ -0,0 +1,36 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_DOM_PRODUCT_H +#define TRIQS_GF_DOM_PRODUCT_H +#include "../tools.hpp" +namespace triqs { namespace gf { + + template + struct domain_product { + typedef std::tuple point_t; + std::tuple domains; + domain_product() = default; + domain_product(Domains const & ... doms) : domains(doms...) {} + friend bool operator == (domain_product const & D1, domain_product const & D2) { return D1.domains == D2.domains;} + }; + +}} +#endif diff --git a/triqs/gf/gf.hpp b/triqs/gf/gf.hpp new file mode 100644 index 00000000..c87c8e77 --- /dev/null +++ b/triqs/gf/gf.hpp @@ -0,0 +1,405 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012-2013 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_GFBASECLASS_H +#define TRIQS_GF_GFBASECLASS_H +#include +#include +#include +#include +#include +#include +#include "./tools.hpp" +#include "./data_proxies.hpp" + +namespace triqs { namespace gf { + using utility::factory; + + // GENERALISE matrxi TO DEFAULT + template class gf; // the value class + template class gf_view; // the view class + + // various implementation traits + namespace gf_implementation { // never use using of this... + // what is the mesh + template struct mesh; + + // evaluator regroup functions to evaluate the function. Cf descriptors + template struct evaluator{ static constexpr int arity = 0;}; + + // closest_point mechanism + template struct get_closest_point; + + // singularity + template struct singularity { typedef nothing type;}; + + // symmetry + template struct symmetry { typedef nothing type;}; + + // factories regroup all factories (constructors..) for all types of gf. + template struct factories; + + // data_proxy contains function to manipulate the data array, but no data itself. + // this is used to specialize this part of the code to array of dim 3 (matrix gf), dim 1 (scalar gf) and vector (e.g. block gf, ...) + template struct data_proxy; + + // This trait contains functions to read/write in hdf5 files. Can be specialized for some descriptor (Cf block) + template struct h5_name; // value is a const char * + + template struct h5_ops { + template static void write(h5::group g, std::string const & s, DataType const & data, GF const &) { h5_write(g,"data",data); } + template static void read (h5::group g, std::string const & s, DataType & data, GF const &) { h5_read(g,"data",data);} + }; + + } // gf_implementation + + // make_gf and make_gf_view forward any args to them + template + gf make_gf(U && ... x) { return gf_implementation::factories::make_gf(std::forward(x)...);} + + template + gf_view make_gf_view(U && ... x) { return gf_implementation::factories::make_gf_view(std::forward(x)...);} + + template + typename gf_implementation::mesh::type make_gf_mesh(U && ... x) { return gf_implementation::mesh::make(std::forward(x)...);} + + template struct gf_desc{}; + template struct gf_tag{}; + + // The trait that "marks" the Green function + TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(ImmutableGreenFunction); + + // ---------------------- implementation -------------------------------- + + /// A common implementation class for gf and gf_view. They will only redefine contructor and = ... + template class gf_impl : + TRIQS_MODEL_CONCEPT(ImmutableGreenFunction), gf_tag> { + public : + + // Pattern : ValueView + typedef gf_view view_type; + typedef gf non_view_type; + + typedef gf_desc descriptor_t; + + typedef typename gf_implementation::mesh::type mesh_t; + typedef typename mesh_t::domain_t domain_t; + typedef typename mesh_t::mesh_point_t mesh_point_t; + typedef typename mesh_t::index_t mesh_index_t; + typedef typename gf_implementation::symmetry::type symmetry_t; + typedef gf_implementation::evaluator evaluator_t; + + typedef gf_implementation::data_proxy data_proxy_t; + typedef typename data_proxy_t::storage_t data_non_view_t; + typedef typename data_proxy_t::storage_view_t data_view_t; + typedef typename std::conditional::type data_t; + + typedef typename gf_implementation::singularity::type singularity_non_view_t; + typedef typename view_type_if_exists_else_type::type singularity_view_t; + typedef typename std::conditional::type singularity_t; + + mesh_t const & mesh() const { return _mesh;} + domain_t const & domain() const { return _mesh.domain();} + data_t & data() { return _data;} + data_t const & data() const { return _data;} + singularity_t & singularity() { return _singularity;} + singularity_t const & singularity() const { return _singularity;} + symmetry_t const & symmetry() const { return _symmetry;} + evaluator_t const & get_evaluator() const { return _evaluator;} + + protected: + mesh_t _mesh; + data_t _data; + singularity_t _singularity; + symmetry_t _symmetry; + evaluator_t _evaluator; + data_proxy_t _data_proxy; + + // --------------------------------Constructors ----------------------------------------------- + // all protected but one, this is an implementation class, see gf/gf_view later for public one + gf_impl() {} // all arrays of zero size (empty) + + public : //everyone can make a copy (for clef lib in particular, this one needs to be public) + + gf_impl(gf_impl const & x) : _mesh(x.mesh()), _data(factory(x.data())), + _singularity(factory(x.singularity())), _symmetry(x.symmetry()), _evaluator(x._evaluator){} + + gf_impl(gf_impl &&) = default; + + protected: + + gf_impl(gf_impl const & x): _mesh(x.mesh()), _data(factory(x.data())), + _singularity(factory(x.singularity())), _symmetry(x.symmetry()), _evaluator(x.get_evaluator()){} + + template + gf_impl(M && m, D && dat, S && sing, SY && sy, EV && ev) : + _mesh(std::forward(m)), _data(std::forward(dat)), _singularity(std::forward(sing)),_symmetry(std::forward(sy)), _evaluator(std::forward(ev)){} + + void operator = (gf_impl const & rhs) = delete; // done in derived class. + + void swap_impl (gf_impl & b) noexcept { + using std::swap; + swap(this->_mesh, b._mesh); swap(this->_data, b._data); swap (this->_singularity,b._singularity); swap(this->_symmetry,b._symmetry); swap(this->_evaluator,b._evaluator); + } + + public: + // ------------- All the call operators ----------------------------- + + // First, a simple () returns a view, like for an array... + view_type operator()() const { return *this;} + + /// Calls are (perfectly) forwarded to the evaluator::operator(), except mesh_point_t and when + /// there is at least one lazy argument ... + template // match any argument list, picking out the first type : () is not permitted + typename std::add_const< + typename boost::lazy_disable_if< // disable the template if one the following conditions it true + boost::mpl::or_< // starting condition [OR] + std::is_base_of< tag::mesh_point, typename std::remove_reference::type>, // Arg0 is (a & or a &&) to a mesh_point_t + clef::is_any_lazy // One of Args is a lazy expression + , boost::mpl::bool_<(sizeof...(Args)!= evaluator_t::arity -1 ) && (evaluator_t::arity !=-1)> // if -1 : no check + >, // end of OR + std::result_of // what is the result type of call + >::type // end of lazy_disable_if + >::type // end of add_Const + operator() (Arg0&& arg0, Args&&... args) const { return _evaluator(this,std::forward( arg0), std::forward(args)...); } + + // Interaction with the CLEF library : calling the gf with any clef expression as argument build a new clef expression + template + typename clef::result_of::make_expr_call::type + //typename clef::result_of::make_expr_call::type + operator()(Arg0 arg0, Args... args) const { + return clef::make_expr_call(view_type(*this),arg0, args...); + } + + typedef typename std::result_of::type r_type; + typedef typename std::result_of::type cr_type; + + r_type operator() (mesh_point_t const & x) { return _data_proxy(_data, x.linear_index());} + cr_type operator() (mesh_point_t const & x) const { return _data_proxy(_data, x.linear_index());} + + template + r_type operator() (closest_pt_wrap const & p) { return _data_proxy(_data, _mesh.index_to_linear( gf_implementation::get_closest_point::invoke(this,p)));} + template + cr_type operator() (closest_pt_wrap const & p) const { return _data_proxy(_data, _mesh.index_to_linear( gf_implementation::get_closest_point::invoke(this,p)));} + + // on mesh component for composite meshes + // enable iif the first arg is a mesh_point_t for the first component of the mesh_t + template::value > + typename std::enable_if< MeshIsComposite && std::is_base_of< tag::mesh_point, Arg0>::value, r_type>::type + operator() (Arg0 const & arg0, Args const & ... args) + { return _data_proxy(_data, _mesh.mesh_pt_components_to_linear(arg0, args...));} + + template::value > + typename std::enable_if< MeshIsComposite && std::is_base_of< tag::mesh_point, Arg0>::value, cr_type>::type + operator() (Arg0 const & arg0, Args const & ... args) const + { return _data_proxy(_data, _mesh.mesh_pt_components_to_linear(arg0, args...));} + + /// A direct access to the grid point + template + r_type on_mesh (Args&&... args) { return _data_proxy(_data,_mesh.index_to_linear(mesh_index_t(std::forward(args)...)));} + + /// A direct access to the grid point (const version) + template + cr_type on_mesh (Args&&... args) const { return _data_proxy(_data,_mesh.index_to_linear(mesh_index_t(std::forward(args)...)));} + + private: + struct _on_mesh_wrapper_const { + gf_impl const & f; _on_mesh_wrapper_const (gf_impl const & _f) : f(_f) {} + template cr_type operator ()(Args && ... args) const { return f.on_mesh(std::forward(args)...);} + }; + struct _on_mesh_wrapper { + gf_impl & f; _on_mesh_wrapper (gf_impl & _f) : f(_f) {} + template r_type operator ()(Args && ... args) const { return f.on_mesh(std::forward(args)...);} + }; + _on_mesh_wrapper_const friend on_mesh(gf_impl const & f) { return f;} + _on_mesh_wrapper friend on_mesh(gf_impl & f) { return f;} + + public: + r_type operator[] (mesh_index_t const & arg) { return _data_proxy(_data,_mesh.index_to_linear(arg));} + cr_type operator[] (mesh_index_t const & arg) const { return _data_proxy(_data,_mesh.index_to_linear(arg));} + + // Interaction with the CLEF library : calling the gf with any clef expression as argument build a new clef expression + template + typename boost::lazy_enable_if< // enable the template if + clef::is_any_lazy, // One of Args is a lazy expression + clef::result_of::make_expr_call + >::type // end of lazy_enable_if + operator[](Arg && arg) const { return clef::make_expr_call(view_type(*this),std::forward(arg));} + + //----------------------------- HDF5 ----------------------------- + + friend std::string get_triqs_hdf5_data_scheme(gf_impl const & g) { return gf_implementation::h5_name::invoke();} + + /// Write into HDF5 + friend void h5_write (h5::group fg, std::string subgroup_name, gf_impl const & g) { + auto gr = fg.create_group(subgroup_name); + gr.write_triqs_hdf5_data_scheme(g); + gf_implementation::h5_ops::write(gr, "data", g._data, g);//can be specialized for some descriptors (E.g. blocks) + h5_write(gr,"singularity",g._singularity); + h5_write(gr,"mesh",g._mesh); + h5_write(gr,"symmetry",g._symmetry); + } + + /// Read from HDF5 + friend void h5_read (h5::group fg, std::string subgroup_name, gf_impl & g) { + auto gr = fg.open_group(subgroup_name); + // Check the attribute or throw + auto tag_file = gr.read_triqs_hdf5_data_scheme(); + auto tag_expected= get_triqs_hdf5_data_scheme(g); + if (tag_file != tag_expected) + TRIQS_RUNTIME_ERROR<< "h5_read : mismatch of the tag TRIQS_HDF5_data_scheme tag in the h5 group : found "<::read(gr, "data", g._data, g);//can be specialized for some descriptors (E.g. blocks) + h5_read(gr,"singularity",g._singularity); + h5_read(gr,"mesh",g._mesh); + h5_read(gr,"symmetry",g._symmetry); + } + + //----------------------------- BOOST Serialization ----------------------------- + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) { + ar & boost::serialization::make_nvp("data",_data); + ar & boost::serialization::make_nvp("singularity",_singularity); + ar & boost::serialization::make_nvp("mesh",_mesh); + ar & boost::serialization::make_nvp("symmetry",_symmetry); + } + + /// print + friend std::ostream & operator << (std::ostream & out, gf_impl const & x) { return out<<(IsView ? "gf_view": "gf");} + friend std::ostream & triqs_nvl_formal_print(std::ostream & out, gf_impl const & x) { return out<<(IsView ? "gf_view": "gf");} + }; + + // --------------------------------------------------------------------------------- + ///The regular class of GF + template class gf : public gf_impl { + typedef gf_impl B; + public : + + gf():B() {} + gf(gf const & g): B(g){} + gf(gf && g) noexcept : B(std::move(g)){} + gf(gf_view const & g): B(g){} + template gf(GfType const & x): B() { *this = x;} + + template // anything from which the factory can make the data ... + gf(typename B::mesh_t const & m, + DataViewType && dat, + typename B::singularity_view_t const & si, + typename B::symmetry_t const & s , + typename B::evaluator_t const & eval = typename B::evaluator_t () + ) : + B(m,factory(std::forward(dat)),si,s,eval) {} + + friend void swap (gf & a, gf & b) noexcept { a.swap_impl (b);} + + gf & operator = (gf const & rhs) { *this = gf(rhs); return *this;} // use move = + gf & operator = (gf & rhs) { *this = gf(rhs); return *this;} // use move = + gf & operator = (gf && rhs) noexcept { swap(*this, rhs); return *this;} + + template void operator = (RHS && rhs) { + this->_mesh = rhs.mesh(); + B::data_proxy_t::assign_with_resize(this->data(), std::forward(rhs).data()); // looks strange for && + this->_singularity = rhs.singularity(); + // to be implemented : there is none in the gf_expr in particular.... + //this->_symmetry = rhs.symmetry(); + } + }; + + // --------------------------------------------------------------------------------- + ///The View class of GF + template class gf_view : public gf_impl { + typedef gf_impl B; + public : + gf_view(gf_view const & g): B(g){} + gf_view(gf_view && g) noexcept : B(std::move(g)){} + + template gf_view(gf_impl const & g): B(g){} + + template + gf_view (typename B::mesh_t const & m, + D const & dat,T const & t,typename B::symmetry_t const & s, + typename B::evaluator_t const &e = typename B::evaluator_t () ) : + B(m,factory(dat),t,s,e) {} + + friend void swap (gf_view & a, gf_view & b) noexcept { a.swap_impl (b);} + + void rebind (gf_view const &X) noexcept { + this->_mesh = X._mesh; this->_symmetry = X._symmetry; + this->_data_proxy.rebind(this->_data,X); + this->_singularity.rebind(X._singularity); + } + + gf_view & operator = (gf_view const & rhs) { triqs_gf_view_assign_delegation(*this,rhs); return *this;} + + template gf_view & operator = (RHS const & rhs) { triqs_gf_view_assign_delegation(*this,rhs); return *this;} + + // Interaction with the CLEF library : auto assignment of the gf (gf(om_) << expression fills the functions by evaluation of expression) + template friend void triqs_clef_auto_assign (gf_view & g, RHS rhs) { + // access to the data . Beware, we view it as a *matrix* NOT an array... (crucial for assignment to scalars !) + g.triqs_clef_auto_assign_impl(rhs, typename std::is_base_of::type()); + assign_from_expression(g.singularity(),rhs); + // if f is an expression, replace the placeholder with a simple tail. If f is a function callable on freq_infty, + // it uses the fact that tail_non_view_t can be casted into freq_infty + } + + private: + template void triqs_clef_auto_assign_impl (RHS const & rhs, std::integral_constant) { + for (auto const & w: this->mesh()) (*this)(w) = rhs(w); + } + template void triqs_clef_auto_assign_impl (RHS const & rhs, std::integral_constant) { + for (auto const & w: this->mesh()) (*this)(w) = triqs::tuple::apply(rhs,w.components_tuple()); + //for (auto w: this->mesh()) triqs::tuple::apply(*this,w.components_tuple()) = triqs::tuple::apply(rhs,w.components_tuple()); + } + + }; // class gf_view + + // delegate = so that I can overload it for specific RHS... + template + DISABLE_IF(arrays::is_scalar) triqs_gf_view_assign_delegation( gf_view & g, RHS const & rhs) { + if (!(g.mesh() == rhs.mesh())) TRIQS_RUNTIME_ERROR<<"Gf Assignment in View : incompatible mesh"; + gf_view::data_proxy_t::assign_no_resize(g.data(),rhs.data()); + g.singularity() = rhs.singularity(); + } + + template + ENABLE_IF(arrays::is_scalar) triqs_gf_view_assign_delegation( gf_view & g, T const & x) { + gf_view::data_proxy_t::assign_to_scalar(g.data(), x); + g.singularity() = x; + } + + // tool for lazy transformation + template struct gf_keeper{ gf_view g; gf_keeper (gf_view const & g_) : g(g_) {} }; + + // ---------------------------------- slicing ------------------------------------ + + template + gf_view slice_target (gf_impl const & g, Args... args) { + return gf_view(g.mesh(), g.data()(tqa::range(), args... ), slice_target (g.singularity(),args...), g.symmetry()); + } + + template + gf_view slice_mesh (gf_impl const & g, Args... args) { + return gf_view(g.mesh().slice(args...), g.data()(g.mesh().slice_get_range(args...),arrays::ellipsis()), g.singularity(), g.symmetry()); + } + +}} + +#include "./gf_expr.hpp" +#endif diff --git a/triqs/gf/gf_expr.hpp b/triqs/gf/gf_expr.hpp new file mode 100644 index 00000000..d4a18e42 --- /dev/null +++ b/triqs/gf/gf_expr.hpp @@ -0,0 +1,129 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_EXPR_H +#define TRIQS_GF_EXPR_H +#include +namespace triqs { namespace gf { + using utility::is_in_ZRC; + namespace gf_expr_tools { + template struct scalar_wrap { + typedef S value_type; + S s; scalar_wrap(S const &s_):s(s_){} + S singularity() const { return s;} + S data() const { return s;} + template value_type operator[](KeyType && key) const { return s;} + template inline value_type operator()(Args && ... args) const { return s;} + friend std::ostream &operator <<(std::ostream &sout, scalar_wrap const &expr){return sout << expr.s; } + }; + + // Combine the two meshes of LHS and RHS : need to specialize where there is a scalar + struct combine_mesh { + template + inline auto operator() (L const & l, R const & r) const -> decltype(l.mesh()) { + if (!(l.mesh() == r.mesh())) TRIQS_RUNTIME_ERROR << "Mesh mismatch : ";//<< l.mesh()<<" vs" < auto operator() (scalar_wrap const & w, R const & r) const -> decltype(r.mesh()) { return r.mesh();} + template auto operator() (L const & l, scalar_wrap const & w) const -> decltype(l.mesh()) { return l.mesh();} + }; + + template struct keeper_type : std::conditional::value, scalar_wrap, typename view_type_if_exists_else_type::type> {}; + }// gf_expr_tools + + template struct gf_expr : TRIQS_MODEL_CONCEPT(ImmutableGreenFunction),gf_tag { + typedef typename gf_expr_tools::keeper_type::type L_t; + typedef typename gf_expr_tools::keeper_type::type R_t; + typedef Descriptor descriptor_t; + //typedef typename std::result_of(typename L_t::value_type,typename R_t::value_type)>::type value_t; + typedef typename std::remove_reference::type>::type mesh_t; + //typedef typename Descriptor::singularity_t::view_type singularity_view_t; + //typedef value_t value_type; + L_t l; R_t r; + template gf_expr(LL && l_, RR && r_) : l(std::forward(l_)), r(std::forward(r_)) {} + mesh_t mesh() const { return gf_expr_tools::combine_mesh()(l,r); } + auto data() const ->decltype( utility::operation()(l.data(), r.data())) { return utility::operation()(l.data(), r.data());} + auto singularity() const DECL_AND_RETURN (utility::operation()(l.singularity() , r.singularity())); + //const singularity_view_t singularity() const { return utility::operation()(l.singularity() , r.singularity());} + //symmetry_t const & symmetry() const { return _symmetry;} + template auto operator[](KeyType && key) const DECL_AND_RETURN(utility::operation()(l[std::forward(key)] , r[std::forward(key)])); + template auto operator()(Args && ... args) const DECL_AND_RETURN(utility::operation()(l(std::forward(args)...) , r(std::forward(args)...))); + friend std::ostream &operator <<(std::ostream &sout, gf_expr const &expr){return sout << "("<::name << " "< struct gf_unary_m_expr : TRIQS_MODEL_CONCEPT(ImmutableGreenFunction),gf_tag{ + typedef typename gf_expr_tools::keeper_type::type L_t; + typedef Descriptor descriptor_t; + //typedef typename L_t::value_type value_type; + typedef typename L_t::mesh_t mesh_t; + //typedef typename Descriptor::singularity_t::view_type singularity_view_t; + L_t l; + template gf_unary_m_expr(LL && l_) : l(std::forward(l_)) {} + mesh_t mesh() const { return l.mesh(); } + auto data() const ->decltype( - l.data()) { return - l.data();} + auto singularity() const DECL_AND_RETURN(l.singularity()); + //const singularity_view_t singularity() const { return l.singularity();} + //symmetry_t const & symmetry() const { return _symmetry;} + template auto operator[](KeyType&& key) const DECL_AND_RETURN( -l[key]); + template auto operator()(Args && ... args) const DECL_AND_RETURN( -l(std::forward(args)...)); + friend std::ostream &operator <<(std::ostream &sout, gf_unary_m_expr const &expr){return sout << '-'< struct get_desc; + template + struct get_desc ::value) && (ImmutableGreenFunction::value))>::type > { + typedef typename A2::descriptor_t type; + }; + template + struct get_desc ::value) && (ImmutableGreenFunction::value)>::type > { + typedef typename A1::descriptor_t type; + }; + template + struct get_desc ::value) && (ImmutableGreenFunction::value) && std::is_same::value >::type > { typedef typename A2::descriptor_t type; }; + + // ------------------------------------------------------------------- + // Now we can define all the C++ operators ... +#define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \ + template\ + typename std::enable_if::value && TRAIT2 ::value, gf_expr::type, utility::tags::TAG, A1,A2>>::type\ + operator OP (A1 const & a1, A2 const & a2) { return gf_expr::type,utility::tags::TAG, A1,A2>(a1,a2);} + + DEFINE_OPERATOR(plus, +, ImmutableGreenFunction,ImmutableGreenFunction); + DEFINE_OPERATOR(minus, -, ImmutableGreenFunction,ImmutableGreenFunction); + DEFINE_OPERATOR(multiplies, *, ImmutableGreenFunction,ImmutableGreenFunction); + DEFINE_OPERATOR(multiplies, *, is_in_ZRC,ImmutableGreenFunction); + DEFINE_OPERATOR(multiplies, *, ImmutableGreenFunction,is_in_ZRC); + DEFINE_OPERATOR(divides, /, ImmutableGreenFunction,ImmutableGreenFunction); + DEFINE_OPERATOR(divides, /, is_in_ZRC,ImmutableGreenFunction); + DEFINE_OPERATOR(divides, /, ImmutableGreenFunction,is_in_ZRC); +#undef DEFINE_OPERATOR + + // the unary is special + template typename std::enable_if::value, gf_unary_m_expr>::type + operator - (A1 const & a1) { return gf_unary_m_expr(a1);} + +}}//namespace triqs::gf +#endif + + diff --git a/triqs/gf/imfreq.hpp b/triqs/gf/imfreq.hpp new file mode 100644 index 00000000..79775e35 --- /dev/null +++ b/triqs/gf/imfreq.hpp @@ -0,0 +1,88 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_MATSUBARA_FREQ_H +#define TRIQS_GF_MATSUBARA_FREQ_H +#include "./tools.hpp" +#include "./gf.hpp" +#include "./local/tail.hpp" +#include "./domains/matsubara.hpp" +#include "./meshes/linear.hpp" +namespace triqs { namespace gf { + + struct imfreq {}; + + namespace gf_implementation { + + // mesh type and its factories + template struct mesh { + typedef linear_mesh> type; + typedef typename type::domain_t domain_t; + + static type make(double beta, statistic_enum S, size_t Nmax = 1025) { + double m1 = std::acos(-1)/beta; + return type( domain_t(beta,S), S==Fermion?m1:0, S==Fermion?(2*Nmax+1)*m1: 2*Nmax*m1, Nmax, without_last); + } + }; + + //singularity + template struct singularity { typedef local::tail type;}; + + //h5 name + template struct h5_name { static std::string invoke(){ return "GfImFreq";}}; + + /// --------------------------- evaluator --------------------------------- + + template + struct evaluator { + static constexpr int arity = 1; + template + arrays::matrix_view > operator() (G const * g, long n) const {return g->data()(n, arrays::range(), arrays::range()); } + template + local::tail_view operator()(G const * g, freq_infty const &) const {return g->singularity();} + }; + + /// --------------------------- data access --------------------------------- + + template struct data_proxy : data_proxy_array,3> {}; + + // ------------------------------- Factories -------------------------------------------------- + + template struct factories { + typedef gf gf_t; + + template + static gf_t make_gf(MeshType && m, tqa::mini_vector shape, local::tail_view const & t) { + typename gf_t::data_non_view_t A(shape.front_append(m.size())); A() =0; + return gf_t ( std::forward(m), std::move(A), t, nothing() ) ; + } + static gf_t make_gf(double beta, statistic_enum S, tqa::mini_vector shape) { + return make_gf(mesh::make(beta,S), shape, local::tail(shape)); + } + static gf_t make_gf(double beta, statistic_enum S, tqa::mini_vector shape, size_t Nmax) { + return make_gf(mesh::make(beta,S,Nmax), shape, local::tail(shape)); + } + static gf_t make_gf(double beta, statistic_enum S, tqa::mini_vector shape, size_t Nmax, local::tail_view const & t) { + return make_gf(mesh::make(beta,S,Nmax), shape, t); + } + }; + } // gf_implementation +}} +#endif diff --git a/triqs/gf/imtime.hpp b/triqs/gf/imtime.hpp new file mode 100644 index 00000000..3712a4f3 --- /dev/null +++ b/triqs/gf/imtime.hpp @@ -0,0 +1,138 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_MATSUBARA_TIME_H +#define TRIQS_GF_MATSUBARA_TIME_H +#include "./tools.hpp" +#include "./gf.hpp" +#include "./local/tail.hpp" +#include "./domains/matsubara.hpp" +#include "./meshes/linear.hpp" + +namespace triqs { namespace gf { + + struct imtime {}; + + namespace gf_implementation { + + // mesh type and its factories + template struct mesh { + typedef linear_mesh> type; + typedef typename type::domain_t domain_t; + static type make(double beta, statistic_enum S, size_t n_time_slices, mesh_kind mk=half_bins) { + return type(domain_t(beta,S), 0, beta, n_time_slices, mk); + } + }; + + // singularity + template struct singularity { typedef local::tail type;}; + + // h5 name + template struct h5_name { static std::string invoke(){ return "GfImTime";}}; + + /// --------------------------- closest mesh point on the grid --------------------------------- + + template + struct get_closest_point { + // index_t is size_t + template + static size_t invoke(G const * g, closest_pt_wrap const & p) { + double x = (g->mesh().kind()==half_bins ? double(p.value) : double(p.value)+ 0.5*g->mesh().delta()); + size_t n = std::floor(x/g->mesh().delta()); + return n; + } + }; + + + /// --------------------------- evaluator --------------------------------- + + template + struct evaluator { + private: + mutable arrays::matrix _tmp; + public : + static constexpr int arity = 1; + evaluator() = default; + evaluator(size_t n1, size_t n2) : _tmp(n1,n2) {} + // WHAT happen in resize ?? + + // NOT TESTED + // TEST THE SPPED when q_view are incorporated... + // true evaluator with interpolation ... + template + arrays::matrix const & operator()(G const * g, double tau) const { + // interpolate between n and n+1, with weight + double beta = g->mesh().domain().beta; + int p = std::floor(tau/beta); + tau -= p*beta; + double a = tau/g->mesh().delta(); + long n = std::floor(a); + double w = a-n; + assert(n < g->mesh().size()-1); + if ((g->mesh().domain().statistic == Fermion) && (p%2==1)) + _tmp = - w*g->data()(n, arrays::range(), arrays::range()) - (1-w)*g->data()(n+1, arrays::range(), arrays::range()); + else + _tmp = w*g->data()(n, arrays::range(), arrays::range()) + (1-w)*g->data()(n+1, arrays::range(), arrays::range()); + //else { // Speed test to redo when incoparated qview in main branch + // _tmp(0,0) = w*g->data()(n, 0,0) + (1-w)*g->data()(n+1, 0,0); + // _tmp(0,1) = w*g->data()(n, 0,1) + (1-w)*g->data()(n+1, 0,1); + // _tmp(1,0) = w*g->data()(n, 1,0) + (1-w)*g->data()(n+1, 1,0); + // _tmp(1,1) = w*g->data()(n, 1,1) + (1-w)*g->data()(n+1, 1,1); + // } + return _tmp; + } + + template + typename G::singularity_t const & operator()(G const * g,freq_infty const &) const {return g->singularity();} + }; + + /// --------------------------- data access --------------------------------- + + template struct data_proxy : data_proxy_array {}; + + // ------------------------------- Factories -------------------------------------------------- + + template struct factories { + typedef gf gf_t; + + template + static gf_t make_gf(MeshType && m, tqa::mini_vector shape, local::tail_view const & t) { + typename gf_t::data_non_view_t A(shape.front_append(m.size())); A() =0; + //return gf_t ( m, std::move(A), t, nothing() ) ; + return gf_t (std::forward(m), std::move(A), t, nothing(), evaluator(shape[0],shape[1]) ) ; + } + /*static gf_t make_gf(double beta, statistic_enum S, tqa::mini_vector shape) { + return make_gf(make_mesh(beta,S,1025,half_bins), shape, local::tail(shape)); + } + static gf_t make_gf(double beta, statistic_enum S, tqa::mini_vector shape, size_t Nmax) { + return make_gf(make_mesh(beta,S,Nmax,half_bins), shape, local::tail(shape)); + } + */ + static gf_t make_gf(double beta, statistic_enum S, tqa::mini_vector shape, size_t Nmax=1025, mesh_kind mk= half_bins) { + return make_gf(mesh::make(beta,S,Nmax,mk), shape, local::tail(shape)); + } + static gf_t make_gf(double beta, statistic_enum S, tqa::mini_vector shape, size_t Nmax, mesh_kind mk, local::tail_view const & t) { + return make_gf(mesh::make(beta,S,Nmax,mk), shape, t); + } + }; + } // gf_implementation +}} +#endif + diff --git a/triqs/gf/legendre.hpp b/triqs/gf/legendre.hpp new file mode 100644 index 00000000..4e8d9c64 --- /dev/null +++ b/triqs/gf/legendre.hpp @@ -0,0 +1,77 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_LEGENDRE_TIME_H +#define TRIQS_GF_LEGENDRE_TIME_H +#include "./tools.hpp" +#include "./gf.hpp" +#include "./local/tail.hpp" +#include "./domains/legendre.hpp" +#include "./meshes/discrete.hpp" + +namespace triqs { namespace gf { + + struct legendre {}; + + namespace gf_implementation { + + // mesh type and its factories + template struct mesh { + typedef discrete_mesh type; + typedef typename type::domain_t domain_t; + static type make(double beta, statistic_enum S, size_t n_leg) { return type(domain_t(beta,S,n_leg)); } + }; + + // h5 name + template struct h5_name { static std::string invoke(){ return "GfLegendre";}}; + + /// --------------------------- evaluator --------------------------------- + + template + struct evaluator { + static constexpr int arity = 1; + //ERROR : give a double and interpolate + template + arrays::matrix_view operator() (G const * g,long n) const {return g->data()(n, arrays::range(), arrays::range()); } + template + local::tail_view operator()(G const * g,freq_infty const &) const {return g->singularity();} + }; + + /// --------------------------- data access --------------------------------- + + template struct data_proxy : data_proxy_array {}; + + // ------------------------------- Factories -------------------------------------------------- + + template struct factories { + typedef gf gf_t; + typedef typename mesh::type mesh_t; + + static gf_t make_gf(double beta, statistic_enum S, tqa::mini_vector shape, size_t n_leg) { + typename gf_t::data_non_view_t A(shape.front_append(n_leg)); A() = 0; + return gf_t(mesh::make(beta, S, n_leg), std::move(A), nothing(), nothing()); + } + + }; + } // gf_implementation + +}} +#endif + diff --git a/triqs/gf/local/CMakeLists.txt b/triqs/gf/local/CMakeLists.txt new file mode 100644 index 00000000..ba95fd92 --- /dev/null +++ b/triqs/gf/local/CMakeLists.txt @@ -0,0 +1,2 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../) +#add_subdirectory(test) diff --git a/triqs/gf/local/fourier_base.cpp b/triqs/gf/local/fourier_base.cpp new file mode 100644 index 00000000..e12a2ec2 --- /dev/null +++ b/triqs/gf/local/fourier_base.cpp @@ -0,0 +1,54 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ +#include "fourier_base.hpp" +#include +#include + +namespace triqs { namespace gf { namespace details { + + void fourier_base(const tqa::vector &in, tqa::vector &out, size_t L, bool direct) { + + // !!!! L must always be the number of time bins !!!! + //const size_t L( (direct ? in.size() : out.size()) ); + //const int L(max(in.size(),out.size())); <-- bug + + fftw_complex *inFFT, *outFFT; + fftw_plan p; + inFFT = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * L); + outFFT = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * L); + + const dcomplex * restrict in_ptr = in.data_start(); + dcomplex * restrict out_ptr = out.data_start(); + const size_t imax = std::min(L,in.size()); + for (size_t i =0; i. + * + ******************************************************************************/ +#ifndef TRIQS_GF_LOCAL_FOURIER_BASE_H +#define TRIQS_GF_LOCAL_FOURIER_BASE_H +#include + +namespace triqs { namespace gf { + + namespace details { + + namespace tqa = triqs::arrays; + typedef std::complex dcomplex; + + void fourier_base(const tqa::vector &in, tqa::vector &out, size_t L, bool direct); + + } + + namespace tags { struct fourier{}; } + +}} + + + +#endif + + diff --git a/triqs/gf/local/fourier_matsubara.cpp b/triqs/gf/local/fourier_matsubara.cpp new file mode 100644 index 00000000..e426d2ea --- /dev/null +++ b/triqs/gf/local/fourier_matsubara.cpp @@ -0,0 +1,173 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#include "fourier_matsubara.hpp" +#include + +namespace triqs { namespace gf { + + namespace impl_local_matsubara { + + inline dcomplex oneFermion(dcomplex a,double b,double tau,double Beta) { + return -a*( b >=0 ? exp(-b*tau)/(1+exp(-Beta*b)) : exp(b*(Beta-tau))/(1+exp(Beta*b)) ); + } + + inline dcomplex oneBoson(dcomplex a,double b,double tau,double Beta) { + return a*( b >=0 ? exp(-b*tau)/(exp(-Beta*b)-1) : exp(b*(Beta-tau))/(1-exp(b*Beta)) ); + } + } + + //-------------------------------------------------------------------------------------- + + void fourier_impl (gf_view &gw , gf_view const & gt){ + + // set behavior according to mesh kind + double shift; + size_t L; + switch(gt.mesh().kind()) { + case half_bins: shift = 0.5; L = gt.mesh().size(); break; + case full_bins: shift = 0.0; L = gt.mesh().size()-1; break; + case without_last: shift = 0.0; L = gt.mesh().size(); break; + } + + auto ta = gt(freq_infty()); + long numberTimeSlices = gt.mesh().size(); + double Beta = gt.domain().beta, Pi = std::acos(-1); + dcomplex I(0,1); + tqa::vector g_in(gt.mesh().size()), g_out (gw.mesh().size()); + + using namespace impl_local_matsubara; + for (size_t n1=0; n1 GfElementType convert_green ( dcomplex const & x) { return x;} + template<> double convert_green ( dcomplex const & x) { return real(x);} + + //--------------------------------------------------------------------------- + + void inverse_fourier_impl (gf_view >, gf_view const & gw) { + + // set behavior according to mesh kind + double shift; + size_t L; + switch(gt.mesh().kind()) { + case half_bins: shift = 0.5; L = gt.mesh().size(); break; + case full_bins: shift = 0.0; L = gt.mesh().size()-1; break; + case without_last: shift = 0.0; L = gt.mesh().size(); break; + } + + static bool Green_Function_Are_Complex_in_time = false; + auto ta = gw(freq_infty()); + + double Beta = gt.domain().beta, Pi = std::acos(-1); + dcomplex I(0,1); + tqa::vector g_in(gw.mesh().size()), g_out (gt.mesh().size()); + + using namespace impl_local_matsubara; + for (size_t n1=0; n1::mesh_type::gf_result_type gt_result_type; + + if (gw.domain().statistic == Fermion){ + for (auto & t : gt.mesh()) + gt(t)(n1,n2) = convert_green (g_out(t.index())*exp(-I*Pi*t/Beta) + + oneFermion(a1,b1,t,Beta) + oneFermion(a2,b2,t,Beta)+ oneFermion(a3,b3,t,Beta) ); + } + else { + for (auto & t : gt.mesh()) + gt(t)(n1,n2) = convert_green (g_out(t.index()) + + oneBoson(a1,b1,t,Beta) + oneBoson(a2,b2,t,Beta) + oneBoson(a3,b3,t,Beta) ); + } + + if (gt.mesh().kind() == full_bins) + gt.on_mesh(L)(n1,n2) = -gt.on_mesh(0)(n1,n2)-convert_green(ta(1)(n1,n2)); + + // set tail + gt.singularity() = gw.singularity(); + + } + } + + + gf_keeper lazy_fourier (gf_view const & g) { return g;} + gf_keeper lazy_inverse_fourier (gf_view const & g) { return g;} + + void triqs_gf_view_assign_delegation( gf_view &g, gf_keeper const & L) { fourier_impl (g,L.g);} + void triqs_gf_view_assign_delegation( gf_view &g, gf_keeper const & L) { inverse_fourier_impl(g,L.g);} + +}} + diff --git a/triqs/gf/local/fourier_matsubara.hpp b/triqs/gf/local/fourier_matsubara.hpp new file mode 100644 index 00000000..d6f43ee2 --- /dev/null +++ b/triqs/gf/local/fourier_matsubara.hpp @@ -0,0 +1,42 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_LOCAL_FOURIER_MATSU_H +#define TRIQS_GF_LOCAL_FOURIER_MATSU_H + +#include "fourier_base.hpp" +#include +#include + +namespace triqs { namespace gf { + + // First the implementation of the fourier transform + void fourier_impl (gf_view &gw , gf_view const & gt); + void inverse_fourier_impl (gf_view >, gf_view const & gw); + + gf_keeper lazy_fourier (gf_view const & g); + gf_keeper lazy_inverse_fourier (gf_view const & g); + + void triqs_gf_view_assign_delegation( gf_view &g, gf_keeper const & L); + void triqs_gf_view_assign_delegation( gf_view &g, gf_keeper const & L); + +}} +#endif + diff --git a/triqs/gf/local/fourier_real.cpp b/triqs/gf/local/fourier_real.cpp new file mode 100644 index 00000000..e4c300e1 --- /dev/null +++ b/triqs/gf/local/fourier_real.cpp @@ -0,0 +1,126 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#include "fourier_real.hpp" +#include + +namespace triqs { namespace gf { + + namespace impl_local_real { + inline dcomplex th_expo(double t, double a ) { return (t < 0 ? 0 : -I * exp(-a*t)); } + inline dcomplex th_expo_neg(double t, double a ) { return (t > 0 ? 0 : I * exp(a*t)); } + } + + //-------------------------------------------------------------------------------------- + + void fourier_impl(gf_view & gw, gf_view const & gt) { + + using namespace impl_local_real; + + size_t L = gt.mesh().size(); + if (gw.mesh().size() != gt.mesh().size()) TRIQS_RUNTIME_ERROR << "Meshes are different"; + double test = std::abs(gt.mesh().delta() * gw.mesh().delta() * L / (2*pi) -1); + if (test > 1.e-10) TRIQS_RUNTIME_ERROR << "Meshes are not compatible"; + + const double tmin = gt.mesh().x_min() + (gt.mesh().kind() == half_bins ? 0.5 : 0.0) * gt.mesh().delta(); + const double wmin = gw.mesh().x_min() + (gw.mesh().kind() == half_bins ? 0.5 : 0.0) * gw.mesh().delta(); + + auto ta = gt(freq_infty()); + tqa::vector g_in(L), g_out(L); + + for (size_t n1=0; n1 & gt, gf_view const & gw) { + + using namespace impl_local_real; + + size_t L = gw.mesh().size(); + if (gw.mesh().size() != gt.mesh().size()) TRIQS_RUNTIME_ERROR << "Meshes are different"; + double test = std::abs(gt.mesh().delta() * gw.mesh().delta() * L / (2*pi) -1); + if (test > 1.e-10) TRIQS_RUNTIME_ERROR << "Meshes are not compatible"; + + const double tmin = gt.mesh().x_min() + (gt.mesh().kind() == half_bins ? 0.5 : 0.0) * gt.mesh().delta(); + const double wmin = gw.mesh().x_min() + (gw.mesh().kind() == half_bins ? 0.5 : 0.0) * gw.mesh().delta(); + + auto ta = gw(freq_infty()); + tqa::vector g_in(L), g_out(L); + + for (size_t n1=0; n1 lazy_fourier (gf_view const & g) { return g;} + gf_keeper lazy_inverse_fourier (gf_view const & g) { return g;} + + void triqs_gf_view_assign_delegation( gf_view &g, gf_keeper const & L) { fourier_impl (g,L.g);} + void triqs_gf_view_assign_delegation( gf_view &g, gf_keeper const & L) { inverse_fourier_impl(g,L.g);} + +}} diff --git a/triqs/gf/local/fourier_real.hpp b/triqs/gf/local/fourier_real.hpp new file mode 100644 index 00000000..f94f4e9d --- /dev/null +++ b/triqs/gf/local/fourier_real.hpp @@ -0,0 +1,67 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_LOCAL_FOURIER_REAL_H +#define TRIQS_GF_LOCAL_FOURIER_REAL_H + +#include "fourier_base.hpp" +#include +#include + +namespace triqs { namespace gf { + + namespace impl_local_real { + dcomplex I(0,1); + double pi = std::acos(-1); + } + + // First the implementation of the fourier transform + void fourier_impl (gf_view &gw , gf_view const & gt); + void inverse_fourier_impl (gf_view >, gf_view const & gw); + + gf_view fourier (gf_view const & gt) { + size_t L = gt.mesh().size(); + double wmin = -impl_local_real::pi * (L-1) / (L*gt.mesh().delta()); + double wmax = impl_local_real::pi * (L-1) / (L*gt.mesh().delta()); + auto gw = make_gf(wmin, wmax, L, gt.data().shape().front_pop()); + auto V = gw(); + fourier_impl(V, gt); + return gw; + } + + gf_view inverse_fourier (gf_view const & gw) { + size_t L = gw.mesh().size(); + double tmin = -impl_local_real::pi * (L-1) / (L*gw.mesh().delta()); + double tmax = impl_local_real::pi * (L-1) / (L*gw.mesh().delta()); + auto gt = make_gf(tmin, tmax, L, gw.data().shape().front_pop()); + auto V = gt(); + inverse_fourier_impl(V, gw); + return gt; + } + + gf_keeper lazy_fourier (gf_view const & g); + gf_keeper lazy_inverse_fourier (gf_view const & g); + + void triqs_gf_view_assign_delegation( gf_view &g, gf_keeper const & L); + void triqs_gf_view_assign_delegation( gf_view &g, gf_keeper const & L); + +}} +#endif + diff --git a/triqs/gf/local/functions.cpp b/triqs/gf/local/functions.cpp new file mode 100644 index 00000000..60efd86f --- /dev/null +++ b/triqs/gf/local/functions.cpp @@ -0,0 +1,127 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#include "functions.hpp" +#include + +namespace triqs { namespace gf { + + dcomplex F(dcomplex a,double b,double Beta) {return -a/(1+exp(-Beta*b));} + using tqa::array; + + //------------------------------------------------------- + // For Imaginary Matsubara Frequency functions + // ------------------------------------------------------ + tqa::matrix density( gf_view const & G) { + dcomplex I(0,1); + auto sh = G.data().shape().front_pop(); + auto Beta = G.domain().beta; + local::tail_view t = G(freq_infty()); + if (!t.is_decreasing_at_infinity()) TRIQS_RUNTIME_ERROR<<" density computation : Green Function is not as 1/omega or less !!!"; + const size_t N1=sh[0], N2 = sh[1]; + tqa::array dens_part(sh), dens_tail(sh), dens(sh); + tqa::matrix res(sh); + dens_part()=0;dens()=0;dens_tail()=0; + for (size_t n1=0; n1 density( gf_view const & gl) { + + auto sh = gl.data().shape().front_pop(); + tqa::matrix res(sh); + res() = 0.0; + + for (auto l : gl.mesh()) { + res -= sqrt(2*l.index()+1) * gl(l); + } + res /= gl.domain().beta; + + return res; + + } + + // compute a tail from the Legendre GF + // this is Eq. 8 of our paper + local::tail_view get_tail(gf_view const & gl, int size = 10, int omin = -1) { + + auto sh = gl.data().shape().front_pop(); + local::tail t(sh, size, omin); + t.data() = 0.0; + + for (int p=1; p<=t.order_max(); p++) + for (auto l : gl.mesh()) + t(p) += (triqs::utility::legendre_t(l.index(),p)/pow(gl.domain().beta,p)) * gl(l); + + return t; + + } + + // Impose a discontinuity G(\tau=0)-G(\tau=\beta) + void enforce_discontinuity(gf_view & gl, tqa::array_view disc) { + + double norm = 0.0; + tqa::vector t(gl.data().shape()[0]); + for (int i=0; i corr(disc.shape()); corr() = 0; + for (auto l : gl.mesh()) { + corr += t(l.index()) * gl(l); + } + + tqa::range R; + for (auto l : gl.mesh()) { + gl.data()(l.index(),R,R) += (disc - corr) * t(l.index()) / norm; + } + + } + + +}} diff --git a/triqs/gf/local/functions.hpp b/triqs/gf/local/functions.hpp new file mode 100644 index 00000000..3313d2ac --- /dev/null +++ b/triqs/gf/local/functions.hpp @@ -0,0 +1,57 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_LOCAL_FUNCTIONS_H +#define TRIQS_GF_LOCAL_FUNCTIONS_H + +#include "../gf.hpp" +#include "../imfreq.hpp" +#include "../legendre.hpp" + +namespace triqs { + namespace gf { + + //------------------------------------------------------- + // For Imaginary Matsubara Frequency functions + // ------------------------------------------------------ + + tqa::matrix density(gf_view const & g); + + tqa::matrix density(gf_view const & g); + + local::tail_view get_tail(gf_view const & gl, int size, int omin); + + void enforce_discontinuity(gf_view & gl, triqs::arrays::array_view disc); + + // For anything that has the ImmutableGfMatsubaraFreq concept, create such a function and compute + // Here I choose to create G and call the function to avoid creating one code for each expression... + //template + //TYPE_ENABLE_IF (tqa::matrix, ImmutableGfMatsubaraFreq) + //density( GfType const & G) { return density( gf_view(G));} + + } + + namespace clef { + TRIQS_CLEF_MAKE_FNT_LAZY (density); + } +} + +#endif + diff --git a/triqs/gf/local/legendre_matsubara.cpp b/triqs/gf/local/legendre_matsubara.cpp new file mode 100644 index 00000000..697c94dc --- /dev/null +++ b/triqs/gf/local/legendre_matsubara.cpp @@ -0,0 +1,118 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by L. Boehnke, M. Ferrero, 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 . + * + ******************************************************************************/ + +#include "legendre_matsubara.hpp" +#include "fourier_matsubara.hpp" +#include "functions.hpp" +#include + +using namespace triqs::utility; + +namespace triqs { namespace gf { + +void legendre_matsubara_direct(gf_view & gw, gf_view const & gl) { + + gw() = 0.0; + triqs::arrays::range R; + + // Use the transformation matrix + for (auto om: gw.mesh()) { + for (auto l: gl.mesh()) { + gw(om) += legendre_T(om.index(),l.index()) * gl(l); + } + } + + gw.singularity() = get_tail(gl, gw.singularity().size(), gw.singularity().order_min()); + +} + +void legendre_matsubara_inverse (gf_view & gl, gf_view const & gw) { + + gl() = 0.0; + + // Construct a temporary imaginary-time Green's function gt + // I set Nt time bins. This is ugly, one day we must code the direct + // transformation without going through imaginary time + long Nt = 50000; + auto gt = triqs::gf::make_gf(gw.domain().beta, gw.domain().statistic, + triqs::arrays::mini_vector(gw.data().shape()[1],gw.data().shape()[2]), + Nt, triqs::gf::half_bins); + + // We first transform to imaginary time because it's been coded with the knowledge of the tails + gt() = lazy_inverse_fourier(gw); + legendre_matsubara_inverse(gl, gt()); + +} + + +void legendre_matsubara_direct (gf_view & gt, gf_view const & gl) { + + gt() = 0.0; + legendre_generator L; + + for (auto t : gt.mesh()) { + L.reset( 2*t/gt.domain().beta-1 ); + for (auto l : gl.mesh()) { + gt(t) += sqrt(2*l.index()+1) / gt.domain().beta * gl(l) * L.next(); + } + } + + gt.singularity() = get_tail(gl, gt.singularity().size(), gt.singularity().order_min()); + +} + +void legendre_matsubara_inverse (gf_view & gl, gf_view const & gt) { + + gl() = 0.0; + legendre_generator L; + + // Do the integral over imaginary time + for (auto t : gt.mesh()) { + L.reset( 2*t/gt.domain().beta-1 ); + for (auto l : gl.mesh()) { + gl(l) += sqrt(2*l.index()+1) * L.next() * gt(t); + } + } + gl.data() *= gt.mesh().delta(); + +} + + +gf_keeper lazy_legendre_imfreq (gf_view const & gl) { return gl; } +gf_keeper lazy_legendre_imtime (gf_view const & gl) { return gl; } +gf_keeper lazy_imfreq_legendre (gf_view const & gw) { return gw; } +gf_keeper lazy_imtime_legendre (gf_view const & gt) { return gt; } + +void triqs_gf_view_assign_delegation( gf_view &gw, gf_keeper const & L) { + legendre_matsubara_direct(gw, L.g); +} +void triqs_gf_view_assign_delegation( gf_view >, gf_keeper const & L) { + legendre_matsubara_direct(gt, L.g); +} +void triqs_gf_view_assign_delegation( gf_view &gl, gf_keeper const & L) { + legendre_matsubara_inverse(gl, L.g); +} +void triqs_gf_view_assign_delegation( gf_view &gl, gf_keeper const & L) { + legendre_matsubara_inverse(gl, L.g); +} + +}} diff --git a/triqs/gf/local/legendre_matsubara.hpp b/triqs/gf/local/legendre_matsubara.hpp new file mode 100644 index 00000000..40a8bf57 --- /dev/null +++ b/triqs/gf/local/legendre_matsubara.hpp @@ -0,0 +1,51 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by L. Boehnke, M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_LOCAL_LEGENDRE_MATSU_H +#define TRIQS_GF_LOCAL_LEGENDRE_MATSU_H + +#include +#include +#include + +namespace triqs { namespace gf { + + void legendre_matsubara_direct (gf_view &gw, gf_view const &gl); + void legendre_matsubara_inverse (gf_view &gl, gf_view const &gw); + + void legendre_matsubara_direct (gf_view >, gf_view const &gl); + void legendre_matsubara_inverse (gf_view &gl, gf_view const >); + + namespace tags { struct legendre{}; } + + gf_keeper lazy_legendre_imfreq (gf_view const & gl); + gf_keeper lazy_legendre_imtime (gf_view const & gl); + gf_keeper lazy_imfreq_legendre (gf_view const & gw); + gf_keeper lazy_imtime_legendre (gf_view const & gt); + + void triqs_gf_view_assign_delegation( gf_view &gw, gf_keeper const & L); + void triqs_gf_view_assign_delegation( gf_view >, gf_keeper const & L); + void triqs_gf_view_assign_delegation( gf_view &gl, gf_keeper const & L); + void triqs_gf_view_assign_delegation( gf_view &gl, gf_keeper const & L); + + +}} +#endif diff --git a/triqs/gf/local/pade.cpp b/triqs/gf/local/pade.cpp new file mode 100644 index 00000000..84eff52c --- /dev/null +++ b/triqs/gf/local/pade.cpp @@ -0,0 +1,68 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, O. Parcollet, I. Krivenko + * + * TRIQS is free software: you can redistribute it and/or modify it under the + * terms of the GNU grneral 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 grneral Public License for more + * details. + * + * You should have received a copy of the GNU grneral Public License along with + * TRIQS. If not, see . + * + ******************************************************************************/ + +#include "pade.hpp" +#include +#include + +namespace triqs { namespace gf { + + typedef std::complex dcomplex; + + void pade (gf_view &gr, gf_view const &gw, int n_points, double freq_offset) { + + // make sure the GFs have the same structure + //assert(gw.shape() == gr.shape()); + + // copy the tail. it doesn't need to conform to the pade approximant + gr.singularity() = gw.singularity(); + + auto sh = gw.data().shape().front_pop(); + int N1 = sh[0], N2 = sh[1]; + for (int n1=0; n1 z_in(n_points); // complex points + arrays::vector u_in(n_points); // values at these points + arrays::vector a(n_points); // corresponding Pade coefficients + + for (int i=0; i < n_points; ++i) z_in(i) = gw.mesh()[i]; + for (int i=0; i < n_points; ++i) u_in(i) = gw.on_mesh(i)(n1,n2); + + triqs::utility::pade_approximant PA(z_in,u_in); + + gr() = 0.0; + for (auto om : gr.mesh()) { + dcomplex e = om + dcomplex(0.0,1.0)*freq_offset; + gr(om)(n1,n2) = PA(e); + } + + } + } + + } + + //gf_keeper lazy_pade(gf_view const & gw) {return gw;} + + //void triqs_gf_view_assign_delegation(gf_view &gr, gf_keeper const & L) { pade(gr, L.g); } + +}} diff --git a/triqs/gf/local/pade.hpp b/triqs/gf/local/pade.hpp new file mode 100644 index 00000000..d7d74a6a --- /dev/null +++ b/triqs/gf/local/pade.hpp @@ -0,0 +1,40 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef TRIQS_GF_LOCAL_PADE_H +#define TRIQS_GF_LOCAL_PADE_H + +#include +#include + +namespace triqs { namespace gf { + + void pade (gf_view &gr, gf_view const &gw, int n_points, double freq_offset); + + //namespace tags { struct pade{}; } + + //gf_keeper lazy_pade(gf_view const & gw); + //void triqs_gf_view_assign_delegation(gf_view &gr, gf_keeper const & L); + +}} + +#endif diff --git a/triqs/gf/local/tail.hpp b/triqs/gf/local/tail.hpp new file mode 100644 index 00000000..0281aaac --- /dev/null +++ b/triqs/gf/local/tail.hpp @@ -0,0 +1,402 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_LOCAL_TAIL_H +#define TRIQS_GF_LOCAL_TAIL_H +#include +#include +#include +#include + +namespace triqs { namespace gf { namespace local { + + namespace details { + static constexpr double small = 1.e-10; + } + + namespace tqa= triqs::arrays; namespace tql= triqs::clef; namespace mpl= boost::mpl; + typedef std::complex dcomplex; + + class tail; // the value class + class tail_view; // the view class + + template struct LocalTail : mpl::false_{}; // a boolean trait to identify the objects modelling the concept LocalTail + template<> struct LocalTail : mpl::true_{}; + template<> struct LocalTail: mpl::true_{}; + template<> struct LocalTail>: mpl::true_{}; + + // a trait to find the scalar of the algebra i.e. the true scalar and the matrix ... + template struct is_scalar_or_element : mpl::or_< tqa::ImmutableMatrix, utility::is_in_ZRC > {}; + + // ---------------------- implementation -------------------------------- + + /// A common implementation class. Idiom : ValueView + template class tail_impl { + public : + typedef void has_view_type_tag; // Idiom : ValueView + typedef tail_view view_type; + typedef tail non_view_type; + + typedef arrays::array data_non_view_type; + typedef arrays::array_view data_view_type; + typedef typename mpl::if_c::type data_type; + + typedef arrays::array mask_non_view_type; + typedef arrays::array_view mask_view_type; + typedef typename mpl::if_c::type mask_type; + + typedef arrays::matrix_view mv_type; + typedef arrays::matrix_view const_mv_type; + //typedef arrays::matrix_view const_mv_type; + + data_view_type data() { return _data;} + const data_view_type data() const { return _data;} + mask_view_type mask_view() { return mask;} + const mask_view_type mask_view() const { return mask;} + + long order_min() const {return omin;} + long order_max() const {return min_element(mask);} + size_t size() const {return _data.shape()[0];} + long smallest_nonzero() const { + long om = omin; + while ((om < this->order_max()) && (max_element(abs(_data(om-omin,tqa::range(),tqa::range()))) < details::small)) om++; + return om; + } + + typedef tqa::mini_vector shape_type; + shape_type shape() const { return shape_type(_data.shape()[1], _data.shape()[2]);} + size_t shape(int i) const { return _data.shape()[i];} + + bool is_decreasing_at_infinity() const { return (smallest_nonzero() >=1);} + + protected: + + long omin; + mask_type mask; + data_type _data; + + // All constructors + tail_impl(): omin(0), mask(), _data() {} // all arrays of zero size (empty) + tail_impl(size_t N1, size_t N2, size_t size_, long order_min): + omin(order_min), mask(tqa::make_shape(N1,N2)), _data(tqa::make_shape(size_,N1,N2)) { + mask() = order_min+size_-1; + _data() = 0; + } + tail_impl(data_type const &d, long order_min, mask_type const &om): omin(order_min), mask(om), _data(d) {} + // tail_impl(tail_impl const & x): omin(x.omin), mask(x.mask), _data(x._data){} + tail_impl(tail_impl const & x): omin(x.omin), mask(x.mask), _data(x._data){} + tail_impl(tail_impl const &) = default; + tail_impl(tail_impl &&) = default; + + friend class tail_impl; + public: + + mv_type operator() (int n) { + if (n>this->order_max()) TRIQS_RUNTIME_ERROR<<" n > Max Order. n= "< Max Order. n= "< + void serialize(Archive & ar, const unsigned int version) { + ar & boost::serialization::make_nvp("omin",omin); + ar & boost::serialization::make_nvp("mask",mask); + ar & boost::serialization::make_nvp("data",_data); + } + + friend std::ostream & operator << (std::ostream & out, tail_impl const & x) { + out <<"tail/tail_view: min/smallest/max = "<< x.order_min() << " " << x.smallest_nonzero() << " "<< x.order_max(); + for (long u = x.order_min(); u <= x.order_max(); ++u) out <<"\n ... Order "< const & x) { + if (omin > 0) TRIQS_RUNTIME_ERROR<<"lhs has too large omin"; + for (size_t n=0; n { + typedef tail_impl B; + friend class tail_view; + public : + tail():B() {} + typedef tqa::mini_vector shape_type; + tail(size_t N1, size_t N2, size_t size_ = 10, long order_min=-1): B(N1,N2,size_,order_min) {} + tail(shape_type const & sh, size_t size_ = 10, long order_min=-1): B(sh[0],sh[1],size_,order_min) {} + tail(tail const & g): B(g){} + tail(tail_view const & g): B(g){} + tail(tail &&) = default; + + // operator = for values + tail & operator = (tail_view const & rhs) { + omin = rhs.omin; + mask = rhs.mask; + _data = rhs._data; + return *this; + } + tail & operator = (tail const & rhs) { + omin = rhs.omin; + mask = rhs.mask; + _data = rhs._data; + return *this; + } + + using B::operator(); + + /// The simplest tail corresponding to : omega + static tail_view omega(size_t N1, size_t N2, size_t size_) { + tail t(N1, N2, size_, -1); + t(-1) = 1; + return t; + } + + /// The simplest tail corresponding to : omega, constructed from a shape for convenience + static tail_view omega(tail::shape_type const & sh, size_t size_) { return omega(sh[0],sh[1],size_);} + + }; + + template void assign_from_expression(tail_view & t,RHS const & rhs) { t = rhs( tail::omega(t.shape(),t.size())); } + + inline void tail_view::rebind( tail const &X) { + omin = X.omin; + mask.rebind(X.mask); + _data.rebind(X._data); + } + inline tail_view & tail_view::operator = (const tail & rhs) { + if (this->_data.is_empty()) rebind(rhs); + else { + if (rhs.omin < omin) TRIQS_RUNTIME_ERROR<<"rhs has too small omin"; + if ((_data.shape()[1] != rhs._data.shape()[1]) || (_data.shape()[2] != rhs._data.shape()[2])) + TRIQS_RUNTIME_ERROR<<"rhs has different shape"; + for (size_t i=0; i tail_view slice_target(tail_impl const & t, tqa::range R1, tqa::range R2) { + return tail_view(t.data()(tqa::range(),R1,R2),t.order_min(),t.mask_view()(R1,R2)); + } + + inline tail inverse(tail_view const & t) { + + // find in t + long omin1 = - t.smallest_nonzero(); + long omax1 = t.order_max() + 2*omin1; + size_t si = omax1-omin1+1; + tail t_inv(t.shape(), si, omin1); + + t_inv(omin1) = inverse(t(-omin1)); + + for (size_t n=1; n= a.n_min and n-p <=b.n_max and n-p >= b.n_min + // hence p <= min ( a.n_max, n-b.n_min ) and p >= max ( a.n_min, n- b.n_max) + const long pmin = std::max(l.smallest_nonzero(), n - r.order_max() ); + const long pmax = std::min(l.order_max(), n - r.smallest_nonzero() ); + for (long p = pmin; p <= pmax; ++p) { res(n) += l(p) * r(n-p);} + } + return res; + } + + template + TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) + operator* (T1 const & a, T2 const & b) { return mult_impl(a,b); } + + template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) + operator* (T1 const & a, T2 const & b) { + tail res(b); for (long n=res.order_min(); n<=res.order_max(); ++n) res(n)=a*res(n); return res; + } + + template TYPE_ENABLE_IF(tail,mpl::and_, tqa::ImmutableMatrix>) + operator* (T1 const & a, T2 const & b) { + tail res(a); for (long n=res.order_min(); n<=res.order_max(); ++n) res(n)=res(n)*b; return res; + } + + inline tail operator * (dcomplex a, tail_view const & r) { tail res(r); res.data()*=a; return res;} + inline tail operator * (tail_view const & r, dcomplex a) { return a*r; } + + template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) + operator/ (T1 const & a, T2 const & b) { return a *inverse(b); } + + inline tail operator / (tail_view const & r, dcomplex a) { tail res(r); res.data() /=a; return res;} + inline tail operator / (dcomplex a, tail_view const & r) { return a * inverse(r); } + + template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) + operator + (T1 const & l, T2 const& r) { + using arrays::range; + if (l.shape() != r.shape()) TRIQS_RUNTIME_ERROR<< "tail addition : shape mismatch"; + long omin1 = std::min(l.smallest_nonzero(),r.smallest_nonzero()); + long omax1 = std::min(l.order_max(),r.order_max()); + size_t si = omax1-omin1+1; + tail res(l.shape(), si, omin1); + for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) + r(i); + return res; + } + + template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) + operator - (T1 const & l, T2 const& r) { + using arrays::range; + if (l.shape() != r.shape()) TRIQS_RUNTIME_ERROR<< "tail substraction : shape mismatch"; + long omin1 = std::min(l.smallest_nonzero(),r.smallest_nonzero()); + long omax1 = std::min(l.order_max(),r.order_max()); + size_t si = omax1-omin1+1; + tail res(l.shape(), si, omin1); + for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) - r(i); + return res; + } + + template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) + operator + (T1 const & a, T2 const & t) { + tail res(t); + res(0) += a; + return res; + } + + + template TYPE_ENABLE_IF(tail,mpl::and_, is_scalar_or_element>) + operator + (T1 const & t, T2 const & a) { return a+t;} + + template TYPE_ENABLE_IF(tail,mpl::and_, LocalTail>) + operator - (T1 const & a, T2 const & t) { return (-a) + t;} + + template TYPE_ENABLE_IF(tail,mpl::and_, is_scalar_or_element>) + operator - (T1 const & t, T2 const & a) { return (-a) + t;} + +}}} +#endif diff --git a/triqs/gf/meshes/discrete.hpp b/triqs/gf/meshes/discrete.hpp new file mode 100644 index 00000000..904ae1ac --- /dev/null +++ b/triqs/gf/meshes/discrete.hpp @@ -0,0 +1,96 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_MESH_DISCRETE_H +#define TRIQS_GF_MESH_DISCRETE_H +#include "./mesh_tools.hpp" +#include "../domains/discrete.hpp" + +namespace triqs { namespace gf { + + template + struct discrete_mesh { + + typedef Domain domain_t; + typedef size_t index_t; + + discrete_mesh (domain_t && dom) : _dom(dom){} + discrete_mesh (domain_t const & dom) : _dom(dom){} //icc has a bug + discrete_mesh () : _dom(){} + + domain_t const & domain() const { return _dom;} + size_t size() const {return _dom.size();} + + /// Conversions point <-> index <-> discrete_index + size_t index_to_point (index_t ind) const {return ind;} + size_t index_to_linear(index_t ind) const {return ind;} + + /// The wrapper for the mesh point + class mesh_point_t : tag::mesh_point,public arith_ops_by_cast { + discrete_mesh const * m; + index_t _index; + public: + mesh_point_t( discrete_mesh const & mesh, index_t const & index_): m(&mesh), _index(index_) {} + void advance() { ++_index;} + operator size_t () const { return m->index_to_point(_index);} + size_t linear_index() const { return _index;} + size_t index() const { return _index;} + bool at_end() const { return (_index == m->size());} + void reset() {_index =0;} + }; + + /// Accessing a point of the mesh + mesh_point_t operator[](index_t i) const { return mesh_point_t (*this,i);} + + /// Iterating on all the points... + typedef mesh_pt_generator iterator; + iterator begin() const { return iterator (this);} + iterator end() const { return iterator (this, true);} + + /// Mesh comparison + bool operator == (discrete_mesh const & M) const { return (_dom == M._dom) ;} + + /// Write into HDF5 + friend void h5_write (h5::group fg, std::string subgroup_name, discrete_mesh const & m) { + h5::group gr = fg.create_group(subgroup_name); + h5_write(gr,"domain",m.domain()); + } + + /// Read from HDF5 + friend void h5_read (h5::group fg, std::string subgroup_name, discrete_mesh & m){ + h5::group gr = fg.open_group(subgroup_name); + typename discrete_mesh::domain_t dom; + h5_read(gr,"domain",dom); + m = discrete_mesh(std::move(dom)); + } + + // BOOST Serialization + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) { + ar & boost::serialization::make_nvp("domain",_dom); + } + + private: + domain_t _dom; + }; +}} +#endif + diff --git a/triqs/gf/meshes/linear.hpp b/triqs/gf/meshes/linear.hpp new file mode 100644 index 00000000..f6d53b54 --- /dev/null +++ b/triqs/gf/meshes/linear.hpp @@ -0,0 +1,181 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_MESH_LINEAR_H +#define TRIQS_GF_MESH_LINEAR_H +#include "./mesh_tools.hpp" +namespace triqs { namespace gf { + + // Three possible meshes + enum mesh_kind { half_bins, full_bins, without_last }; + + template + struct linear_mesh { + + typedef Domain domain_t; + typedef size_t index_t; + typedef typename domain_t::point_t domain_pt_t; + + linear_mesh (domain_t const & dom, double a, double b, size_t n_pts, mesh_kind mk) : + _dom(dom), L(n_pts), a_pt(a), b_pt(b), meshk(mk) { + switch(mk) { + case half_bins: del = (b-a)/L; xmin = a+0.5*del; break; + case full_bins: del = (b-a)/(L-1); xmin = a; break; + case without_last: del = (b-a)/L; xmin = a; break; + } + xmax = xmin + del*(L-1); + } + + linear_mesh (domain_t && dom, double a, double b, size_t n_pts, mesh_kind mk) : + _dom(dom), L(n_pts), a_pt(a), b_pt(b), meshk(mk) { + switch(mk) { + case half_bins: del = (b-a)/L; xmin = a+0.5*del; break; + case full_bins: del = (b-a)/(L-1); xmin = a; break; + case without_last: del = (b-a)/L; xmin = a; break; + } + xmax = xmin + del*(L-1); + } + + linear_mesh () : _dom(), L(0), a_pt(0), b_pt(0), xmin(0), xmax(0), del(0), meshk(half_bins) {} + + domain_t const & domain() const { return _dom;} + size_t size() const { return L; } + double delta() const { return del; } + double x_max() const { return xmax; } + double x_min() const { return xmin; } + mesh_kind kind() const { return meshk; } + + /// Conversions point <-> index <-> linear_index + domain_pt_t index_to_point (index_t ind) const {return embed(xmin + ind * del, mpl::bool_, domain_pt_t>::value >()) ;} + private : // multiply by I is the type is a complex .... + domain_pt_t embed( double x, mpl::bool_ ) const { return x;} + domain_pt_t embed( double x, mpl::bool_ ) const { return std::complex(0,x);} + public : + + size_t index_to_linear(index_t ind) const {return ind;} + + /// The wrapper for the mesh point + class mesh_point_t : tag::mesh_point, public arith_ops_by_cast { + linear_mesh const * m; + index_t _index; + public: + mesh_point_t( linear_mesh const & mesh, index_t const & index_): m(&mesh), _index(index_) {} + void advance() { ++_index;} + operator domain_pt_t () const { return m->index_to_point(_index);} + size_t linear_index() const { return _index;} + size_t index() const { return _index;} + bool at_end() const { return (_index == m->size());} + void reset() {_index =0;} + }; + + /// Accessing a point of the mesh + mesh_point_t operator[](index_t i) const { return mesh_point_t (*this,i);} + + /// Iterating on all the points... + typedef mesh_pt_generator iterator; + iterator begin() const { return iterator (this);} + iterator end() const { return iterator (this, true);} + + /// Mesh comparison + bool operator == (linear_mesh const & M) const { return ((_dom == M._dom) && (size() ==M.size()) && (std::abs(xmin - M.xmin)<1.e-15) && (std::abs(xmax - M.xmax)<1.e-15));} + + /// Write into HDF5 + friend void h5_write (h5::group fg, std::string subgroup_name, linear_mesh const & m) { + h5::group gr = fg.create_group(subgroup_name); + int k; + switch(m.meshk) { + case half_bins: k=0; break; + case full_bins: k=1; break; + case without_last: k=2; break; + } + h5_write(gr,"domain",m.domain()); + h5_write(gr,"min",m.a_pt); + h5_write(gr,"max",m.b_pt); + h5_write(gr,"size",m.size()); + h5_write(gr,"kind",k); + } + + /// Read from HDF5 + friend void h5_read (h5::group fg, std::string subgroup_name, linear_mesh & m){ + h5::group gr = fg.open_group(subgroup_name); + typename linear_mesh::domain_t dom; + double a,b; + size_t L; + int k; + mesh_kind mk; + h5_read(gr,"domain",dom); + h5_read(gr,"min",a); + h5_read(gr,"max",b); + h5_read(gr,"size",L); + h5_read(gr,"kind",k); + switch(k) { + case 0: mk = half_bins; break; + case 1: mk = full_bins; break; + case 2: mk = without_last; break; + } + m = linear_mesh(std::move(dom), a, b, L, mk); + } + + // BOOST Serialization + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) { + ar & boost::serialization::make_nvp("domain",_dom); + ar & boost::serialization::make_nvp("a_pt",a_pt); + ar & boost::serialization::make_nvp("b_pt",b_pt); + ar & boost::serialization::make_nvp("xmin",xmin); + ar & boost::serialization::make_nvp("xmax",xmax); + ar & boost::serialization::make_nvp("del",del); + ar & boost::serialization::make_nvp("size",L); + ar & boost::serialization::make_nvp("kind",meshk); + } + + private: + domain_t _dom; + size_t L; + double a_pt, b_pt; + double xmin, xmax; + double del; + mesh_kind meshk; + }; + + + // UNUSED + /// Simple approximation of a point of the domain by a mesh point. No check + template + size_t get_closest_mesh_pt_index ( linear_mesh const & mesh, typename D::point_t const & x) { + double a = (x - mesh.x_min())/mesh.delta(); + return std::floor(a); + } + + /// Approximation of a point of the domain by a mesh point + template + std::tuple windowing ( linear_mesh const & mesh, typename D::point_t const & x) { + double a = (x - mesh.x_min())/mesh.delta(); + long i = floor(a); + bool in = (! ((i<0) || (i>=long(mesh.size())-1))); + double w = a-i; + // std::cerr << " window "<< i << " "<< in << " "<< w<< std::endl ; + return std::make_tuple(in, (in ? size_t(i) : 0),w); + } + +}} +#endif + diff --git a/triqs/gf/meshes/mesh_tools.hpp b/triqs/gf/meshes/mesh_tools.hpp new file mode 100644 index 00000000..2a9cabaf --- /dev/null +++ b/triqs/gf/meshes/mesh_tools.hpp @@ -0,0 +1,61 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_MESHTOOLS_H +#define TRIQS_GF_MESHTOOLS_H +#include "../tools.hpp" + +namespace triqs { namespace gf { + + // Derive from this object using CRTP to provide arithmetic operation by casting the final object to C + template struct arith_ops_by_cast {}; +#define IMPL_OP(OP)\ + template \ + auto operator OP(arith_ops_by_cast const & x, T const & y) -> decltype( std::declval() OP y) {return C(static_cast(x)) OP y;}\ + template \ + auto operator OP( T const & y, arith_ops_by_cast const & x) -> TYPE_DISABLE_IF(decltype (y OP std::declval()), std::is_same) {return y OP C(static_cast(x));} + IMPL_OP(+); IMPL_OP(-); IMPL_OP(*); IMPL_OP(/); +#undef IMPL_OP + + //TYPE_DISABLE_IF(decltype (std::declval() OP std::declval()), std::is_same)\ + //operator OP( T const & y, arith_ops_by_cast const & x) {return y OP C(static_cast(x));} + + //------------------------------------------------------ + + template + class mesh_pt_generator : + public boost::iterator_facade< mesh_pt_generator, typename MeshType::mesh_point_t , boost::forward_traversal_tag, + typename MeshType::mesh_point_t const & > { + friend class boost::iterator_core_access; + MeshType const * mesh; + size_t u; + typename MeshType::mesh_point_t pt; + typename MeshType::mesh_point_t const & dereference() const { return pt;} + bool equal(mesh_pt_generator const & other) const { return ((mesh == other.mesh) && (other.u==u) );} + public: + mesh_pt_generator( MeshType const * m=NULL, bool atEnd = false): mesh(m), u(atEnd ? m->size(): 0), pt((*m)[typename MeshType::index_t()]) {} + void increment() { ++u; pt.advance(); } + bool at_end() const { return (u>=mesh->size());} + typename MeshType::domain_t::point_t to_point() const { return pt;} + }; + + +}} +#endif diff --git a/triqs/gf/meshes/product.hpp b/triqs/gf/meshes/product.hpp new file mode 100644 index 00000000..fc6adec3 --- /dev/null +++ b/triqs/gf/meshes/product.hpp @@ -0,0 +1,150 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_MESH_PRODUCT_H +#define TRIQS_GF_MESH_PRODUCT_H +#include "./mesh_tools.hpp" +#include "../domains/product.hpp" +#include +namespace triqs { namespace gf { + + template struct mesh_product : tag::composite { + typedef domain_product domain_t; + typedef std::tuple index_t; + typedef std::tuple m_tuple_t; + typedef std::tuple m_pt_tuple_t; + typedef typename domain_t::point_t domain_pt_t; + + static constexpr int dim = sizeof...(Meshes); + + mesh_product () {} + mesh_product (Meshes const & ... meshes) : m_tuple(meshes...), _dom(meshes.domain()...) {} + + domain_t const & domain() const { return _dom;} + m_tuple_t const & components() const { return m_tuple;} + m_tuple_t & components() { return m_tuple;} + + /// size of the mesh is the product of size + struct _aux0 { template size_t operator()(M const & m, size_t R) { return R*m.size();}}; + size_t size() const { return triqs::tuple::fold(_aux0(), m_tuple, 1);} + + /// Conversions point <-> index <-> linear_index + struct _aux1 { template void operator()(P & p, M const & m, I const& i) {p = m.index_to_point(i);}}; + typename domain_t::point_t index_to_point(index_t const & ind) const { domain_pt_t res; triqs::tuple::apply_on_zip3(_aux1(), res,m_tuple,ind); return res;} + + // index[0] + component[0].size * (index[1] + component[1].size* (index[2] + ....)) + struct _aux2 { template size_t operator()(M const & m, I const & i,size_t R) {return m.index_to_linear(i) + R * m.size();}}; + size_t index_to_linear(index_t const & ii) const { return triqs::tuple::fold_on_zip(_aux2(), m_tuple, ii, size_t(0)); } + + // Same but a tuple of mesh_point_t + struct _aux3 { template size_t operator()(M const & m, P const & p,size_t R) {return p.linear_index() + R * m.size();}}; + size_t mp_to_linear(m_pt_tuple_t const & mp) const { return triqs::tuple::fold_on_zip(_aux3(), m_tuple, mp, size_t(0)); } + + // Same but a variadic list of mesh_point_t + template size_t mesh_pt_components_to_linear(MP const & ... mp) const { + static_assert(std::is_same< std::tuple, m_pt_tuple_t>::value, "Call incorrect "); + //static_assert(std::is_same< std::tuple::type>::type...>, m_pt_tuple_t>::value, "Call incorrect "); + return mp_to_linear(std::forward_as_tuple(mp...)); + } // speed test ? or make a variadic fold... + + /// The wrapper for the mesh point + class mesh_point_t : tag::mesh_point{ + const mesh_product * m; + m_pt_tuple_t _c; bool _atend; + struct F2 { template typename M::mesh_point_t operator()(M const & m, typename M::index_t const & i) const { return m[i];}}; + struct F1 { template typename M::mesh_point_t operator()(M const & m) const { return m[typename M::index_t()];}}; + public : + mesh_point_t(mesh_product const & m_, index_t index_ ) : m(&m_), _c (triqs::tuple::apply_on_zip(F2(), m_.m_tuple, index_)), _atend(false) {} + mesh_point_t(mesh_product const & m_) : m(&m_), _c (triqs::tuple::apply(F1(), m_.m_tuple)), _atend(false) {} + m_pt_tuple_t const & components_tuple() const { return _c;} + size_t linear_index() const { return m->mp_to_linear(_c);} + + typedef domain_pt_t cast_t; + operator cast_t() const { return m->index_to_point(index);} + + // index[0] +=1; if index[0]==m.component[0].size() { index[0]=0; index[1] +=1; if ....} and so on until dim + struct _aux1 { template bool operator()(P & p, bool done) + {if (done) return true; p.advance(); if (p.at_end()) {p.reset(); return false;} return true;} + }; + void advance() { triqs::tuple::fold(_aux1(), _c, false);} + + //index_t index() const { return _index;} // not implemented yet + bool at_end() const { return _atend;} + + struct _aux{ template size_t operator()(M & m,size_t ) { m.reset(); return 0;}}; + void reset() { _atend = false; triqs::tuple::fold(_aux(), _c,0);} + };// end mesh_point_t + + /// Accessing a point of the mesh + mesh_point_t operator[](index_t i) const { return mesh_point_t(*this, i);} + mesh_point_t operator()(typename Meshes::index_t ... i) const { return (*this)[std::make_tuple(i...)];} + + /// Iterating on all the points... + typedef mesh_pt_generator iterator; + iterator begin() const { return iterator (this);} + iterator end() const { return iterator (this, true);} + + /// Mesh comparison + friend bool operator == (mesh_product const & M1, mesh_product const & M2) { return M1.m_tuple==M2.m_tuple; } + + /// Write into HDF5 + struct _auxh5w { + h5::group gr; _auxh5w( h5::group gr_) : gr(gr_) {} //icc has yet another bug on new initialization form with {}... + template size_t operator()(M const & m, size_t N) { std::stringstream fs;fs <<"MeshComponent"<< N; h5_write(gr,fs.str(), m); return N+1; } + }; + friend void h5_write (h5::group fg, std::string subgroup_name, mesh_product const & m) { + h5::group gr = fg.create_group(subgroup_name); + //h5_write(gr,"domain",m.domain()); + triqs::tuple::fold(_auxh5w(gr), m.components(), size_t(0)); + } + + /// Read from HDF5 + struct _auxh5r { + h5::group gr;_auxh5r( h5::group gr_) : gr(gr_) {} + template size_t operator()(M & m, size_t N) { std::stringstream fs;fs <<"MeshComponent"<< N; h5_read(gr,fs.str(), m); return N+1; } + }; + friend void h5_read (h5::group fg, std::string subgroup_name, mesh_product & m){ + h5::group gr = fg.open_group(subgroup_name); + //h5_read(gr,"domain",m._dom); + triqs::tuple::fold(_auxh5r(gr), m.components(), size_t(0)); + } + + // BOOST Serialization + friend class boost::serialization::access; + template struct _aux_ser { + Archive & ar;_aux_ser( Archive & ar_) : ar(ar_) {} + template size_t operator()(M & m, size_t N) { + std::stringstream fs;fs <<"MeshComponent"<< N; + ar & boost::serialization::make_nvp(fs.str().c_str(),m); + return N+1; + } + }; + template + void serialize(Archive & ar, const unsigned int version) { + triqs::tuple::fold(_aux_ser(ar), m_tuple, size_t(0)); + } + + private: + m_tuple_t m_tuple; + domain_t _dom; +}; + +}} +#endif diff --git a/triqs/gf/refreq.hpp b/triqs/gf/refreq.hpp new file mode 100644 index 00000000..489bf04e --- /dev/null +++ b/triqs/gf/refreq.hpp @@ -0,0 +1,95 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_FREQ_H +#define TRIQS_GF_FREQ_H +#include "./tools.hpp" +#include "./gf.hpp" +#include "./local/tail.hpp" +#include "./domains/R.hpp" +#include "./meshes/linear.hpp" + +namespace triqs { namespace gf { + + struct refreq {}; + + namespace gf_implementation { + + template struct mesh { + typedef linear_mesh type; + typedef typename type::domain_t domain_t; + static type make(double wmin, double wmax, size_t n_freq, mesh_kind mk) { + return type(domain_t(), wmin, wmax, n_freq, mk); + } + }; + + template struct singularity { typedef local::tail type;}; + template struct h5_name { static std::string invoke(){ return "GfReFreq";}}; + + /// --------------------------- evaluator --------------------------------- + + template + struct evaluator { + static constexpr int arity = 1; + template + arrays::matrix_view > operator() (G const * g,double w0) const { + auto & data = g->data(); + auto & mesh = g->mesh(); + size_t index; double w; bool in; + std::tie(in, index, w) = windowing(mesh,w0); + if (!in) TRIQS_RUNTIME_ERROR <<" Evaluation out of bounds"; + arrays::matrix > res = w*data(mesh.index_to_linear(index), arrays::ellipsis()) + (1-w)*data(mesh.index_to_linear(index+1), arrays::ellipsis()); + return res; + } + template + local::tail_view operator()(G const * g,freq_infty const &) const {return g->singularity();} + }; + + /// --------------------------- data access --------------------------------- + + template struct data_proxy : data_proxy_array,3> {}; + + // ------------------------------- Factories -------------------------------------------------- + + template struct factories { + typedef gf gf_t; + + template + static gf_t make_gf(MeshType && m, tqa::mini_vector shape, local::tail_view const & t) { + typename gf_t::data_non_view_t A(shape.front_append(m.size())); A() =0; + return gf_t ( std::forward(m), std::move(A), t, nothing() ) ; + } + + static gf_t make_gf(double wmin, double wmax, size_t n_freq, tqa::mini_vector shape) { + typename gf_t::data_non_view_t A(shape.front_append(n_freq)); A() =0; + return gf_t(mesh::make(wmin, wmax, n_freq, full_bins), std::move(A), local::tail(shape), nothing()); + } + + static gf_t make_gf(double wmin, double wmax, size_t n_freq, tqa::mini_vector shape, mesh_kind mk) { + typename gf_t::data_non_view_t A(shape.front_append(n_freq)); A() =0; + return gf_t(mesh::make(wmin, wmax, n_freq, mk), std::move(A), local::tail(shape), nothing()); + } + + }; + } // gf_implementation + +}} +#endif + diff --git a/triqs/gf/retime.hpp b/triqs/gf/retime.hpp new file mode 100644 index 00000000..c480c788 --- /dev/null +++ b/triqs/gf/retime.hpp @@ -0,0 +1,89 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_ONE_REAL_TIME_H +#define TRIQS_GF_ONE_REAL_TIME_H +#include "./tools.hpp" +#include "./gf.hpp" +#include "./local/tail.hpp" +#include "./domains/R.hpp" +#include "./meshes/linear.hpp" + +namespace triqs { namespace gf { + + struct retime {}; + + namespace gf_implementation { + + template struct mesh { + typedef linear_mesh type; + typedef typename type::domain_t domain_t; + + static type make(double tmin, double tmax, size_t n_points, mesh_kind mk) { + return type(domain_t(), tmin, tmax, n_points, mk); + } + }; + + template struct singularity { typedef local::tail type;}; + template struct h5_name { static std::string invoke(){ return "GfReTime";}}; + + /// --------------------------- evaluator --------------------------------- + + template + struct evaluator { + static constexpr int arity = 1; + template + arrays::matrix_view > operator() (G const * g,double t0) const { + auto & data = g->data(); + auto & mesh = g->mesh(); + size_t index; double w; bool in; + std::tie(in, index, w) = windowing(mesh,t0); + if (!in) TRIQS_RUNTIME_ERROR <<" Evaluation out of bounds"; + arrays::matrix > res = w*data(mesh.index_to_linear(index), arrays::ellipsis()) + (1-w)*data(mesh.index_to_linear(index+1), arrays::ellipsis()); + return res; + } + template + local::tail_view operator()(G const * g,freq_infty const &) const {return g->singularity();} + }; + + /// --------------------------- data access --------------------------------- + + template struct data_proxy : data_proxy_array,3> {}; + + // ------------------------------- Factories -------------------------------------------------- + + template struct factories { + typedef gf gf_t; + + static gf_t make_gf(double tmin, double tmax, size_t n_points, tqa::mini_vector shape) { + typename gf_t::data_non_view_t A(shape.front_append(n_points)); A() =0; + return gf_t(mesh::make(tmin, tmax, n_points, full_bins), std::move(A), local::tail(shape), nothing()); + } + + static gf_t make_gf(double tmin, double tmax, size_t n_points, tqa::mini_vector shape, mesh_kind mk) { + typename gf_t::data_non_view_t A(shape.front_append(n_points)); A() =0; + return gf_t(mesh::make(tmin, tmax, n_points, mk), std::move(A), local::tail(shape), nothing()); + } + + }; + } // gf_implementation +}} +#endif + diff --git a/triqs/gf/tools.hpp b/triqs/gf/tools.hpp new file mode 100644 index 00000000..f4d06f07 --- /dev/null +++ b/triqs/gf/tools.hpp @@ -0,0 +1,105 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_TOOLS_H +#define TRIQS_GF_TOOLS_H +#include +#include +#include +#include +#include +#include +#include +#include "triqs/utility/complex_ops.hpp" +#include +#include +#include + +namespace triqs { namespace gf { + namespace tqa= triqs::arrays; + namespace mpl=boost::mpl; + + namespace tag { struct composite{}; struct mesh_point{};} + + struct matrix_valued {}; + struct scalar_valued {}; + + //------------------------------------------------------ + + typedef std::complex dcomplex; + + enum statistic_enum {Boson,Fermion}; + + struct freq_infty{}; // the point at infinity + + inline std::vector split(const std::string &s, char delim){ + std::vector elems; + std::stringstream ss(s); + std::string item; + while(std::getline(ss, item, delim)) { elems.push_back(item); } + return elems; + } + //------------------------------------------------------ + + template struct closest_pt_wrap; + + template struct closest_pt_wrap : tag::mesh_point { T value; template explicit closest_pt_wrap(U&&x): value(std::forward(x)){} }; + + template struct closest_pt_wrap : tag::mesh_point { + std::tuple value_tuple; + template explicit closest_pt_wrap(U&& ... x): value_tuple (std::forward(x) ... ){} + }; + + template closest_pt_wrap closest_mesh_pt(T && ... x) { return closest_pt_wrap (std::forward(x)...);} + + //------------------------------------------------------ + + struct nothing { + template explicit nothing(Args...) {} // takes anything, do nothing.. + nothing() {} + typedef void has_view_type_tag; // Idiom : ValueView + typedef nothing view_type; + typedef nothing non_view_type; + void rebind (nothing){} + template< typename RHS> void operator=(RHS && ) {} + friend void h5_write (h5::group, std::string subgroup_name, nothing ) {} + friend void h5_read (h5::group, std::string subgroup_name, nothing ) {} + // BOOST Serialization + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) { + } + friend nothing operator +( nothing, nothing) { return nothing();} + template friend void assign_from_expression(nothing & ,RHS) {} +}; + + template nothing operator+(nothing, T const &) { return nothing();} + template nothing operator-(nothing, T const &) { return nothing();} + template nothing operator*(nothing, T const &) { return nothing();} + template nothing operator/(nothing, T const &) { return nothing();} + template TYPE_DISABLE_IF(nothing, std::is_same) operator+(T const &, nothing) { return nothing();} + template TYPE_DISABLE_IF(nothing, std::is_same) operator-(T const &, nothing) { return nothing();} + template TYPE_DISABLE_IF(nothing, std::is_same) operator*(T const &, nothing) { return nothing();} + template TYPE_DISABLE_IF(nothing, std::is_same) operator/(T const &, nothing) { return nothing();} + + //------------------------------------------------------ + +}} +#endif diff --git a/triqs/gf/two_real_times.hpp b/triqs/gf/two_real_times.hpp new file mode 100644 index 00000000..2e693974 --- /dev/null +++ b/triqs/gf/two_real_times.hpp @@ -0,0 +1,154 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_GF_TWO_TIMES_H +#define TRIQS_GF_TWO_TIMES_H +#include "./tools.hpp" +#include "./gf.hpp" +#include "./retime.hpp" +#include "./meshes/product.hpp" + +namespace triqs { namespace gf { + + struct two_real_times {}; + + namespace gf_implementation { + + // the mesh + template struct mesh { + typedef typename mesh::type m1_t; + typedef mesh_product type; + static type make (double tmax, double n_time_slices) { +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + m1_t m1({},0, tmax,n_time_slices, triqs::gf::full_bins); + return {m1,m1}; +#else + m1_t m1(typename m1_t::domain_t(),0, tmax,n_time_slices, triqs::gf::full_bins); + type m(m1,m1); + return m; +#endif + } + }; + + // h5 name + template struct h5_name { static std::string invoke(){ return "GfTwoRealTime";}}; + + /// --------------------------- closest mesh point on the grid --------------------------------- + + template + struct get_closest_point { + typedef typename mesh::type mesh_t; + + // NOT FINISHED, NOT TESTED + template + static typename mesh_t::index_t invoke(G const * g, closest_pt_wrap const & p) { + double x = (g->mesh().kind()==half_bins ? double(p.value) : double(p.value)+ 0.5*g->mesh().delta()); + size_t n = std::floor(x/g->mesh().delta()); + return n; + } + + }; + + /// --------------------------- evaluator --------------------------------- + + template + struct evaluator { + static constexpr int arity = 2; + template + arrays::matrix_view > operator() (G const * g, double t0, double t1) const { + auto & m0 = std::get<0>(g->mesh().components()); + double s= m0.x_max()/m0.size(); + return g->data()(g->mesh().index_to_linear( typename G::mesh_t::index_t(t0*s, t1*s)), arrays::range(), arrays::range());//mesh.index_to_linear(mesh.point_to_index (t1,t2))); + } + }; + + /// --------------------------- data access --------------------------------- + + template struct data_proxy : data_proxy_array,3> {}; + + // ------------------------------- Factories -------------------------------------------------- + + template struct factories { + typedef gf gf_t; + typedef typename mesh::type mesh_t; + + static gf_t make_gf(double tmax, double n_time_slices, tqa::mini_vector shape) { + auto m = mesh::make(tmax, n_time_slices); + typename gf_t::data_non_view_t A(shape.front_append(m.size())); A() =0; + return gf_t (m, std::move(A), nothing(), nothing() ) ; + } + }; + + // ------------------------------- Path -------------------------------------------------- + /* + struct path { + + typedef typename mesh_t::index_t mesh_pt_t; + typedef triqs::arrays::mini_vector delta_t; + + delta_t pt, delta; + size_t L; + + path( mesh_t const & m, pt_t const & start_pt, delta_t const & d_) : pt(start_pt), delta(d_), L(std::get<1>(m.components()).size()){} + + void advance() { pt += delta;} + + bool out_of_mesh () const { return (! ( (pt[1]>=0) && ( pt[0] >= pt[1]) && (pt[0]<= L)));} + + typedef mesh_pt_generator iterator; + iterator begin() const { return {this, false};} + iterator end() const { return {this, true};} + + }; + + path make_path ( mesh_t const & m, typename mesh_t::index_t starting_point, delta) { + return path(m, starting_point,delta); + } + + // for (auto & p : make_path(G.mesh(), make_tuple(i,j), make_tuple(di,dj) )) G(p) +=0; + */ + + } // gf_implementation + + // ------------------------------- Additionnal free function for this gf -------------------------------------------------- + + // from g(t,t') and t, return g(t-t') for any t'>t + gf slice (gf_view const & g, double t) { + auto const & m = std::get<0> (g.mesh().components()); + long it = get_closest_mesh_pt_index(m, t); + long nt = m.size() - it; + if (it < nt) nt = it ; + double dt = m.delta(); + auto res = make_gf(0, nt*dt, nt, g(t,t).shape()); + res() = 0; + auto _ = arrays::range();// everyone + for(long sh=0; sh + auto get_1d_mesh_from_2times_mesh(M const & m) DECL_AND_RETURN(std::get<0>(m.components())); + +}} +#endif + diff --git a/triqs/h5.hpp b/triqs/h5.hpp new file mode 100644 index 00000000..e8677dc5 --- /dev/null +++ b/triqs/h5.hpp @@ -0,0 +1,29 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_H5_FULL_H +#define TRIQS_H5_FULL_H +#include "./h5/group.hpp" +#include "./h5/scalar.hpp" +#include "./h5/vector.hpp" +#include "./h5/string.hpp" +#include "./h5/make_h5_read_write.hpp" +#endif + diff --git a/triqs/h5/base.hpp b/triqs/h5/base.hpp new file mode 100644 index 00000000..9bf72973 --- /dev/null +++ b/triqs/h5/base.hpp @@ -0,0 +1,184 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_H5_BASE_H +#define TRIQS_H5_BASE_H +#include +#include +#include +#include "hdf5_hl.h" +#include + +namespace triqs { + + inline std::string get_triqs_hdf5_data_scheme(bool) { return "bool";} + inline std::string get_triqs_hdf5_data_scheme(int) { return "int";} + inline std::string get_triqs_hdf5_data_scheme(long) { return "long";} + inline std::string get_triqs_hdf5_data_scheme(long long) { return "long long";} + inline std::string get_triqs_hdf5_data_scheme(unsigned int) { return "int";} + inline std::string get_triqs_hdf5_data_scheme(unsigned long) { return "unsigned long";} + inline std::string get_triqs_hdf5_data_scheme(unsigned long long) { return "unsigned long long";} + inline std::string get_triqs_hdf5_data_scheme(float) { return "float";} + inline std::string get_triqs_hdf5_data_scheme(double) { return "double";} + inline std::string get_triqs_hdf5_data_scheme(long double) { return "long double";} + inline std::string get_triqs_hdf5_data_scheme(std::complex) { return "complex";} + + namespace h5 { + + using utility::mini_vector; + + // conversion of C type to HDF5 native + inline H5::PredType native_type_from_C(char) { return H5::PredType::NATIVE_CHAR; } + inline H5::PredType native_type_from_C(signed char) { return H5::PredType::NATIVE_SCHAR; } + inline H5::PredType native_type_from_C(unsigned char) { return H5::PredType::NATIVE_UCHAR; } + inline H5::PredType native_type_from_C(short) { return H5::PredType::NATIVE_SHORT; } + inline H5::PredType native_type_from_C(unsigned short) { return H5::PredType::NATIVE_USHORT; } + inline H5::PredType native_type_from_C(int) { return H5::PredType::NATIVE_INT; } + inline H5::PredType native_type_from_C(unsigned) { return H5::PredType::NATIVE_UINT; } + inline H5::PredType native_type_from_C(long) { return H5::PredType::NATIVE_LONG; } + inline H5::PredType native_type_from_C(unsigned long) { return H5::PredType::NATIVE_ULONG; } + inline H5::PredType native_type_from_C(long long) { return H5::PredType::NATIVE_LLONG; } + inline H5::PredType native_type_from_C(unsigned long long) { return H5::PredType::NATIVE_ULLONG; } + inline H5::PredType native_type_from_C(float) { return H5::PredType::NATIVE_FLOAT; } + inline H5::PredType native_type_from_C(double) { return H5::PredType::NATIVE_DOUBLE; } + inline H5::PredType native_type_from_C(long double) { return H5::PredType::NATIVE_LDOUBLE; } + inline H5::PredType native_type_from_C(bool) { return H5::PredType::NATIVE_SCHAR; } + inline H5::PredType native_type_from_C(std::string) { return H5::PredType::C_S1; } + + // conversion of C type to HDF5 native + // NEED TO CHANGE THIS ? It is not standard... We should fix a standard or have a trait + inline H5::PredType h5_type_from_C(char) { return H5::PredType::NATIVE_CHAR; } + inline H5::PredType h5_type_from_C(signed char) { return H5::PredType::NATIVE_SCHAR; } + inline H5::PredType h5_type_from_C(unsigned char) { return H5::PredType::NATIVE_UCHAR; } + inline H5::PredType h5_type_from_C(short) { return H5::PredType::NATIVE_SHORT; } + inline H5::PredType h5_type_from_C(unsigned short) { return H5::PredType::NATIVE_USHORT; } + inline H5::PredType h5_type_from_C(int) { return H5::PredType::NATIVE_INT; } + inline H5::PredType h5_type_from_C(unsigned) { return H5::PredType::NATIVE_UINT; } + inline H5::PredType h5_type_from_C(long) { return H5::PredType::NATIVE_LONG; } + inline H5::PredType h5_type_from_C(unsigned long) { return H5::PredType::NATIVE_ULONG; } + inline H5::PredType h5_type_from_C(long long) { return H5::PredType::NATIVE_LLONG; } + inline H5::PredType h5_type_from_C(unsigned long long) { return H5::PredType::NATIVE_ULLONG; } + inline H5::PredType h5_type_from_C(float) { return H5::PredType::NATIVE_FLOAT; } + inline H5::PredType h5_type_from_C(double) { return H5::PredType::NATIVE_DOUBLE; } + inline H5::PredType h5_type_from_C(long double) { return H5::PredType::NATIVE_LDOUBLE; } + inline H5::PredType h5_type_from_C(bool) { return H5::PredType::NATIVE_SCHAR; } + inline H5::PredType h5_type_from_C(std::string) { return H5::PredType::C_S1; } + + // If it is complex return T else T + template struct remove_complex { typedef T type;}; + template struct remove_complex > { typedef T type;}; + template struct remove_complex > { typedef T type;}; + template struct remove_complex: remove_complex{}; + + //------------- compute the data type (removing complex) ---------------------------------- + + // in memory + template H5::PredType data_type_memory () { return native_type_from_C(typename remove_complex::type()); } + + // the type of data to put in the file_or_group + template H5::PredType data_type_file () { return h5_type_from_C(typename remove_complex::type());} + + //------------- compute void * pointer to the data ---------------------------------- + template + typename std::enable_if< boost::is_complex::value, typename std::conditional::value, const void *, void *>::type >::type + get_data_ptr (S * p) { + typedef typename std::conditional::value, const typename S::value_type, typename S::value_type>::type T; + return reinterpret_cast(p); + } + + template + typename std::enable_if< !boost::is_complex::value, typename std::conditional::value, const void *, void *>::type >::type + get_data_ptr (S * p) {return p;} + + // dataspace from lengths and strides. Correct for the complex. strides must be >0 + template + H5::DataSpace dataspace_from_LS ( + mini_vector const & Ltot, + mini_vector const & L, + mini_vector const & S, + mini_vector const & offset = mini_vector() ) + { + static const unsigned int rank = R + (IsComplex ? 1 : 0); + hsize_t totdimsf[rank], dimsf [rank], stridesf[rank], offsetf[rank]; // dataset dimensions + for (size_t u=0; ucreateAttribute(name.c_str(), strdatatype, attr_dataspace); + //myatt_in.write(strdatatype, strwritebuf); + myatt_in.write(strdatatype, (void *)(value.c_str())); + } + + + /****************** Read string attribute *********************************************/ + + /// Return the attribute name of obj, and "" if the attribute does not exist. + inline std::string read_string_attribute (H5::H5Object const * obj, std::string name ) { + std::string value =""; + H5::Attribute attr; + if (H5LTfind_attribute(obj -> getId(), name.c_str() )==0) return value;// not present + // can not find how to get the size with hl. Using full interface + //herr_t err2 = H5LTget_attribute_string(gr.getId(), x.c_str(), name.c_str() , &(buf.front()) ) ; + //value.append( &(buf.front()) ); + try { attr= obj->openAttribute(name.c_str());} + catch (H5::AttributeIException) { return value;} + try { + H5::DataSpace dataspace = attr.getSpace(); + int rank = dataspace.getSimpleExtentNdims(); + if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string attribute and got rank !=0"; + size_t size = attr.getStorageSize(); + H5::StrType strdatatype(H5::PredType::C_S1, size+1); + std::vector buf(size+1, 0x00); + attr.read(strdatatype, (void *)(&buf[0])); + value.append( &(buf.front()) ); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + return value; + } + + }} +#endif + diff --git a/triqs/h5/group.cpp b/triqs/h5/group.cpp new file mode 100644 index 00000000..8f86ce00 --- /dev/null +++ b/triqs/h5/group.cpp @@ -0,0 +1,36 @@ +#include "./group.hpp" + +namespace triqs { namespace h5 { + + extern "C" { + herr_t get_group_elements_name_ds(hid_t loc_id, const char *name, void *opdata) { + H5O_info_t object_info; herr_t err =H5Oget_info_by_name(loc_id,name,&object_info,H5P_DEFAULT ); + if (err<0) TRIQS_RUNTIME_ERROR << "get_group_elements_name_ds internal"; + if (object_info.type == H5O_TYPE_DATASET) static_cast *>(opdata)->push_back(name); + return 0; + } + herr_t get_group_elements_name_grp(hid_t loc_id, const char *name, void *opdata) { + H5O_info_t object_info; herr_t err =H5Oget_info_by_name(loc_id,name,&object_info,H5P_DEFAULT ); + if (err<0) TRIQS_RUNTIME_ERROR << "get_group_elements_name_grp internal"; + if (object_info.type == H5O_TYPE_GROUP) static_cast *>(opdata)->push_back(name); + return 0; + } + } + //----------------------------------------------------------------------- + + std::vector group::get_all_subgroup_names(std::string const & key) const { + std::vector grp_name; + H5::Group F(_g); + F.iterateElems(key.c_str(), NULL, get_group_elements_name_grp, static_cast(&grp_name)); + return grp_name; + } + + std::vector group::get_all_dataset_names(std::string const & key) const { + std::vector ds_name; + H5::Group F(_g); + F.iterateElems(key.c_str(), NULL, get_group_elements_name_ds, static_cast(&ds_name)); + return ds_name; + } + +}} + diff --git a/triqs/h5/group.hpp b/triqs/h5/group.hpp new file mode 100644 index 00000000..e8537d23 --- /dev/null +++ b/triqs/h5/group.hpp @@ -0,0 +1,108 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_H5_GROUP_H +#define TRIQS_H5_GROUP_H +#include "./base.hpp" +namespace triqs { namespace h5 { + /** + * \brief A local derivative of Group. + * Rational : use ADL for h5_read/h5_write, catch and rethrow exception, add some policy for opening/creating + */ + class group { + H5::Group _g; + public: + group() = default; + group( group const & ) = default; + group (H5::Group g) : _g(g) {} + + /// Takes the "/" group at the top of the file. + group (H5::H5File f) : _g(f.openGroup("/")) {} // can not fail, right ? + + group(std::string const & filename, int flag) { H5::H5File f(filename, H5F_ACC_TRUNC); *this = group(f);} + + group(hid_t id_, bool is_group) { + if (is_group) { _g.setId(id_); } + else { H5::H5File f; f.setId(id_); *this = group(f); } + } + /// Write the triqs tag of the group if it is an object. + template void write_triqs_hdf5_data_scheme (T const & obj) { + h5::write_string_attribute( &_g, "TRIQS_HDF5_data_scheme" , get_triqs_hdf5_data_scheme(obj).c_str() ) ; + } + /// Read the triqs tag of the group if it is an object. Returns"" if attribute is not present + std::string read_triqs_hdf5_data_scheme() const { return read_string_attribute(&_g, "TRIQS_HDF5_data_scheme") ; } + /// + bool has_key (std::string const & key) const { return (H5Lexists(_g.getId(), key.c_str(), H5P_DEFAULT)); } + /// + void unlink_key_if_exists(std::string const & key) const { if (this->has_key(key)) _g.unlink(key.c_str()); } + /// Open a subgroup. Throw it if does not exists + group open_group(std::string const & key) const { + if (!has_key(key)) TRIQS_RUNTIME_ERROR << "no subgroup "< + H5::DataSet create_dataset(std::string const & key, Args && ... args) const { + unlink_key_if_exists(key); + H5::DataSet res; + try{ res = _g.createDataSet(key.c_str(), std::forward(args)...);} + catch (H5::GroupIException const & e){ TRIQS_RUNTIME_ERROR << "Error in creating the dataset "<< key <<"\n H5 error message : \n "<< e.getCDetailMsg(); } + return res; + } + + /// Returns all names of subgroup of key in G + std::vector get_all_subgroup_names(std::string const & key) const; + + /// Returns all names of dataset of key in G + std::vector get_all_dataset_names(std::string const & key) const; + + void write_string_attribute (std::string const & obj_name, std::string const & attr_name, std::string const & value){ + herr_t err = H5LTset_attribute_string(_g.getId(),obj_name.c_str(),attr_name.c_str(), value.c_str() ) ; + if (err<0) TRIQS_RUNTIME_ERROR << "Error in setting attribute of "<< obj_name<<" named "<< attr_name << " to " << value; + } + + }; +}} +#endif diff --git a/triqs/h5/h5_boost_python_exceptions.hpp b/triqs/h5/h5_boost_python_exceptions.hpp new file mode 100644 index 00000000..494439c4 --- /dev/null +++ b/triqs/h5/h5_boost_python_exceptions.hpp @@ -0,0 +1,44 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef TRIQS_H5_EXCEPTIONS_H +#define TRIQS_H5_EXCEPTIONS_H + +#include +#include +#include +#include + +namespace triqs { namespace utility { + + // transcription of H5 error + inline void translatorH5Error(H5::Exception const& x) { + std::stringstream f; f<< " H5 exception\n"<(translatorH5Error);} + +}} + +#endif + diff --git a/triqs/h5/h5_extractor.hpp b/triqs/h5/h5_extractor.hpp new file mode 100644 index 00000000..8e7b621d --- /dev/null +++ b/triqs/h5/h5_extractor.hpp @@ -0,0 +1,41 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_H5_H5_EXTRACTOR_GROUP_H +#define TRIQS_H5_H5_EXTRACTOR_GROUP_H +#include "./group.hpp" +#include + +namespace triqs { namespace h5 { + + /** + * \brief Extractor for cython usage only + */ + template + struct h5_extractor { + typename view_type_if_exists_else_type::type operator() (group fg, std::string const & subgroup_name) const { + typename non_view_type_if_exists_else_type::type r; + h5_read(fg,subgroup_name,r); + return r; + } + }; + +}} +#endif diff --git a/triqs/h5/make_h5_read_write.hpp b/triqs/h5/make_h5_read_write.hpp new file mode 100644 index 00000000..6173e976 --- /dev/null +++ b/triqs/h5/make_h5_read_write.hpp @@ -0,0 +1,78 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_TOOLS_H5_MAKE_READ_WRITE_H +#define TRIQS_TOOLS_H5_MAKE_READ_WRITE_H +#include +#include +#include +#include + +namespace triqs { namespace h5 { + + template struct has_h5_read : std::false_type {}; + template struct has_h5_read(), std::string(), (T&)(std::declval())))> : std::true_type {}; + + template struct has_h5_write : std::false_type {}; + template struct has_h5_write(), std::string(), std::declval()))> : std::true_type {}; + + typedef std::function h5_rw_lambda_t; + + namespace details { + // given a pointer to an object, synthesize h5_read/write function for this object + template h5_rw_lambda_t make_h5_write_impl(T * p, std::integral_constant) { + return [p](h5::group F, std::string const &Name) {h5_write(F,Name, *p);}; + } + template h5_rw_lambda_t make_h5_read_impl(T * p, std::integral_constant) { + return [p](h5::group F, std::string const &Name) {h5_read(F,Name, *p);}; + } + + // use boost serialization as a generic case + template h5_rw_lambda_t make_h5_read_impl(T * p, std::integral_constant) { + return [p](h5::group F, std::string const &Name) { std::string s; h5_read(F,Name, s); *p = triqs::deserialize(s); }; + } + template h5_rw_lambda_t make_h5_write_impl(const T * p, std::integral_constant) { + return + [p](h5::group F, std::string const &Name) {h5_write(F,Name, triqs::serialize(*p)); + F.write_string_attribute(Name,"TRIQS_HDF5_data_scheme",get_triqs_hdf5_data_scheme(*p)); + }; + } + + // do_nothing + template h5_rw_lambda_t make_h5_read_impl (T * p, std::integral_constant) { return h5_rw_lambda_t();} + template h5_rw_lambda_t make_h5_write_impl(T * p, std::integral_constant) { return h5_rw_lambda_t();} + + }//details + + // Generate a lambda (h5::group, Name) -> void + // that calls h5_read/write if it exists, and reverts to boost serialization into a string otherwise + template h5_rw_lambda_t make_h5_write(T * p) { return details::make_h5_write_impl(p,std::integral_constant::value?0:1>());} + template h5_rw_lambda_t make_h5_read (T * p) { return details::make_h5_read_impl (p,std::integral_constant::value?0:1>());} + + // Generate a lambda (h5::group, Name) -> void + // that calls h5_read/write if it exists, and does nothing otherwise + template h5_rw_lambda_t make_h5_write_or_nothing(T * p) { return details::make_h5_write_impl(p,std::integral_constant::value?0:2>());} + template h5_rw_lambda_t make_h5_read_or_nothing (T * p) { return details::make_h5_read_impl (p,std::integral_constant::value?0:2>());} + +}}// end namespace +#endif + + + diff --git a/triqs/h5/scalar.hpp b/triqs/h5/scalar.hpp new file mode 100644 index 00000000..c83cff99 --- /dev/null +++ b/triqs/h5/scalar.hpp @@ -0,0 +1,56 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_H5_SCALAR_H +#define TRIQS_H5_SCALAR_H +#include "./group.hpp" +namespace triqs { namespace h5 { + + template + typename std::enable_if::value>::type + h5_write (group g, std::string const & name, S const & A) { + try { + g.unlink_key_if_exists(name); + H5::DataSet ds = g.create_dataset( name, data_type_file(), H5::DataSpace() ); + ds.write( (void *)(&A), data_type_memory(), H5::DataSpace() ); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + + template + typename std::enable_if::value>::type + h5_read (group g, std::string const & name, S & A) { + try { + H5::DataSet ds = g.open_dataset(name); + H5::DataSpace dataspace = ds.getSpace(); + int rank = dataspace.getSimpleExtentNdims(); + if (rank != 0) TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : expecting a scalar (rank =0)" + <<" while the array stored in the hdf5 file has rank = "<(), H5::DataSpace() , H5::DataSpace() ); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + + // the complex number is missing here... +}} +#endif + + + diff --git a/triqs/h5/string.hpp b/triqs/h5/string.hpp new file mode 100644 index 00000000..8e91ca7d --- /dev/null +++ b/triqs/h5/string.hpp @@ -0,0 +1,124 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_H5_STRING_H +#define TRIQS_H5_STRING_H +#include "./group.hpp" +#include +namespace triqs { + + inline std::string get_triqs_hdf5_data_scheme(std::string const & ) { return "string";} + + namespace h5 { + + /** + * \brief Write a string into an hdf5 file + * \param f The h5 file or group of type H5::H5File or H5::Group + * \param name The name of the hdf5 array in the file/group where the stack will be stored + * \param value The string + * \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc). + */ + inline void h5_write (group g, std::string const & name, std::string const & value) { + try { + H5::StrType strdatatype(H5::PredType::C_S1, value.size()); + H5::DataSet ds = g.create_dataset(name, strdatatype, H5::DataSpace()); + ds.write((void*)(value.c_str()), strdatatype ); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + + /** + * \brief Read a string from an hdf5 file + * \param f The h5 file or group of type H5::H5File or H5::Group + * \param name The name of the hdf5 array in the file/group where the stack will be stored + * \param value The string to fill + * \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc). + */ + inline void h5_read (group g, std::string const & name, std::string & value) { + try { + H5::DataSet ds = g.open_dataset(name); + H5::DataSpace dataspace = ds.getSpace(); + int rank = dataspace.getSimpleExtentNdims(); + if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string and got rank !=0"; + size_t size = ds.getStorageSize(); + H5::StrType strdatatype(H5::PredType::C_S1, size); + std::vector buf(size+1, 0x00); + ds.read( (void *)(&buf[0]), strdatatype, H5::DataSpace(), H5::DataSpace() ); + value = ""; value.append( &(buf.front()) ); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + + + /*********************************** 1d array and std::vector of string *********************************/ + namespace detail { + + template + void write_1darray_vector_of_string_impl (group g, std::string const & name, ArrayVectorOfStringType const & V) { + size_t s=0; for (auto & x : V) s = std::max(s,x.size()); + try { + H5::DataSet ds; + H5::StrType strdatatype(H5::PredType::C_S1, s); + const size_t n = V.size(); + std::vector buf(n*(s+1), 0x00); + size_t i=0; for (auto & x : V) {strcpy( &buf[i*s], x.c_str()); ++i;} + + mini_vector L; L[0]=V.size(); + mini_vector S; S[0]=1; + auto d_space = dataspace_from_LS<1,false > (L,L,S); + + ds = g.create_dataset(name, strdatatype, d_space ); + ds.write( (void *)(&buf[0]),strdatatype, d_space ); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + + //------------------------------------------------------------ + + template + void read_1darray_vector_of_string_impl (group g, std::string const & name, ArrayVectorOfStringType & V) { + try { + H5::DataSet ds = g.open_dataset(name); + H5::DataSpace dataspace = ds.getSpace(); + mini_vector dims_out; + int ndims = dataspace.getSimpleExtentDims( &dims_out[0], NULL); + if (ndims !=1) TRIQS_RUNTIME_ERROR << "triqs::h5 : Trying to read 1d array/vector . Rank mismatch : the array stored in the hdf5 file has rank = "< buf(Len*(size+1), 0x00); + + mini_vector L; L[0]=V.size(); + mini_vector S; S[0]=1; + auto d_space = dataspace_from_LS<1,false > (L,L,S); + + ds.read( (void *)(&buf[0]),strdatatype, d_space ); + size_t i=0; for (auto & x : V) { x = ""; x.append(&buf[i*(size)]); ++i;} + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + }// detail + +}} +#endif + diff --git a/triqs/h5/vector.hpp b/triqs/h5/vector.hpp new file mode 100644 index 00000000..afe8eb55 --- /dev/null +++ b/triqs/h5/vector.hpp @@ -0,0 +1,99 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_H5_VECTOR_H +#define TRIQS_H5_VECTOR_H +#include "./group.hpp" +#include "./string.hpp" +#include + +namespace triqs { + + inline std::string get_triqs_hdf5_data_scheme(std::vector const & ) { return "vector";} + + template + std::string get_triqs_hdf5_data_scheme(std::vector const&) { + using triqs::get_triqs_hdf5_data_scheme;// for the basic types, not found by ADL + std::stringstream fs; + fs<<"std::vector<"<"; + return fs.str(); + } + + namespace h5 { + + // special case of vector of string + inline void h5_write (group f, std::string const & name, std::vector const & V) { + detail::write_1darray_vector_of_string_impl(f,name,V); + } + + inline void h5_read (group f, std::string const & name, std::vector & V) { + detail::read_1darray_vector_of_string_impl(f,name,V); + } + + // implementation for vector of double and complex + namespace vector_impl { + + // the dataspace corresponding to the array. Contiguous data only... + template + H5::DataSpace data_space_for_vector (std::vector const & V) { + mini_vector L,S; S[0]=1;L[0] = V.size(); + return h5::dataspace_from_LS<1, boost::is_complex::value > (L,L,S); + } + + template + inline void h5_write_vector_impl (group g, std::string const & name, std::vector const & V) { + try { + H5::DataSet ds = g.create_dataset(name, h5::data_type_file(), data_space_for_vector(V) ); + ds.write( &V[0], h5::data_type_memory(), data_space_for_vector(V) ); + // if complex, to be python compatible, we add the __complex__ attribute + if (boost::is_complex::value) h5::write_string_attribute(&ds,"__complex__","1"); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + + template + inline void h5_read_impl (group g, std::string const & name, std::vector & V) { + try { + H5::DataSet ds = g.open_dataset(name); + H5::DataSpace dataspace = ds.getSpace(); + static const unsigned int Rank = 1 + (boost::is_complex::value ? 1 : 0); + int rank = dataspace.getSimpleExtentNdims(); + if (rank != Rank) TRIQS_RUNTIME_ERROR << "triqs : h5 : read vector. Rank mismatch : the array stored in the hdf5 file has rank = "< dims_out; + dataspace.getSimpleExtentDims( &dims_out[0], NULL); + V.resize(dims_out[0]); + ds.read( &V[0], h5::data_type_memory(), data_space_for_vector(V) , dataspace ); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + }// impl namespace + + + inline void h5_write (group f, std::string const & name, std::vector const & V) { vector_impl::h5_write_vector_impl(f,name,V);} + inline void h5_write (group f, std::string const & name, std::vector> const & V) { vector_impl::h5_write_vector_impl(f,name,V);} + + inline void h5_read (group f, std::string const & name, std::vector & V) { vector_impl::h5_read_impl(f,name,V);} + inline void h5_read (group f, std::string const & name, std::vector> & V) { vector_impl::h5_read_impl(f,name,V);} + + } +} +#endif + + diff --git a/triqs/lattice/bravais_lattice_and_brillouin_zone.cpp b/triqs/lattice/bravais_lattice_and_brillouin_zone.cpp new file mode 100644 index 00000000..aa3cb80f --- /dev/null +++ b/triqs/lattice/bravais_lattice_and_brillouin_zone.cpp @@ -0,0 +1,93 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ +#include "bravais_lattice_and_brillouin_zone.hpp" +#include +#include +#include +namespace triqs { namespace lattice_tools { + + using namespace tqa; + using namespace std; + //using triqs::arrays::blas::dot; + const double almost_zero(1E-10); + + bravais_lattice::bravais_lattice( units_type const & units__) : units_(3,3), dim_(units__.len(0)) { + units_(range(0,dim_),range()) = units__(); + units_(range(dim_,3),range()) = 0; + // First complete the basis. Add some tests for safety + tqa::vector ux(3),uy(3),uz(3); + assert(dim_==2); + switch (dim_) { + case 1: + ux = units_(0,range()); + uz() = 0; uz(1) = 1 ; + uz = uz - dot(uz,ux)* ux; + // no luck, ux was parallel to z, another one must work + if (sqrt(dot(uz,uz)). + * + ******************************************************************************/ +#ifndef TRIQS_LATTICE_BRAVAIS_LATTICE_H +#define TRIQS_LATTICE_BRAVAIS_LATTICE_H +#include +#include +#include +#include +#include +#include +#include + +namespace triqs { namespace lattice_tools { + + namespace tqa = triqs::arrays; + using tqa::array; using tqa::array_view; using tqa::matrix_view;using tqa::matrix;using tqa::range; + + typedef tqa::vector R_type; + typedef tqa::vector K_type; + typedef tqa::vector_view R_view_type; + typedef tqa::vector_view K_view_type; + typedef std::complex dcomplex; + + class bravais_lattice { + public : + typedef matrix units_type; + typedef std::unordered_map orbital_type; // name -> position in space + + bravais_lattice(units_type const & units); + + size_t n_orbitals() const {return orbitals_.size();} + units_type const & units() const { return units_;} + size_t dim() const { return dim_; } + + /** + * Push_back mechanism of a pair orbital_name -> position in R^3 + * VectorType is anything from which a tqa::vector can be constructed + */ + template + void push_back(std::string const & s, VectorType && v) { orbitals_.insert(std::make_pair(s,std::forward(v)));} + + /*** + * Transform into real coordinates. + * @param[in] x : coordinates in the basis :unit_i arrays::vector or vector_view + * @return Coordinates in R^3 ("real" coordinates) + */ + template + R_view_type lattice_to_real_coordinates(R const & x) const { + R_type res(3); res() =0; + for (size_t i =0; i< dim();i++) res += x (i) * units_(i,range()); + return(res); + } + + protected : + units_type units_; + size_t dim_; + orbital_type orbitals_; + }; + + class brillouin_zone { + bravais_lattice lattice_; + tqa::matrix K_reciprocal, K_reciprocal_inv; + public : + + brillouin_zone( bravais_lattice const & bl_); + bravais_lattice lattice() const { return lattice_;} + + /*** + * Transform into real coordinates. + * @param[in] k : coordinates in the basis (K_reciprocal_i) + * @return Coordinates in R^3 ("real" coordinates) + */ + K_view_type lattice_to_real_coordinates (K_view_type const & k) const; + + /// Inverse of latt_to_real_k + K_view_type real_to_lattice_coordinates (K_view_type const & k) const; + }; + +}} +#endif diff --git a/triqs/lattice/concepts.rst b/triqs/lattice/concepts.rst new file mode 100644 index 00000000..6aa9ce58 --- /dev/null +++ b/triqs/lattice/concepts.rst @@ -0,0 +1,28 @@ + + +Concept Function +return_type +arg_type +return_type operator()(arg_type const &) const : the evaluation of the function + + +Concept FunctionOnBravaisLattice + +refines Function +bravais_lattice const & lattice() const + + +Concept ShortRangeFunctionOnBravaisLattice + +* refines FunctionOnBravaisLattice +* derived from Tag::ShortRangeFunctionOnBravaisLattice ?? +* map_type +* begin, end: iterator -> pair + + +Concept FunctionOnBrillouinZone + +* refines Function +brillouin_zone const & bz() const + + diff --git a/triqs/lattice/functors.hpp b/triqs/lattice/functors.hpp new file mode 100644 index 00000000..34781446 --- /dev/null +++ b/triqs/lattice/functors.hpp @@ -0,0 +1,90 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_LATTICE_FUNCTORS_H +#define TRIQS_LATTICE_FUNCTORS_H + +namespace triqs { namespace lattice_tools { + + const double pi = acos(-1.0); + const std::complex I(0,1); + + template struct minus_chech_impl { + typedef typename F::arg_type arg_type; + typedef typename F::return_type return_type; + F f; + minus_chech_impl(F const & f_):f(f_){} + brillouin_zone const & bz() const {return f.bz();} + return_type operator()(arg_type const & x) const { return_type res(f(x)); res *=-1; return res;} + }; + + namespace result_of { template struct minus_chech{ typedef minus_chech_impl type;}; } + + /** + * Given f of type F which models FunctionOnBravaisLattice, minus_check(f) : + * - returns -f(-args) + * - its type models Function + * + */ + template minus_chech_impl minus_chech(F const & f) { return minus_chech_impl (f);} + + template//, typename Enabler = boost::enable_if< Tag::check > > + class fourier_impl { + F f; + brillouin_zone bz_; + // deduce the return type from decltype(begin()->second) + public: + typedef typename non_view_type_if_exists_else_type< decltype(f.begin()->second)>::type return_construct_type; + typedef typename view_type_if_exists_else_type::type return_type; + typedef K_view_type arg_type; + + fourier_impl (F f_):f(f_), bz_(f_.lattice()), res(f.n_bands(),f.n_bands()) {} + + //brillouin_zone const & bz() const { return bz_; } + + return_type operator()(K_view_type const & k) { + res()=0; + for (auto const & pdm : f) { res += pdm.second * exp( 2*pi*I* this->dot_product(k,pdm.first)); } + return res; + } + + protected: + inline double dot_product(K_view_type const & a, typename F::arg_type const & b) const { + assert(b.size()>= this->bz_.lattice().dim()); + double r=0; for (size_t i=0; i< this->bz_.lattice().dim();++i) r += a(i) * b[i]; + return r; + } + return_construct_type res; + //typename F::return_construct_type res; + }; + + /** + * Given f of type F which models ShortRangeFunctionOnBravaisLattice, Fourier(f) returns + * - a type that models FunctionOnBravaisLattice + * - and returns the Fourier transform f(k) + */ + template fourier_impl Fourier(F f) { return fourier_impl (f);} + //namespace result_of { template struct Fourier { typedef fourier_impl type;}; } + +}} + +#endif + diff --git a/triqs/lattice/grid_generator.hpp b/triqs/lattice/grid_generator.hpp new file mode 100644 index 00000000..f76e5138 --- /dev/null +++ b/triqs/lattice/grid_generator.hpp @@ -0,0 +1,73 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef TRIQS_GRID_GENERATOR_H +#define TRIQS_GRID_GENERATOR_H + +#include + +namespace triqs { namespace lattice_tools { + + /** + * Generate the point in a cuboid as an array const & + */ + class grid_generator : + public boost::iterator_facade< grid_generator, K_type const &, boost::forward_traversal_tag, K_type const & > { + friend class boost::iterator_core_access; + size_t dim, nkpts,nx,ny,nz,N_X,N_Y,N_Z,index_; + double step_x, step_y, step_z; + bool at_end; + K_type pt; + void init() { + nx=0; ny=0; nz=0;at_end = false;index_ =0; + N_X = nkpts; + N_Y = (dim>1 ? nkpts : 1); + N_Z = (dim>2 ? nkpts : 1); + step_x = 1.0/double(N_X); step_y = 1.0/double(N_Y); step_z = 1.0/double(N_Z); + pt(0)=step_x/2; pt(1)=step_y/2; pt(2)=step_z/2; + } + + void increment() { + if (nx. + * + ******************************************************************************/ +#include "tight_binding.hpp" +#include +#include +#include "grid_generator.hpp" +#include "functors.hpp" +namespace triqs { namespace lattice_tools { +using namespace std; + using namespace tqa; + + //------------------------------------------------------ + + array_view hopping_stack (tight_binding const & TB, array_view const & k_stack) { + auto TK = Fourier(TB); + array res(TB.n_bands(), TB.n_bands(), k_stack.len(1)); + for(size_t i = 0; i energies_on_bz_path(tight_binding const & TB, K_view_type K1, K_view_type K2, size_t n_pts) { + auto TK = Fourier(TB); + const size_t norb=TB.lattice().n_orbitals(); + const size_t ndim=TB.lattice().dim(); + array eval(norb,n_pts); + K_type dk = (K2 - K1)/double(n_pts), k = K1; + for (size_t i =0; i energies_on_bz_grid(tight_binding const & TB, size_t n_pts) { + + auto TK = Fourier(TB); + const size_t norb=TB.lattice().n_orbitals(); + const size_t ndim=TB.lattice().dim(); + grid_generator grid(ndim,n_pts); + array eval(norb,grid.size()); + for (; grid ; ++grid) { + eval(range(),grid.index()) = linalg::eigenvalues( TK( (*grid) (range(0,ndim))), false); + } + return eval; + } + + //------------------------------------------------------ + + std::pair, array > dos(tight_binding const & TB, size_t nkpts, size_t neps) { + + // The Fourier transform of TK + // auto TK = Fourier(TB); // C++0x .... + auto TK = Fourier(TB); + + // loop on the BZ + const size_t ndim=TB.lattice().dim(); + const size_t norb=TB.lattice().n_orbitals(); + grid_generator grid(ndim,nkpts); + array tempeval(norb); + array evec(norb,norb,grid.size()); + array eval(norb,grid.size()); + if (norb ==1) + for (; grid ; ++grid) { + double ee = real(TK( (*grid) (range(0,ndim)))(0,0)); + eval(0,grid.index()) =ee; + evec(0,0,grid.index()) =1; + } + else + for (; grid ; ++grid) { + //cerr<<" index = "< eval_sl = eval(range(),grid.index()); + array_view evec_sl = evec(range(),range(),grid.index()); + std::tie (eval_sl,evec_sl) = linalg::eigenelements( TK( (*grid) (range(0,ndim)))); //, true); + //cerr<< " point "<< *grid << " value "<< eval_sl<< endl; //" "<< (*grid) (range(0,ndim)) << endl; + } + + // define the epsilon mesh, etc. + array epsilon(neps); + double epsmax = tqa::max_element(eval); + double epsmin = tqa::min_element(eval); + double deps=(epsmax-epsmin)/neps; + //for (size_t i =0; i< neps; ++i) epsilon(i)= epsmin+i/(neps-1.0)*(epsmax-epsmin); + for (size_t i =0; i< neps; ++i) epsilon(i)=epsmin+(i+0.5)*deps; + + // bin the eigenvalues according to their energy + // NOTE: a is defined as an integer. it is the index for the DOS. + //REPORT <<"Starting Binning ...."< rho (neps,norb);rho()=0; + for(size_t l=0;l, array > dos_patch(tight_binding const & TB, const array & triangles, size_t neps, size_t ndiv) { + // WARNING: This version only works for a single band Hamiltonian in 2 dimensions!!!! + // triangles is an array of points defining the triangles of the patch + // neps in the number of bins in energy + // ndiv in the number of divisions used to divide the triangles + + //const size_t ndim=TB.lattice().dim(); + //const size_t norb=TB.lattice().n_orbitals(); + int ntri = triangles.len(0)/3; + array dos(neps); + + // Check consistency + const size_t ndim=TB.lattice().dim(); + //const size_t norb=TB.lattice().n_orbitals(); + if (ndim !=2) TRIQS_RUNTIME_ERROR<<"dos_patch : dimension 2 only !"; + if (triangles.len(1) != ndim) TRIQS_RUNTIME_ERROR<<"dos_patch : the second dimension of the 'triangle' array in not "< thop(1,1); + array energ(nk), weight(nk); + + // a, b, c are the corners of the triangle + // g the center of gravity taken from a + array a(ndim), b(ndim), c(ndim), g(ndim), rv(ndim); + int pt = 0; + double s, t; + + // The Fourier transform of TK + auto TK = Fourier(TB); + + // loop over the triangles + for (int tri = 0; tri < ntri; tri++) { + a = triangles(pt,range()); + pt++; + b = triangles(pt,range()); + pt++; + c = triangles(pt,range()); + pt++; + g = ((a+b+c)/3.0-a)/double(ndiv); + + // the area around a k point might be different from one triangle to the other + // so I use it to weight the sum in the dos + double area = abs(0.5*((b(0)-a(0))*(c(1)-a(1))-(b(1)-a(1))*(c(0)-a(0)))/(ndiv*ndiv)); + + for (size_t i = 0; iepsmax) epsmax=energ(k_index); + if (energ(k_index) epsilon(neps); + double deps=(epsmax-epsmin)/neps; + for (size_t i =0; i< neps; ++i) epsilon(i)= epsmin+i/(neps-1.0)*(epsmax-epsmin); + + // bin the eigenvalues according to their energy + int ind; + double totalweight(0.0); + dos() = 0.0; + for (size_t j = 0; j < nk; j++) { + ind=int((energ(j)-epsmin)/deps); + if (ind == int(neps)) ind--; + dos(ind) += weight(j); + totalweight += weight(j); + } + dos /= deps;// Normalize the DOS + return std::make_pair(epsilon, dos); + } + + + + + + }} + diff --git a/triqs/lattice/tight_binding.cpp.new b/triqs/lattice/tight_binding.cpp.new new file mode 100644 index 00000000..24f7b2b0 --- /dev/null +++ b/triqs/lattice/tight_binding.cpp.new @@ -0,0 +1,295 @@ +#include "tight_binding.hpp" + +#include +#include +#include +#include +#include "grid_generator.hpp" +#include "functors.hpp" + +using namespace std; +namespace triqs { namespace lattice_tools { + using namespace tqa; + + tight_binding::tight_binding(bravais_lattice const & bl__, map_type const & t_r) : bl_(bl__),tr(t_r) {check();} + + tight_binding::tight_binding(bravais_lattice const & bl__,boost::python::object dct) : + bl_(bl__), tr(triqs::python_tools::Py_to_C::convert::invoke(dct)) {check();} + + void tight_binding::check() { + const size_t no = bl_.n_orbitals(); + for (map_type::const_iterator it = tr.begin(); it !=tr.end(); ++it) { + if (it->second.len(0) != no) throw triqs::runtime_error()<<"tight_binding construction : the first dim matrix is of size "<< it->second.len(0) <<" instead of "<< no; + if (it->second.len(1) != no) throw triqs::runtime_error()<<"tight_binding construction : the second dim matrix is of size "<< it->second.len(1) <<" instead of "<< no; + } + } + + //------------------------------------------------------ + + array_view hopping_stack (tight_binding const & TB, array const & k_stack) { + result_of::Fourier::type TK = Fourier(TB); + array res(TB.n_bands(), TB.n_bands(), k_stack.len(1)); + for(size_t i = 0; i energies_on_bz_path(tight_binding const & TB, K_view_type K1, K_view_type K2, size_t n_pts) { + + result_of::Fourier::type TK = Fourier(TB); + const size_t norb=TB.lattice().n_orbitals(); + const size_t ndim=TB.lattice().dim(); + array eval(norb,n_pts); + K_type dk = (K2 - K1)/double(n_pts), k = K1; + for (size_t i =0; i energies_on_bz_grid(tight_binding const & TB, size_t n_pts) { + + result_of::Fourier::type TK = Fourier(TB); + const size_t norb=TB.lattice().n_orbitals(); + const size_t ndim=TB.lattice().dim(); + grid_generator grid(ndim,n_pts); + array eval(norb,grid.size()); + for (; grid ; ++grid) { + eval(range(),grid.index()) = linalg::eigenvalues( TK( (*grid) (range(0,ndim))), false); + } + return eval; + } + + //------------------------------------------------------ + + struct bz_grid { + + const brillouin_zone bz; + const size_t nkpts, dim; + const size_t N_Z,N_Y,N_X; + + size_t size () const { return (N_X * N_Y * N_Z);} + + bz_grid( brillouin_zone const & bz_, size_t nkpts_) : + bz(bz_), + nkpts(nkpts_), dim (bz.lattice().dim()), + N_X (nkpts), N_Y (dim>1 ? nkpts : 1), N_Z (dim>2 ? nkpts : 1) {} + + template + void foreach(F f) { + K_type k(3); + for (int nz = 0; nz < N_Z; nz++) + for (int ny = 0; ny < N_Y; ny++) + for (int nx = 0; nx < N_X; nx++) { + k(0) = nx/double(N_X); + k(1) = ny/double(N_Y); + k(2) = nz/double(N_Z); + f(k); + } + } + }; + + +#ifndef TRIQS_HAS_CPP11_LAMBDA + void lambda_loop( result_of::Fourier::type const & TK, + array & evec, array & eval, + size_t & index, size_t ndim, K_type const & k) { + array_view eval_sl = eval(range(),index); + array_view evec_sl = evec(range(),range(),index); + boost::tie (eval_sl,evec_sl) = linalg::eigenelements( TK( k(range(0,ndim)))) ;//, true); + index++; + } + +}} +#include +#include +namespace triqs { namespace lattice_tools { + + namespace BLL=boost::lambda; + using boost::ref; + using boost::cref; +#endif + + + std::pair, array > dos(tight_binding const & TB, size_t nkpts, size_t neps) { + + // The Fourier transform of TK + // auto TK = Fourier(TB); // C++0x .... + result_of::Fourier::type TK = Fourier(TB); + + // loop on the BZ + const size_t ndim=TB.lattice().dim(); + const size_t norb=TB.lattice().n_orbitals(); + + bz_grid grid(brillouin_zone(TB.lattice()),nkpts); + //grid_generator grid(ndim,nkpts); + array tempeval(norb); + array evec(norb,norb,grid.size()); + array eval(norb,grid.size()); + size_t index=0; +#ifdef TRIQS_HAS_CPP11_LAMBDA + grid.foreach([&] { + array_view eval_sl = eval(range(),index); + array_view evec_sl = evec(range(),range(),index); + boost::tie (eval_sl,evec_sl) = linalg::eigenelements( TK( k(range(0,ndim))), true); + index++; + }); + +#else + + int N_X (nkpts), N_Y (ndim>1 ? nkpts : 1), N_Z (ndim>2 ? nkpts : 1); + K_type k(3); + for (int nz = 0; nz < N_Z; nz++) + for (int ny = 0; ny < N_Y; ny++) + for (int nx = 0; nx < N_X; nx++) { + k(0) = nx/double(N_X); + k(1) = ny/double(N_Y); + k(2) = nz/double(N_Z); + array_view eval_sl = eval(range(),index); + array_view evec_sl = evec(range(),range(),index); + boost::tie (eval_sl,evec_sl) = linalg::eigenelements( TK( k(range(0,ndim)))) ;//, true); + index++; + } + + +// grid.foreach(BLL::bind(lambda_loop,cref(TK),ref(evec),ref(eval),ref(index),ndim,BLL::_1)); +#endif + +/* + for (; grid ; ++grid) { +//cerr<<" index = "< eval_sl = eval(range(),grid.index()); +array_view evec_sl = evec(range(),range(),grid.index()); +boost::tie (eval_sl,evec_sl) = linalg::eigenelements( TK( (*grid) (range(0,ndim))), true); +//cerr<< " point "<< *grid << " value "<< eval_sl<< endl; //" "<< (*grid) (range(0,ndim)) << endl; +} + */ +// define the epsilon mesh, etc. +array epsilon(neps); +double epsmax = tqa::max_element(eval); +double epsmin = tqa::min_element(eval); +double deps=(epsmax-epsmin)/neps; +//for (size_t i =0; i< neps; ++i) epsilon(i)= epsmin+i/(neps-1.0)*(epsmax-epsmin); +for (size_t i =0; i< neps; ++i) epsilon(i)=epsmin+(i+0.5)*deps; + +// bin the eigenvalues according to their energy +// NOTE: a is defined as an integer. it is the index for the DOS. +//REPORT <<"Starting Binning ...."< rho (neps,norb);rho()=0; +for(size_t l=0;l, array > dos_patch(tight_binding const & TB, const array & triangles, size_t neps, size_t ndiv) { + // WARNING: This version only works for a single band Hamiltonian in 2 dimensions!!!! + // triangles is an array of points defining the triangles of the patch + // neps in the number of bins in energy + // ndiv in the number of divisions used to divide the triangles + + //const size_t ndim=TB.lattice().dim(); + //const size_t norb=TB.lattice().n_orbitals(); + int ntri = triangles.len(0)/3; + array dos(neps); + + // Check consistency + const size_t ndim=TB.lattice().dim(); + //const size_t norb=TB.lattice().n_orbitals(); + if (ndim !=2) throw triqs::runtime_error()<<"dos_patch : dimension 2 only !"; + if (triangles.len(1) != ndim) throw triqs::runtime_error()<<"dos_patch : the second dimension of the 'triangle' array in not "< thop(1,1); + array energ(nk), weight(nk); + + // a, b, c are the corners of the triangle + // g the center of gravity taken from a + array a(ndim), b(ndim), c(ndim), g(ndim), rv(ndim); + int pt = 0; + double s, t; + + // The Fourier transform of TK + // auto TK = Fourier(TB); // C++0x .... + result_of::Fourier::type TK = Fourier(TB); + + // loop over the triangles + for (int tri = 0; tri < ntri; tri++) { + a = triangles(pt,range()); + pt++; + b = triangles(pt,range()); + pt++; + c = triangles(pt,range()); + pt++; + g = ((a+b+c)/3.0-a)/double(ndiv); + + // the area around a k point might be different from one triangle to the other + // so I use it to weight the sum in the dos + double area = abs(0.5*((b(0)-a(0))*(c(1)-a(1))-(b(1)-a(1))*(c(0)-a(0)))/(ndiv*ndiv)); + + for (size_t i = 0; iepsmax) epsmax=energ(k_index); + if (energ(k_index) epsilon(neps); + double deps=(epsmax-epsmin)/neps; + for (size_t i =0; i< neps; ++i) epsilon(i)= epsmin+i/(neps-1.0)*(epsmax-epsmin); + + // bin the eigenvalues according to their energy + int ind; + double totalweight(0.0); + dos() = 0.0; + for (size_t j = 0; j < nk; j++) { + ind=int((energ(j)-epsmin)/deps); + if (ind == int(neps)) ind--; + dos(ind) += weight(j); + totalweight += weight(j); + } + dos /= deps;// Normalize the DOS + return std::make_pair(epsilon, dos); +} + + + + + +}} + diff --git a/triqs/lattice/tight_binding.hpp b/triqs/lattice/tight_binding.hpp new file mode 100644 index 00000000..a9b0d60c --- /dev/null +++ b/triqs/lattice/tight_binding.hpp @@ -0,0 +1,91 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_LATTICE_TIGHTBINDINGS_H +#define TRIQS_LATTICE_TIGHTBINDINGS_H +#include "bravais_lattice_and_brillouin_zone.hpp" + +namespace triqs { namespace lattice_tools { + + /** + For tightbinding Hamiltonian with fully localised orbitals + Model the ShortRangeFunctionOnBravaisLattice concept. + Overlap between orbital is taken as unit matrix. + */ + class tight_binding { + typedef std::vector, matrix>> displ_value_stack_t; + displ_value_stack_t displ_value_stack; + bravais_lattice bl_; + public : + typedef std::vector arg_type; + + /// + tight_binding (bravais_lattice const & bl) : bl_(bl) {}; + + /// Underlying lattice + bravais_lattice const & lattice() const { return bl_;} + + /// Number of bands, i.e. size of the matrix t(k) + size_t n_bands() const { return bl_.n_orbitals();} + + /** + * Push_back mechanism of a pair displacement -> matrix + * VectorIntType is anything from which a std::vector can be constructed + * MatrixDComplexType is anything from which a matrix can be constructed + */ + template + void push_back(VectorIntType && v, MatrixDComplexType && m) { + std::vector V(std::forward(v)); + if (v.size() != bl_.dim()) TRIQS_RUNTIME_ERROR<<"tight_binding : displacement of incorrect size : got "<< v.size() << "instead of "<< bl_.dim(); + matrix M(std::forward(m)); + if (M.len(0) != n_bands()) TRIQS_RUNTIME_ERROR<<"tight_binding : the first dim matrix is of size "<< M.len(0) <<" instead of "<< n_bands(); + if (M.len(1) != n_bands()) TRIQS_RUNTIME_ERROR<<"tight_binding : the first dim matrix is of size "<< M.len(1) <<" instead of "<< n_bands(); + displ_value_stack.push_back(std::make_pair(std::move(V), std::move(M))); + } + + void reserve(size_t n) { displ_value_stack.reserve(n);} + + // iterators + typedef displ_value_stack_t::const_iterator const_iterator; + typedef displ_value_stack_t::iterator iterator; + const_iterator begin() const { return displ_value_stack.begin();} + const_iterator end() const { return displ_value_stack.end();} + iterator begin() { return displ_value_stack.begin();} + iterator end() { return displ_value_stack.end();} + }; + + /** + Factorized version of hopping (for speed) + k_in[:,n] is the nth vector + In the result, R[:,:,n] is the corresponding hopping t(k) + */ + array_view hopping_stack (tight_binding const & TB, array_view const & k_stack); + // not optimal ordering here + + std::pair, array > dos(tight_binding const & TB, size_t nkpts, size_t neps); + std::pair, array > dos_patch(tight_binding const & TB, const array & triangles, size_t neps, size_t ndiv); + array_view energies_on_bz_path(tight_binding const & TB, K_view_type K1, K_view_type K2, size_t n_pts); + array_view energies_on_bz_grid(tight_binding const & TB, size_t n_pts); + +}} + +#endif + + diff --git a/triqs/mc_tools/MersenneRNG.cpp b/triqs/mc_tools/MersenneRNG.cpp new file mode 100644 index 00000000..f3752b5d --- /dev/null +++ b/triqs/mc_tools/MersenneRNG.cpp @@ -0,0 +1,41 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#include "MersenneRNG.hpp" + +namespace triqs { +namespace mc_tools { + namespace RandomGenerators{ + + double RandMT::eval() { +#ifdef DEBUG + double r = (double)(randomMT())/0xFFFFFFFFU; + std::cout<<"RANDOM "<. + * + ******************************************************************************/ + +#ifndef MERSENNE_RNG_H +#define MERSENNE_RNG_H + +#include +#include +#include +#include + +//#include +namespace triqs { +namespace mc_tools { +namespace RandomGenerators{ + + +// This is the ``Mersenne Twister'' random number generator MT19937, which +// generates pseudorandom integers uniformly distributed in 0..(2^32 - 1) +// starting from any odd seed in 0..(2^32 - 1). This version is a recode +// by Shawn Cokus (Cokus@math.washington.edu) on March 8, 1998 of a version by +// Takuji Nishimura (who had suggestions from Topher Cooper and Marc Rieffel in +// July-August 1997). +// +// Effectiveness of the recoding (on Goedel2.math.washington.edu, a DEC Alpha +// running OSF/1) using GCC -O3 as a compiler: before recoding: 51.6 sec. to +// generate 300 million random numbers; after recoding: 24.0 sec. for the same +// (i.e., 46.5% of original time), so speed is now about 12.5 million random +// number generations per second on this machine. +// +// According to the URL +// (and paraphrasing a bit in places), the Mersenne Twister is ``designed +// with consideration of the flaws of various existing generators,'' has +// a period of 2^19937 - 1, gives a sequence that is 623-dimensionally +// equidistributed, and ``has passed many stringent tests, including the +// die-hard test of G. Marsaglia and the load test of P. Hellekalek and +// S. Wegenkittl.'' It is efficient in memory usage (typically using 2506 +// to 5012 bytes of static data, depending on data type sizes, and the code +// is quite short as well). It generates random numbers in batches of 624 +// at a time, so the caching and pipelining of modern systems is exploited. +// It is also divide- and mod-free. +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Library General Public License as published by +// the Free Software Foundation (either version 2 of the License or, at your +// option, any later version). This library 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 Library General Public License for more details. You should have +// received a copy of the GNU Library General Public License along with this +// library; if not, write to the Free Software Foundation, Inc., 59 Temple +// Place, Suite 330, Boston, MA 02111-1307, USA. +// +// The code as Shawn received it included the following notice: +// +// Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. When +// you use this, send an e-mail to with +// an appropriate reference to your work. +// +// It would be nice to CC: when you write. +// +// RandMT class created by Paul Gresham +// There seems to be a slight performance deficit in process creation +// however I've not profiled the class to compare it with the straight +// C code. +// +// Use of a class removes many C nasties and also allows you to easily +// create multiple generators. +// To compile on GNU a simple line is: +// g++ -O3 RandMT.cc -o RandMT +// + +typedef unsigned long uint32; + +class RandMT { + + static const int N = 624; // length of state vector + static const int M = 397; // a period parameter + static const uint32 K = 0x9908B0DFU; // a magic constant + + // If you want a single generator, consider using a singleton class + // instead of trying to make these static. + uint32 state[N+1]; // state vector + 1 extra to not violate ANSI C + uint32 *next; // next random value is computed from here + uint32 initseed; // + int left; // can *next++ this many times before reloading + + inline uint32 hiBit(uint32 u) { + return u & 0x80000000U; // mask all but highest bit of u + } + + inline uint32 loBit(uint32 u) { + return u & 0x00000001U; // mask all but lowest bit of u + } + + inline uint32 loBits(uint32 u) { + return u & 0x7FFFFFFFU; // mask the highest bit of u + } + + inline uint32 mixBits(uint32 u, uint32 v) { + return hiBit(u)|loBits(v); // move hi bit of u to hi bit of v + } + + uint32 reloadMT(void) { + register uint32 *p0=state, *p2=state+2, *pM=state+M, s0, s1; + register int j; + + if(left < -1) + seedMT(initseed); + + left=N-1, next=state+1; + + for(s0=state[0], s1=state[1], j=N-M+1; --j; s0=s1, s1=*p2++) + *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); + + for(pM=state, j=M; --j; s0=s1, s1=*p2++) + *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); + + s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); + s1 ^= (s1 >> 11); + s1 ^= (s1 << 7) & 0x9D2C5680U; + s1 ^= (s1 << 15) & 0xEFC60000U; + return(s1 ^ (s1 >> 18)); + } + + uint32 seed_save; + +public: + + RandMT() { + seedMT(1U); + } + + RandMT(uint32 seed) { + seedMT(seed); + } + + RandMT( RandMT const & R) { + seedMT(R.seed_save); + } + + void seedMT(uint32 seed) { + + seed_save = seed; + + // + // We initialize state[0..(N-1)] via the generator + // + // x_new = (69069 * x_old) mod 2^32 + // + // from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's + // _The Art of Computer Programming_, Volume 2, 3rd ed. + // + // Notes (SJC): I do not know what the initial state requirements + // of the Mersenne Twister are, but it seems this seeding generator + // could be better. It achieves the maximum period for its modulus + // (2^30) iff x_initial is odd (p. 20-21, Sec. 3.2.1.2, Knuth); if + // x_initial can be even, you have sequences like 0, 0, 0, ...; + // 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...; 2^29, 2^29 + 2^31, + // 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd below. + // + // Even if x_initial is odd, if x_initial is 1 mod 4 then + // + // the lowest bit of x is always 1, + // the next-to-lowest bit of x is always 0, + // the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , + // the 3rd-from-lowest bit of x 4-cycles ... 0 1 1 0 0 1 1 0 ... , + // the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... , + // ... + // + // and if x_initial is 3 mod 4 then + // + // the lowest bit of x is always 1, + // the next-to-lowest bit of x is always 1, + // the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , + // the 3rd-from-lowest bit of x 4-cycles ... 0 0 1 1 0 0 1 1 ... , + // the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... , + // ... + // + // The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is + // 16, which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It + // also does well in the dimension 2..5 spectral tests, but it could be + // better in dimension 6 (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth). + // + // Note that the random number user does not see the values generated + // here directly since reloadMT() will always munge them first, so maybe + // none of all of this matters. In fact, the seed values made here could + // even be extra-special desirable if the Mersenne Twister theory says + // so-- that's why the only change I made is to restrict to odd seeds. + // + initseed = seed; + + register uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = state; + register int j; + left = 0; + for(*s++=x, j=N; --j; *s++ = (x*=69069U) & 0xFFFFFFFFU); + } + + + + inline uint32 randomMT(void) { + uint32 y; + + if(--left < 0) + return(reloadMT()); + + y = *next++; + y ^= (y >> 11); + y ^= (y << 7) & 0x9D2C5680U; + y ^= (y << 15) & 0xEFC60000U; + return(y ^ (y >> 18)); + } + + double operator()() { return DBL_EPSILON+eval()*(1-2*DBL_EPSILON);} + + double eval(); +// inline of this causes a BIG pb with g++ 4.1.2. WHY ????? +// inline double operator()() { +// return ((double)(randomMT())/0xFFFFFFFFU); +// } + +}; + +}}} + +#endif diff --git a/triqs/mc_tools/full_update_mechanism.hpp b/triqs/mc_tools/full_update_mechanism.hpp new file mode 100644 index 00000000..348f06c3 --- /dev/null +++ b/triqs/mc_tools/full_update_mechanism.hpp @@ -0,0 +1,76 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef FULL_UPDATE_H_jh93n8 +#define FULL_UPDATE_H_jh93n8 + +/* + * Usage : create such an object + * transform it into boost::function and pass it as AfterCycleDuty +*/ +class full_update_mechanism { + int iter_fastup,nfastup; + double FullUpdate_diff_ALERT, FullUpdate_diff_increase, FullUpdate_diff_reduce; + triqs::utility::report_stream & REPORT; + + public : + full_update_mechanism (triqs::utility::report_stream & rep_, + int NbreFastIteration_Init, int FullUpdate_diff_ALERT_, int FullUpdate_diff_increase_, int FullUpdate_diff_reduce_): REPORT(rep) { + // fast update mechanism + nfastup=NbreFastIteration_Init; + iter_fastup=0; + FullUpdate_diff_ALERT = FullUpdate_diff_ALERT_; + FullUpdate_diff_increase= FullUpdate_diff_increase_; + FullUpdate_diff_reduce = FullUpdate_diff_reduce_; + } + + virtual ~full_update_mechanism() {} + + virtual double fullUpdate(){return 0;} + + bool operator()() { + + //Update the FullUpdate data if necessary + iter_fastup++; + // Here we take some decision, depending whether nfastup is too big, too small ,etc + if ((nfastup>=0) && (iter_fastup>=nfastup)) { + iter_fastup=0; + // Now updating cleanly + double diff=this->fullUpdate(); + //REPORT << "Full update done" << endl; + if (diff > FullUpdate_diff_ALERT) + REPORT <<"Full update : diff="<< diff <<" WARNING : Fast Update deviation too big "< FullUpdate_diff_reduce) {bo=true;nfastup=max(1,nfastup/2);} + if (bo) { + REPORT << "diff="< +// Brigitte Surer +// Bela Bauer +// +// downgraded by O. Parcollet for compilation with icc11 & boost 1.45 +// +// Use, modification, and distribution are subject to the Boost Software +// License, Version 1.0. (See at .) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ + template class generator { + public: + static std::size_t const buffer_size = 1000; + template generator(Generator const & gen, std::size_t size = buffer_size) + : + buf(make_shared(gen, size)) + , cur(buf->cur) + , end(buf->end()) + {} + inline R const operator()() { + if (cur == end) + buf->fill(); + return *cur++; + } + generator(generator const & rhs) + : + buf(new buffer (*rhs.buf)) + , cur(buf->cur) + , end(buf->end()) + {} + generator & operator=(generator rhs) { + swap(*this, rhs); + return *this; + } + private: + class buffer: public std::vector { + public: + friend class generator; + template buffer(Generator const & gen, std::size_t size) + : std::vector(size) + , engine(make_shared(gen)) + , cur(this->end()) + , fill_helper(lambda::bind(std::generate, lambda::_1, lambda::_2, ref(*reinterpret_cast(engine.get())))) + , clone(lambda::bind(buffer::template type_keeper, lambda::_1, lambda::_2)) + {} + template buffer(reference_wrapper gen, std::size_t size) + : std::vector(size) + , cur(this->end()) + , fill_helper(lambda::bind(std::generate, lambda::_1, lambda::_2, gen)) + {} + buffer(buffer const & rhs) + : std::vector(rhs) + , cur(this->begin() + (rhs.cur - rhs.begin())) + , fill_helper(rhs.fill_helper) + , clone(rhs.clone) + { + if (rhs.engine) + clone(*this, rhs); + } + inline void fill() { + fill_helper(this->begin(), this->end()); + cur = this->begin(); + } + private: + template static void type_keeper(buffer & lhs, buffer const & rhs) { + lhs.engine = make_shared(*reinterpret_cast(rhs.engine.get())); + lhs.fill_helper = lambda::bind(std::generate, lambda::_1, lambda::_2, ref(*reinterpret_cast(lhs.engine.get()))); + } + shared_ptr engine; + typename std::vector::const_iterator cur; + function::iterator, typename std::vector::iterator)> fill_helper; + function clone; + }; + + shared_ptr buf; + typename buffer::const_iterator & cur; + typename buffer::const_iterator end; + }; +} diff --git a/triqs/mc_tools/histograms.hpp b/triqs/mc_tools/histograms.hpp new file mode 100644 index 00000000..7b26388e --- /dev/null +++ b/triqs/mc_tools/histograms.hpp @@ -0,0 +1,111 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef STATISTIC_HISTOGRAM_H +#define STATISTIC_HISTOGRAM_H + +#include +#include +#include + +namespace triqs { +namespace mc_tools { + + /** + Histograms for a MonteCarlo run. + For integer in [0,Size] + */ + class histogram { + protected: + int del; + std::vector data; + + public : + /** */ + histogram(int Size):del(0),data(Size,0){} + + /** */ + histogram & operator<<(unsigned int i) + { if (i>data.size()) del++;else data[i]++; return *this;} + + /** */ + inline void reset(){del=0; for (unsigned int u=0; u0)) throw "histogram_binned construction : one must have a=0); + histogram::operator<< (static_cast(i) ); + return *this; + } + + /** */ + void save(std::ostream & where){ + double norm = std::accumulate(data.begin(), data.end(), 0); + for ( unsigned int i =0; i HistogramBinnedMap; + typedef std::map HistogramMap; + + +} +}// end namespaces + +#endif + + + + diff --git a/triqs/mc_tools/impl_tools.hpp b/triqs/mc_tools/impl_tools.hpp new file mode 100644 index 00000000..d8b5d49e --- /dev/null +++ b/triqs/mc_tools/impl_tools.hpp @@ -0,0 +1,57 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_TOOLS_MC_IMPL_TOOLS_H +#define TRIQS_TOOLS_MC_IMPL_TOOLS_H +#include +#include +#include + +namespace triqs { namespace mc_tools { + + template struct has_h5_read : std::false_type {}; + template struct has_h5_read(), std::string(), std::declval()))> : std::true_type {}; + + template struct has_h5_write : std::false_type {}; + template struct has_h5_write(), std::string(), std::declval()))> : std::true_type {}; + + typedef std::function h5_rw_lambda_t; + + // given a pointer to an object, synthesize h5_read/write function for this object + template h5_rw_lambda_t make_h5_write_impl(T * p, std::true_type) { + return [p](h5::group F, std::string const &Name) {h5_write(F,Name, *p);}; + } + template h5_rw_lambda_t make_h5_read_impl(T * p, std::true_type) { + return [p](h5::group F, std::string const &Name) {h5_read(F,Name, *p);}; + } + template h5_rw_lambda_t make_h5_read_impl (T * p, std::false_type) { return h5_rw_lambda_t();} + template h5_rw_lambda_t make_h5_write_impl(T * p, std::false_type) { return h5_rw_lambda_t();} + + template h5_rw_lambda_t make_h5_write(T * p) { return make_h5_write_impl(p,std::integral_constant::value>());} + template h5_rw_lambda_t make_h5_read (T * p) { return make_h5_read_impl (p,std::integral_constant::value>());} + + // move_construtible is not in gcc 4.6 std lib + template + struct is_move_constructible : std::is_constructible::type> {}; + +}}// end namespace +#endif + + diff --git a/triqs/mc_tools/mc_basic_step.hpp b/triqs/mc_tools/mc_basic_step.hpp new file mode 100644 index 00000000..e0d42778 --- /dev/null +++ b/triqs/mc_tools/mc_basic_step.hpp @@ -0,0 +1,51 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef MC_STEPS_H +#define MC_STEPS_H + +#include +#include "mc_move_set.hpp" + +namespace triqs { namespace mc_tools { namespace Step { + + // Performs one Metropolis step + template + struct Metropolis { + static void do_it (move_set & MoveGroup, random_generator & RNG, MCSignType & signe){ + double r = MoveGroup.attempt(); + if (RNG() < std::min(1.0,r)) { + signe *= MoveGroup.accept(); +#ifdef DEBUG + std::cerr<<" Metropolis sign = "<< signe <. + * + ******************************************************************************/ +#ifndef TRIQS_TOOLS_MC_GENERIC_H +#define TRIQS_TOOLS_MC_GENERIC_H +#include +#include +#include +#include +#include "./mc_measure_set.hpp" +#include "./mc_move_set.hpp" +#include "./mc_basic_step.hpp" +#include "./random_generator.hpp" + +namespace triqs { namespace mc_tools { + + /** + * \brief Generic Monte Carlo class. + */ + template > + class mc_generic { + + public: + + /** + * Constructor from a set of parameters + */ + mc_generic(uint64_t N_Cycles, uint64_t Length_Cycle, uint64_t N_Warmup_Cycles, std::string Random_Name, int Random_Seed, int Verbosity, + std::function AfterCycleDuty = std::function() ) : + RandomGenerator(Random_Name, Random_Seed), + AllMoves(RandomGenerator), + AllMeasures(), + report(&std::cout, Verbosity), + Length_MC_Cycle(Length_Cycle), + NWarmIterations(N_Warmup_Cycles), + NCycles(N_Cycles), + after_cycle_duty(AfterCycleDuty), + sign_av(0) {} + + /** + * Constructor from a dictionnary + * \param[in] P dictionary parameters + * \param[in] AfterCycleDuty a function bool() to be called after each QMC cycle + */ + mc_generic(utility::parameters const & P, std::function AfterCycleDuty = std::function() ) : + RandomGenerator(std::string(P["Random_Generator_Name"]), long(P["Random_Seed"])), + //RandomGenerator(P["Random_Generator_Name"]), P.value_or_default("Random_Seed",1)), + report(&std::cout,int(P["Verbosity"])), + AllMoves(RandomGenerator), + AllMeasures(), + Length_MC_Cycle(long(P["Length_Cycle"])), /// NOT NICE THIS EXPLICIT CAST : no unsigned in parameters, really ?? + NWarmIterations(long(P["N_Warmup_Cycles"])), + NCycles(long(P["N_Cycles"])), + after_cycle_duty(AfterCycleDuty), + sign_av(0) {} + + /** + * Register move M with its probability of being proposed. + * NB : the proposition_probability needs to be >0 but does not need to be + * normalized. Normalization is automatically done with all the added moves + * before starting the run + */ + template + void add_move (MoveType && M, std::string name, double proposition_probability = 1.0) { + static_assert( !std::is_pointer::value, "add_move in mc_generic takes ONLY values !"); + AllMoves.add(std::forward(M), name, proposition_probability); + } + + /** + * Register the Measure M + */ + template + void add_measure (MeasureType && M, std::string name) { + static_assert( !std::is_pointer::value, "add_measure in mc_generic takes ONLY values !"); + AllMeasures.insert(std::forward(M), name); + } + + /// get the average sign (to be called after collect_results) + MCSignType average_sign() const { return sign_av; } + + /// get the current percents done + uint64_t percent() const { return done_percent; } + + // An access to the random number generator + random_generator & rng(){ return RandomGenerator;} + + /// Start the Monte Carlo + bool start(MCSignType sign_init, std::function const & stop_callback) { + assert(stop_callback); + Timer.start(); + sign = sign_init; done_percent = 0; nmeasures = 0; + sum_sign = 0; + bool stop_it=false, finished = false; + uint64_t NCycles_tot = NCycles+ NWarmIterations; + report << std::endl << std::flush; + for (NC =0; !stop_it; ++NC) { + for (uint64_t k=1; (k<=Length_MC_Cycle); k++) { MCStepType::do_it(AllMoves,RandomGenerator,sign); } + if (after_cycle_duty) {after_cycle_duty();} + if (thermalized()) { + nmeasures++; + sum_sign += sign; + AllMeasures.accumulate(sign); + } + // recompute fraction done + uint64_t dp = uint64_t(floor( ( NC*100.0) / (NCycles_tot-1))); + if (dp>done_percent) { done_percent=dp; report << done_percent; report<<"%; "; report <= NCycles_tot -1) || converged () ); + stop_it = (stop_callback() || finished); + } + report << std::endl << std::endl << std::flush; + Timer.stop(); + return finished; + + } + + /// Reduce the results of the measures, and reports some statistics + void collect_results(boost::mpi::communicator const & c) { + + uint64_t nmeasures_tot; + MCSignType sum_sign_tot; + boost::mpi::reduce(c, nmeasures, nmeasures_tot, std::plus(), 0); + boost::mpi::reduce(c, sum_sign, sum_sign_tot, std::plus(), 0); + + sign_av = sum_sign_tot / double(nmeasures_tot); + + report(3) << "[Node "< MeasureType & get_measure(std::string const & name) { return AllMeasures.template get (name); } + template MeasureType const & get_measure(std::string const & name) const { return AllMeasures.template get (name); } + + template MoveType & get_move (std::string const & name) { return AllMoves.template get (name); } + template MoveType const & get_move (std::string const & name) const { return AllMoves.template get (name); } + + /// HDF5 interface + friend void h5_write (h5::group g, std::string const & name, mc_generic const & mc){ + auto gr = g.create_group(name); + h5_write(gr,"moves", mc.AllMoves); + h5_write(gr,"measures", mc.AllMeasures); + h5_write(gr,"length_monte_carlo_cycle", mc.Length_MC_Cycle); + h5_write(gr,"number_cycle_requested", mc.NCycles); + h5_write(gr,"number_warming_cycle_requested", mc.NWarmIterations); + h5_write(gr,"number_cycle_done", mc.NC); + h5_write(gr,"number_measure_done", mc.nmeasures); + h5_write(gr,"sign", mc.sign); + h5_write(gr,"sum_sign", mc.sum_sign); + } + + /// HDF5 interface + friend void h5_read (h5::group g, std::string const & name, mc_generic & mc){ + auto gr = g.open_group(name); + h5_read(gr,"moves", mc.AllMoves); + h5_read(gr,"measures", mc.AllMeasures); + h5_read(gr,"length_monte_carlo_cycle", mc.Length_MC_Cycle); + h5_read(gr,"number_cycle_requested", mc.NCycles); + h5_read(gr,"number_warming_cycle_requested", mc.NWarmIterations); + h5_read(gr,"number_cycle_done", mc.NC); + h5_read(gr,"number_measure_done", mc.nmeasures); + h5_read(gr,"sign", mc.sign); + h5_read(gr,"sum_sign", mc.sum_sign); + } + + private: + random_generator RandomGenerator; + move_set AllMoves; + measure_set AllMeasures; + utility::report_stream report; + uint64_t Length_MC_Cycle;/// Length of one Monte-Carlo cycle between 2 measures + uint64_t NWarmIterations, NCycles; + uint64_t nmeasures; + MCSignType sum_sign; + utility::timer Timer; + std::function after_cycle_duty; + MCSignType sign, sign_av; + uint64_t NC,done_percent;// NC = number of the cycle + + bool thermalized() const { return (NC>= NWarmIterations);} + bool converged() const { return false;} + }; + + + /// Retrieve a Measure given name and type. NB : the type is checked at runtime + template M & get_measure(mc_generic & s, std::string const & name) { return s.template get_measure (name); } + template M const & get_measure(mc_generic const & s, std::string const & name) { return s.template get_measure (name); } + + /// Retrieve a Move given name and type. NB : the type is checked at runtime + template M & get_move(mc_generic & s, std::string const & name) { return s.template get_move (name); } + template M const & get_move(mc_generic const & s, std::string const & name) { return s.template get_move (name); } + +}}// end namespace +#endif + diff --git a/triqs/mc_tools/mc_measure_set.hpp b/triqs/mc_tools/mc_measure_set.hpp new file mode 100644 index 00000000..fbd6500f --- /dev/null +++ b/triqs/mc_tools/mc_measure_set.hpp @@ -0,0 +1,193 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_TOOLS_MC_MEASURE2_H +#define TRIQS_TOOLS_MC_MEASURE2_H + +#include +#include +#include +#include +#include "./impl_tools.hpp" + +namespace triqs { namespace mc_tools { + + // mini concept checking + template struct has_accumulate : std::false_type {}; + template struct has_accumulate ().accumulate(MCSignType()))> : std::true_type {}; + + template struct has_collect_result : std::false_type {}; + template struct has_collect_result < T, decltype(std::declval().collect_results(std::declval()))> : std::true_type {}; + + //-------------------------------------------------------------------- + + template + class measure { + + std::shared_ptr impl_; + std::function clone_; + size_t hash_; + std::string type_name_; + + std::function accumulate_; + std::function collect_results_; + std::function h5_r, h5_w; + + uint64_t count_; + + template + void construct_delegation (MeasureType * p) { + impl_= std::shared_ptr (p); + clone_ = [p]() { return MeasureType(*p);} ; + hash_ = typeid(MeasureType).hash_code(); + type_name_ = typeid(MeasureType).name(); + accumulate_ = [p](MCSignType const & x) { p->accumulate(x);}; + count_ = 0; + collect_results_ = [p] ( boost::mpi::communicator const & c) { p->collect_results(c);}; + h5_r = make_h5_read(p); + h5_w = make_h5_write(p); + } + + public : + + template + measure (MeasureType && p) { + static_assert( is_move_constructible::value, "This measure is not MoveConstructible"); + static_assert( has_accumulate::value, " This measure has no accumulate method !"); + static_assert( has_collect_result::value, " This measure has no collect_results method !"); + construct_delegation( new typename std::remove_reference::type(std::forward(p))); + } + + // Value semantics. Everyone at the end call move = ... + measure(measure const &rhs) {*this = rhs;} + measure(measure &rhs) {*this = rhs;} // or it will use the template = bug + measure(measure && rhs) { *this = std::move(rhs);} + measure & operator = (measure const & rhs) { *this = rhs.clone_(); return *this;} +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + measure & operator = (measure && rhs) =default; +#else + measure & operator = (measure && rhs) { + using std::swap; +#define SW(X) swap(X,rhs.X) + SW(impl_); SW(hash_); SW(type_name_); SW(clone_); + SW(accumulate_); SW(collect_results_); SW(h5_r); SW(h5_w); + SW(count_); +#undef SW + return *this; + } +#endif + + void accumulate(MCSignType signe){ assert(impl_); count_++; accumulate_(signe); } + void collect_results (boost::mpi::communicator const & c ) { collect_results_(c);} + + uint64_t count() const { return count_;} + + template bool has_type() const { return (typeid(MeasureType).hash_code() == hash_); }; + template void check_type() const { + if (!(has_type())) + TRIQS_RUNTIME_ERROR << "Trying to retrieve a measure of type "<< typeid(MeasureType).name() << " from a measure of type "<< type_name_; + }; + + template MeasureType & get() { check_type(); return *(static_cast(impl_.get())); } + template MeasureType const & get() const { check_type(); return *(static_cast(impl_.get())); } + + friend void h5_write (h5::group g, std::string const & name, measure const & m){ if (m.h5_w) m.h5_w(g,name);}; + friend void h5_read (h5::group g, std::string const & name, measure & m) { if (m.h5_r) m.h5_r(g,name);}; + }; + + //-------------------------------------------------------------------- + + template + class measure_set { + typedef measure measure_type; + std::map> m_map; + public : + + measure_set(){} + + measure_set(measure_set const &) = default; + measure_set(measure_set &&) = default; + + measure_set& operator = (measure_set const &) = default; +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + measure_set& operator = (measure_set &&) = default; + +#else + measure_set& operator = (measure_set && rhs) { + using std::swap; + swap(m_map,rhs.m_map); + return *this; + } +#endif + + /** + * Register the Measure M with a name + */ + template + void insert (MeasureType && M, std::string const & name) { + if (has(name)) TRIQS_RUNTIME_ERROR <<"measure_set : insert : measure '"<(M)))); + // not implemented on gcc 4.6's stdlibc++ ? + // m_map.emplace(name, measure_type (std::forward(M))); + } + + bool has(std::string const & name) const { return m_map.find(name) != m_map.end(); } + + void accumulate(MCSignType const & signe) { for (auto & nmp : m_map) nmp.second.accumulate(signe); } + + std::vector names() const { + std::vector res; + for (auto & nmp : m_map) res.push_back(nmp.first); + return res; + } + + // gather result for all measure, on communicator c + void collect_results (boost::mpi::communicator const & c ) { for (auto & nmp : m_map) nmp.second.collect_results(c); } + + // HDF5 interface + friend void h5_write (h5::group g, std::string const & name, measure_set const & ms){ + auto gr = g.create_group(name); + for (auto & p : ms.m_map) h5_write(gr,p.first, p.second); + } + + friend void h5_read (h5::group g, std::string const & name, measure_set & ms){ + auto gr = g.open_group(name); + for (auto & p : ms.m_map) h5_read(gr,p.first, p.second); + } + + // access to the measure, given its type, with dynamical type check + template + MeasureType & get_measure(std::string const & name) { + auto it = m_map.find (name); + if (it == m_map.end()) TRIQS_RUNTIME_ERROR << " Measure " << name << " unknown"; + return it->template get(); + } + + template + MeasureType const & get_measure(std::string const & name) const { + auto it = m_map.find (name); + if (it == m_map.end()) TRIQS_RUNTIME_ERROR << " Measure " << name << " unknown"; + return it->template get(); + } + }; + +}}// end namespace +#endif + diff --git a/triqs/mc_tools/mc_move_set.hpp b/triqs/mc_tools/mc_move_set.hpp new file mode 100644 index 00000000..660fce27 --- /dev/null +++ b/triqs/mc_tools/mc_move_set.hpp @@ -0,0 +1,312 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_TOOLS_MC_MOVE_SET2_H +#define TRIQS_TOOLS_MC_MOVE_SET2_H +#include +#include +#include +#include +#include "./random_generator.hpp" +#include "./impl_tools.hpp" + +namespace triqs { namespace mc_tools { + + // mini concept checking + template struct has_attempt : std::false_type {}; + template struct has_attempt ().attempt()))> : std::true_type {}; + + template struct has_accept : std::false_type {}; + template struct has_accept ().accept())> : std::true_type {}; + + template struct has_reject : std::false_type {}; + template struct has_reject().reject())> : std::true_type {}; + + //---------------------------------- + + template + class move { + + std::shared_ptr impl_; + std::function clone_; + size_t hash_; + std::string type_name_; + + std::function attempt_, accept_; + std::function reject_; + std::function h5_r, h5_w; + + uint64_t NProposed, Naccepted; + double acceptance_rate_; + + template + void construct_delegation (MoveType * p) { + impl_= std::shared_ptr (p); + hash_ = typeid(MoveType).hash_code(); + type_name_ = typeid(MoveType).name(); + clone_ = [p](){return MoveType(*p);}; + attempt_ = [p](){return p->attempt();}; + accept_ = [p](){return p->accept();}; + reject_ = [p](){p->reject();}; + h5_r = make_h5_read(p); // make_h5_read in impl_tools + h5_w = make_h5_write(p); + NProposed=0; + Naccepted=0; + acceptance_rate_ =-1; + } + + public : + + template + move (MoveType && p ) { + static_assert( is_move_constructible::value, "This move is not MoveConstructible"); + static_assert( has_attempt::value, "This move has no attempt method (or is has an incorrect signature) !"); + static_assert( has_accept::value, "This move has no accept method (or is has an incorrect signature) !"); + static_assert( has_reject::value, "This move has no reject method (or is has an incorrect signature) !"); + construct_delegation( new typename std::remove_reference::type(std::forward(p))); + } + + // Close to value semantics. Everyone at the end call move = ... + // no default constructor. + move(move const &rhs) {*this = rhs;} + move(move &rhs) {*this = rhs;} // to avoid clash with tempalte construction ! + move(move && rhs) { *this = std::move(rhs);} + move & operator = (move const & rhs) { *this = rhs.clone_(); return *this;} +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + move & operator = (move && rhs) = default; +#else + move & operator = (move && rhs) { // how painful is icc ! + using std::swap; +#define SW(X) swap(X,rhs.X) + SW(impl_); SW(hash_); SW(type_name_); SW(clone_); + SW(attempt_); SW(accept_); SW(reject_); SW(h5_r); SW(h5_w); + SW(NProposed);SW(Naccepted); SW(acceptance_rate_); +#undef SW + return *this; + } +#endif + + MCSignType attempt(){ NProposed++; return attempt_();} + MCSignType accept() { Naccepted++; return accept_(); } + void reject() { reject_(); } + + double acceptance_rate() const { return acceptance_rate_;} + + void collect_statistics(boost::mpi::communicator const & c) { + uint64_t nacc_tot=0, nprop_tot=1; + boost::mpi::reduce(c, Naccepted, nacc_tot, std::plus(), 0); + boost::mpi::reduce(c, NProposed, nprop_tot, std::plus(), 0); + acceptance_rate_ = nacc_tot/static_cast(nprop_tot); + } + + // true iif the stored object has type MoveType Cf hash_code doc. + template bool has_type() const { return (typeid(MoveType).hash_code() == hash_); }; + + template void check_type() const { + if (!(has_type())) + TRIQS_RUNTIME_ERROR << "Trying to retrieve a move of type "<< typeid(MoveType).name() << " from a move of type "<< type_name_; + }; + + // retrieve an object of the correct type + template MoveType & get() { check_type(); return *(static_cast(impl_.get())); } + template MoveType const & get() const { check_type(); return *(static_cast(impl_.get())); } + + // redirect the h5 call to the object lambda, if it not empty (i.e. if the underlying object can be called with h5_read/write + friend void h5_write (h5::group g, std::string const & name, move const & m){ if (m.h5_w) m.h5_w(g,name);}; + friend void h5_read (h5::group g, std::string const & name, move & m) { if (m.h5_r) m.h5_r(g,name);}; + }; + + //-------------------------------------------------------------------- + + /// A vector of (moves, proposition_probability), which is also a move itself + template + class move_set { + std::vector > move_vec; + std::vector names_; + move * current; + size_t current_move_number; + random_generator * RNG; + std::vector Proba_Moves, Proba_Moves_Acc_Sum; + MCSignType try_sign_ratio; + uint64_t debug_counter; + public: + + /// + move_set(random_generator & R): RNG(&R) { Proba_Moves.push_back(0); debug_counter=0;} + + /// + move_set(move_set const &) = default; + move_set(move_set &&) = default; + move_set& operator = (move_set const &) = default; +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + move_set& operator = (move_set &&) = default; +#else + move_set& operator = (move_set && rhs) { + using std::swap; +#define SW(X) swap(X,rhs.X) + SW(move_vec); SW(names_); SW(current); SW(current_move_number); SW(RNG); + SW(Proba_Moves); SW(Proba_Moves_Acc_Sum); SW(try_sign_ratio); SW(debug_counter); +#undef SW + return *this; + } +#endif + + /** + * Add move M with its probability of being proposed. + * NB : the proposition_probability needs to be >0 but does not need to be + * normalized. Normalization is automatically done with all the added moves + * before starting the run + */ + template + void add (MoveType && M, std::string name, double proposition_probability) { + move_vec.emplace_back(std::forward(M)); + assert(proposition_probability >=0); + Proba_Moves.push_back(proposition_probability); + names_.push_back(name); + normaliseProba();// ready to run after each add ! + } + + /** + * - Picks up one of the move at random (weighted by their proposition probability), + * - Call attempt method of that move + * - Returns the metropolis ratio R (see move concept). + * The sign ratio returned by the try method of the move is kept. + */ + double attempt() { + assert( Proba_Moves_Acc_Sum.size()>0); + // Choice of move with its probability + double proba = (*RNG)(); assert(proba>=0); + current_move_number =0; while (proba >= Proba_Moves_Acc_Sum[current_move_number] ) { current_move_number++;} + assert(current_move_number>0); assert(current_move_number<=move_vec.size()); + current_move_number--; + current = & move_vec[current_move_number]; +#ifdef TRIQS_TOOLS_MC_DEBUG + std::cerr << "*******************************************************"<< std::endl; + std::cerr << "move number : " << debug_counter++ << std::endl; + std::cerr << "Name of the proposed move: " << name_of_currently_selected() << std::endl; + std::cerr <<" Proposition probability = "<attempt(); + if (!std::isfinite(std::abs(rate_ratio))) + TRIQS_RUNTIME_ERROR<<"Monte Carlo Error : the rate is not finite in move "<=0)); + try_sign_ratio = ( abs_rate_ratio> 1.e-14 ? rate_ratio/abs_rate_ratio : 1); // keep the sign + return abs_rate_ratio; + } + + /** + * accept the move previously selected and tried. + * Returns the Sign computed as, if M is the move : + * Sign = sign (M.attempt()) * M.accept() + */ + MCSignType accept() { + MCSignType accept_sign_ratio = current->accept(); + // just make sure that accept_sign_ratio is a sign! + assert(std::abs(std::abs(accept_sign_ratio)-1.0) < 1.e-10); +#ifdef TRIQS_TOOLS_MC_DEBUG + std::cerr.setf(std::ios::scientific, std::ios::floatfield); + std::cerr<<" ... Move accepted"<reject(); + } + + /// Pretty printing of the acceptance probability of the moves. + std::string get_statistics(boost::mpi::communicator const & c, int shift = 0) { + std::ostringstream s; + for (unsigned int u =0; u< move_vec.size(); ++u) { + move_vec[u].collect_statistics(c); + for(int i=0; i()) { + auto & ms = move_vec[u].template get(); + s << "Move set " << names_[u] << ": " << move_vec[u].acceptance_rate() << "\n"; + s << ms.get_statistics(c,shift+2); + } else { + s << "Move " << names_[u] << ": " << move_vec[u].acceptance_rate() << "\n"; + } + } + return s.str(); + } + + private: + + void normaliseProba() { // Computes the normalised accumulated probability + if (move_vec.size() ==0) TRIQS_RUNTIME_ERROR<<" no moves registered"; + double acc = 0; + Proba_Moves_Acc_Sum.clear(); + for (unsigned int u = 0; u0); + for (unsigned int u = 0; u + MoveType & get_move(std::string const & name) { + int u=0; for (;u(); + } + + template + MoveType const & get_move(std::string const & name) const { + int u=0; for (;u(); + } + + };// class move_set + +}}// end namespace +#endif + diff --git a/triqs/mc_tools/random_generator.cpp b/triqs/mc_tools/random_generator.cpp new file mode 100644 index 00000000..214235d4 --- /dev/null +++ b/triqs/mc_tools/random_generator.cpp @@ -0,0 +1,81 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#include "random_generator.hpp" +#include "./MersenneRNG.hpp" +#include +//#include +#include +//#include +#include +#include +#include +#include +#include +#include +#define AS_STRING(X) AS_STRING2(X) +#define AS_STRING2(X) #X + +// List of All available Boost random number generator +#define RNG_LIST (mt19937)(mt11213b)\ +(lagged_fibonacci607) (lagged_fibonacci1279) (lagged_fibonacci2281) (lagged_fibonacci3217) (lagged_fibonacci4423)\ +(lagged_fibonacci9689) (lagged_fibonacci19937) (lagged_fibonacci23209) (lagged_fibonacci44497) (ranlux3) + + +namespace triqs { + namespace mc_tools { + + typedef boost::generator gen_type; + + inline gen_type * choose_gen(std::string const & RandomGeneratorName, std::size_t seed_, boost::shared_ptr &ptr) { + + if (RandomGeneratorName=="") return new gen_type( mc_tools::RandomGenerators::RandMT (seed_)); + + // now boost random number generators +#define DRNG(r,data,XX) if (RandomGeneratorName==AS_STRING(XX)) { \ + boost::shared_ptr localptr = boost::make_shared(seed_);\ + ptr = localptr; boost::uniform_real<> dis;\ + return new gen_type( boost::variate_generator >(*localptr,dis));} + + BOOST_PP_SEQ_FOR_EACH(DRNG,~,RNG_LIST) + + TRIQS_RUNTIME_ERROR<<"The random generator "<. + * + ******************************************************************************/ + +#ifndef POLYMORPH_RANDOM_GENERATOR_H +#define POLYMORPH_RANDOM_GENERATOR_H + +#include +#include "../utility/exceptions.hpp" +#include "./generator.hpp" +#include "math.h" +#include + +namespace triqs { +namespace mc_tools { + + /** + * This is a random generator that take the name of the random generator at construct + * and serve random numbers, buffered with a version boost::generator , + * to hide the cost of dynamical polymorphism. + */ + class random_generator { + boost::shared_ptr rng_ptr; + boost::scoped_ptr< boost::generator > gen; + std::string name; + void operator = ( random_generator const & p); //forbid + std::size_t seed; + public: + + /// Takes the boost name of the generator e.g. mt19937,... + random_generator(std::string const & RandomGeneratorName, std::size_t seed_ ); + + /// + random_generator( random_generator const & p); + + /// Return a list of the names of available generators, with separator sep + static std::string random_generator_names(std::string const & sep=" "); + + /// Returns a integer in [0,i-1] with flat distribution +#define INTEGER_OVERLOAD(T) T operator()(T i) { return (i==1 ? 0 : T(floor(i*((*gen)()))));} + INTEGER_OVERLOAD(int) + INTEGER_OVERLOAD(size_t) +#undef INTEGER_OVERLOAD + + /// Returns a double in [0,1[ with flat distribution + double operator()() { return ((*gen)());} + + /// Returns a double in [0,x[ with flat distribution + double operator()(double x) { return x*((*gen)());} + + /// Returns a double in [a,b[ with flat distribution + double operator()(double a, double b) { assert (b>a); return a + (b-a)*((*gen)());} + + }; + +} +} + +#endif diff --git a/triqs/mc_tools/v1/mc_measure_set.hpp b/triqs/mc_tools/v1/mc_measure_set.hpp new file mode 100644 index 00000000..003a666a --- /dev/null +++ b/triqs/mc_tools/v1/mc_measure_set.hpp @@ -0,0 +1,171 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef MC_MEASURE1_H +#define MC_MEASURE1_H + +#include +#include +#include +#include +#include +#include + +namespace triqs { +namespace mc_tools { + namespace mpi=boost::mpi; + using std::size_t; + + //-------------------------------------------------------------------- + + namespace details { + + template + class measure_base { + public: + virtual ~measure_base(){} + virtual void accumulate(MCSignType signe)=0; + virtual void collect_results(mpi::communicator const & c)=0; + virtual uint64_t count() const=0; + }; + + //-------------------------------------------------------------------- + + template struct IsMeasure { + BOOST_CONCEPT_USAGE(IsMeasure) + { + i.accumulate(MCSignType(1.0)); + i.collect_results (*c); + } + private: + X i; boost::mpi::communicator const * c; + }; + + //-------------------------------------------------------------------- + + template + class measure_impl : public measure_base { + BOOST_CONCEPT_ASSERT((IsMeasure)); + void operator=(measure_impl const &); // forbidden + protected: + boost::shared_ptr ptr; + uint64_t count_; + public: + measure_impl(MeasureType * _ptr):measure_base(), ptr(_ptr),count_(0) {} + measure_impl(boost::shared_ptr sptr) : measure_base(), ptr(sptr),count_(0) {} + measure_impl( measure_impl const & X):measure_base(X), ptr( new MeasureType (*X.ptr.get())),count_(X.count_) {} + virtual ~measure_impl(){} + virtual void accumulate(MCSignType signe){ count_++; ptr->accumulate(signe); } + virtual void collect_results(mpi::communicator const & c) { ptr->collect_results (c); } + virtual uint64_t count() const { return count_;} + }; + + }//details namespace + + //-------------------------------------------------------------------- + + template + class mcmeasure { + boost::shared_ptr< details::measure_base > impl_; + public : + + template + mcmeasure ( MeasureType * p) : impl_( new details::measure_impl (p)) {} + + template + mcmeasure ( boost::shared_ptr sptr) : impl_( new details::measure_impl (sptr)) {} + + mcmeasure() {} + void accumulate(MCSignType const & signe) { assert(impl_); impl_->accumulate(signe);} + void collect_results(boost::mpi::communicator const & communicator) { assert(impl_); impl_-> collect_results(communicator);} + uint64_t count() const { assert(impl_); return impl_->count();} + // Recover the measure in its original type + /* template T const & get() const { assert(impl_); + details::measure_impl * res = dynamic_cast< details::measure_impl *> (impl_.get()); + if (!res) TRIQS_RUNTIME_ERROR<<"Internal error in measure_set : Measure is not of the required type"; + return res.get(); + } */ + }; + + //-------------------------------------------------------------------- + + template + class measure_set : public std::map > { + typedef std::map > BaseType; + typedef mcmeasure measure_type; + public : + typedef typename BaseType::iterator iterator; + typedef typename BaseType::const_iterator const_iterator; + + /** + * Register the Measure M with a name + * WARNING : the pointer is deleted automatically by the class at destruction. + */ + template + void insert (T * && M, std::string const & name) { + if (has(name)) TRIQS_RUNTIME_ERROR <<"measure_set : insert : measure '"< + void insert(boost::shared_ptr ptr, std::string const & name) { + if (has(name)) TRIQS_RUNTIME_ERROR <<"measure_set : insert : measure '"<second; + } + + measure_type const & operator[](std::string const & name) const { + if (!has(name)) + throw std::out_of_range("No result found with the name: " + name); + return BaseType::find(name)->second; + } + + /// + void accumulate( MCSignType & signe) { for (iterator it= this->begin(); it != this->end(); ++it) it->second.accumulate(signe); } + + /// + //size_t size() const {return name_to_mes.size(); } + + /// + std::vector names() const { + std::vector res; + for (const_iterator it= this->begin(); it !=this->end(); ++it) res.push_back(it->first); + return res; + } + + // gather result for all measure, on communicator c + void collect_results (boost::mpi::communicator const & c ) { + for (typename BaseType::iterator it = this->begin(); it != this->end(); ++it) it->second.collect_results(c); + } + + }; + +}}// end namespace +#endif + diff --git a/triqs/mc_tools/v1/mc_move_set.hpp b/triqs/mc_tools/v1/mc_move_set.hpp new file mode 100644 index 00000000..4b6ee90d --- /dev/null +++ b/triqs/mc_tools/v1/mc_move_set.hpp @@ -0,0 +1,263 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef TRIQS_TOOLS_MC_MOVE_SET1_H +#define TRIQS_TOOLS_MC_MOVE_SET1_H + +#include +#include +#include "random_generator.hpp" +#include +#include + +namespace triqs { namespace mc_tools { + namespace mpi=boost::mpi; + template class move_set; + namespace details { + + template + struct move_base { + virtual ~move_base(){} + virtual MCSignType Try()=0; + virtual MCSignType Accept()=0; + virtual void Reject()=0; + virtual double acceptance_probability(mpi::communicator const & c) const=0;// on master,0 on nodes + virtual void print (triqs::utility::report_stream &, mpi::communicator const &, std::string name, std::string decal) const =0; + }; + + //-------------------------------------------------------------------- + + template struct IsMove { + BOOST_CONCEPT_USAGE(IsMove) + { + Y r = i.Try(); + r = i.Accept(); + i.Reject(); + } + private: + X i; + }; + + //-------------------------------------------------------------------- + + template + void print_move (MoveType const &,triqs::utility::report_stream &,mpi::communicator const &,std::string name,std::string decal){} + + template + void print_move (move_set const & M, triqs::utility::report_stream & report, mpi::communicator const & c, std::string name, std::string decal); + + //-------------------------------------------------------------------- + + template + class move_impl : boost::noncopyable, public move_base { + BOOST_CONCEPT_ASSERT((IsMove)); + private: + boost::shared_ptr ptr; // ptr to the move + uint64_t NProposed,NAccepted; // Statistics + void operator=(move_impl const &); // forbidden + public: + move_impl(MoveType * move_ptr):move_base(),ptr(move_ptr),NProposed(0),NAccepted(0) {} + move_impl(boost::shared_ptr sptr):move_base(),ptr(sptr),NProposed(0),NAccepted(0) {} + move_impl(move_impl const & M): + move_base(),ptr(new MoveType (*M.ptr.get())), + NProposed(M.NProposed),NAccepted(M.NAccepted){} + virtual ~move_impl(){} + virtual MCSignType Try(){ NProposed++; return ptr->Try();} + virtual MCSignType Accept() { NAccepted++; return ptr->Accept(); } + virtual void Reject() { ptr->Reject();} + const MoveType * get() const { return ptr.get();} + /// Acceptance Probability on the master and 0 on the nodes + virtual double acceptance_probability(mpi::communicator const & c) const { + uint64_t nacc_tot=0, nprop_tot=1; + mpi::reduce(c, NAccepted, nacc_tot, std::plus(), 0); + mpi::reduce(c, NProposed, nprop_tot, std::plus(), 0); + return nacc_tot/static_cast(nprop_tot); + } + virtual void print (triqs::utility::report_stream & report, mpi::communicator const & c, std::string name, std::string decal) const { + report<< decal <<"Acceptance probability of move : "< + class move_set { + boost::ptr_vector > moves_; + std::vector names_; + details::move_base * current; + size_t current_move_number; + random_generator & RNG; + std::vector Proba_Moves, Proba_Moves_Acc_Sum; + public: + + /// + move_set(random_generator & R): RNG(R) { Proba_Moves.push_back(0); } + + /** + * Add move M with its probability of being proposed. + * NB : the PropositionProbability needs to be >0 but does not need to be + * normalized. Normalization is automatically done with all the added moves + * before starting the run + * + * WARNING : the pointer is deleted automatically by the MC class at destruction. + */ + template + void add (MoveType * && M, std::string name, double PropositionProbability) { + moves_.push_back(new details::move_impl(M)); + assert(PropositionProbability >=0); + Proba_Moves.push_back(PropositionProbability); + names_.push_back(name); + normaliseProba();// ready to run after each add ! + } + + template + void add (boost::shared_ptr sptr, std::string name, double PropositionProbability) { + moves_.push_back(new details::move_impl(sptr)); + assert(PropositionProbability >=0); + Proba_Moves.push_back(PropositionProbability); + names_.push_back(name); + normaliseProba();// ready to run after each add ! + } + + //----------------- + /** + * - Picks up one of the move at random (weighted by their proposition probability), + * - Call Try method of that move + * - Returns the metropolis ratio R (see move concept). + * The sign ratio returned by the try method of the move is kept. + */ + double Try() { + assert( Proba_Moves_Acc_Sum.size()>0); + // Choice of move with its probability + double proba = RNG();assert(proba>=0); + //std::cerr<<" Size of proba_moves_acc"<< Proba_Moves_Acc_Sum.size()<= Proba_Moves_Acc_Sum[current_move_number] ) { current_move_number++;} + //std::cerr << "curren move #"<0); assert(current_move_number<=this->size()); + current_move_number--; + current = &moves_[current_move_number]; +#ifdef DEBUG + std::cerr << "*******************************************************"<< std::endl; + std::cerr << "Name of the proposed move: " << name_of_currently_selected() << std::endl; + std::cerr <<" Proposition probability = "<Try(); + if (!std::isfinite(std::abs(rate_ratio))) + TRIQS_RUNTIME_ERROR<<"Monte Carlo Error : the rate is not finite in move "<=0)); + try_sign_ratio = ( abs_rate_ratio> 1.e-14 ? rate_ratio/abs_rate_ratio : 1); // keep the sign + return abs_rate_ratio; + } + + //----------------- + /** + * Accept the move previously selected and tried. + * Returns the Sign computed as, if M is the move : + * Sign = sign (M.Try()) * M.Accept() + */ + MCSignType Accept() { + MCSignType accept_sign_ratio = current->Accept(); + // just make sure that accept_sign_ratio is a sign! + assert(std::abs(std::abs(accept_sign_ratio)-1.0) < 1.e-10); +#ifdef DEBUG + std::cerr.setf(std::ios::scientific, std::ios::floatfield); + std::cerr<<" ... Move accepted"<Reject(); + } + + //----------------- + /// Number of moves registered in the move_set + size_t size() const { return moves_.size();} + + //----------------- + /// Pretty printing of the acceptance probability of the moves. + void print (triqs::utility::report_stream & report, mpi::communicator const & c, std::string name="", std::string decal="") const { + report <0); + for (unsigned int u = 0; usize()+1); + } + + /// for debug only + std::string name_of_currently_selected() const { return names_[current_move_number];} + + };// class move_set + + namespace details { // specialization for pretty print of move_set. + template + inline void print_move (move_set const & M, triqs::utility::report_stream & report, mpi::communicator const & c, std::string name, std::string decal) { + M.print(report,c,name,decal); + } + } + + + +} +}// end namespace +#endif + diff --git a/triqs/parameters.hpp b/triqs/parameters.hpp new file mode 100644 index 00000000..82d42287 --- /dev/null +++ b/triqs/parameters.hpp @@ -0,0 +1,25 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ALL_PARAMETERS_H +#define TRIQS_ALL_PARAMETERS_H +#include "./parameters/parameters.hpp" +#endif + diff --git a/triqs/parameters/CMakeLists.txt b/triqs/parameters/CMakeLists.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/triqs/parameters/CMakeLists.txt @@ -0,0 +1 @@ + diff --git a/triqs/parameters/defaults.cpp b/triqs/parameters/defaults.cpp new file mode 100644 index 00000000..184a03e8 --- /dev/null +++ b/triqs/parameters/defaults.cpp @@ -0,0 +1,58 @@ +/******************************************************************************* + * + * 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 . + * + ******************************************************************************/ +#include "./defaults.hpp" +#include +namespace triqs { namespace utility { + + std::vector> parameter_defaults:: generate_help() const{ + std::vector> str; +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + 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)}); + } +#else + std::vector v; + v.push_back("parameter:"); v.push_back("status:"); v.push_back("default value:"); v.push_back("description:"); + str.push_back(v); + for (auto const &s : object_map){ + std::string key=s.first; std::ostringstream val; val << s.second; + v.clear(); + if(is_required(key)) { + v.push_back(key); v.push_back("required"); v.push_back("-"); v.push_back(doc(key)); + } + else { + v.push_back(key); v.push_back("optional"); v.push_back(val.str()); v.push_back(doc(key)); + } + str.push_back(v); + } +#endif + return str; + } + + std::ostream & operator << (std::ostream & out, parameter_defaults const & p) { + out<< print_formatted(p.generate_help()); + return out; + } + +}} diff --git a/triqs/parameters/defaults.hpp b/triqs/parameters/defaults.hpp new file mode 100644 index 00000000..c14e0749 --- /dev/null +++ b/triqs/parameters/defaults.hpp @@ -0,0 +1,112 @@ +/******************************************************************************* + * + * 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 . + * + ******************************************************************************/ +#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 map_t; + map_t object_map; + std::map documentation; + std::map is_optional; + + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::make_nvp("object_map",object_map); } + + struct _inserter { + parameter_defaults * p; bool opt; + _inserter(parameter_defaults *p_, bool opt_) : p(p_), opt(opt_) {} + template _inserter operator()(std::string const & key, T && def_val, std::string const & doc) { + p->object_map[key] = std::forward(def_val); + p->documentation[key] = doc; + p->is_optional[key] = opt; + return *this; + } + + }; + friend struct _inserter; + + template const T getter(std::map 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 + _inserter optional (std::string const & key, T && def_val, std::string const & doc) { + return _inserter(this, true)(key,std::forward(def_val), doc); + } + + ///inserter for required parameters; + ///calls can be chained for multiple parameters + template + _inserter required (std::string const & key, T && def_val, std::string const & doc) { + return _inserter(this, false)(key,std::forward(def_val), doc); + } + + ///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> generate_help() const; + + ///print a formatted table of required and optional parameters + friend std::ostream & operator << (std::ostream & out, parameter_defaults const & p); + + }; + +}} +#endif diff --git a/triqs/parameters/opaque_object_h5.cpp b/triqs/parameters/opaque_object_h5.cpp new file mode 100644 index 00000000..4f7dd339 --- /dev/null +++ b/triqs/parameters/opaque_object_h5.cpp @@ -0,0 +1,64 @@ +#include "./opaque_object_h5.hpp" + +namespace triqs { namespace utility { + + std::map> _object::code_to_deserialization_fnts; + std::map> _object::code_to_h5_read_fnts; + std::map _object::h5_type_to_c_equivalence; + std::map, size_t > _object::code_element_rank_to_code_array; + std::map _object::h5_scheme_to_code; + std::map _object::type_code_to_type_name; + std::map _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(); + 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 "<() : _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" << 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); + } +}} + diff --git a/triqs/parameters/opaque_object_h5.hpp b/triqs/parameters/opaque_object_h5.hpp new file mode 100644 index 00000000..6938a530 --- /dev/null +++ b/triqs/parameters/opaque_object_h5.hpp @@ -0,0 +1,331 @@ +/******************************************************************************* + * + * 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_OPAQUE_OBJECT_H5_H +#define TRIQS_UTILITY_OPAQUE_OBJECT_H5_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace triqs { namespace utility { + + template + std::ostream & operator<<(std::ostream & out, std::vector 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 struct _object_collapse_type_impl : std::conditional::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 struct _object_collapse_type_impl< arrays::array> { typedef arrays::array_c type;}; + template struct _object_collapse_type_impl< arrays::matrix> { typedef arrays::array_c type;}; + template struct _object_collapse_type_impl< arrays::vector> { typedef arrays::array_c type;}; + + //same thing for the view + template struct _object_collapse_type_impl< arrays::array_view> { typedef arrays::array_c type;}; + template struct _object_collapse_type_impl< arrays::matrix_view> { typedef arrays::array_c type;}; + template struct _object_collapse_type_impl< arrays::vector_view> { typedef arrays::array_c type;}; + + // uncomment after merge qview branch + //template struct _object_collapse_type_impl< arrays::array_qview> { typedef arrays::array_c type;}; + //template struct _object_collapse_type_impl< arrays::matrix_qview> { typedef arrays::array_c type;}; + //template struct _object_collapse_type_impl< arrays::vector_qview> { typedef arrays::array_c type;}; + + template struct _object_collapse_type: _object_collapse_type_impl ::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 + void h5_read(h5::group const &gr, std::string const &Name, arrays::array_c & a) { + arrays::array 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 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 h5_w; // the function to write in h5 + std::function serialize_; // for boost serialization ... + std::function print_; + std::string name_; + + public : + + template static constexpr size_t type_code () { return typeid(T).hash_code();} + template static std::string make_type_name () { return get_triqs_hdf5_data_scheme(typename _object_collapse_type::type());} + //template 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 + _object ( T && obj, std::string const & name){ delegate_constructor( new typename std::remove_cv::type>::type(std::forward(obj)), name); } + + private: + template void delegate_constructor( T * obj, std::string const & name) { + p = std::shared_ptr (obj); + type_code_ = type_code(); + 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::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 _object & operator=(RHS && rhs) { + typedef typename _object_collapse_type::type storage_t; + *this = _object (storage_t(std::forward(rhs)),this->name()); + register_type::invoke(); + //register_type::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 bool has_type() const { return type_code_ == type_code();} + + 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 + void save(Archive & ar, const unsigned int version) const { + std::string s = serialize_(); + ar << boost::serialization::make_nvp("type_name", type_code_to_type_name[type_code_]); + ar << boost::serialization::make_nvp("seria_str", s); + } + template + void load(Archive & ar, const unsigned int version) { + std::string s, tnn; + ar >> boost::serialization::make_nvp("type_name", tnn); + ar >> boost::serialization::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> code_to_deserialization_fnts; + static std::map> code_to_h5_read_fnts; + static std::map h5_type_to_c_equivalence; + static std::map, size_t > code_element_rank_to_code_array; + static std::map h5_scheme_to_code; + static std::map type_code_to_type_name; + static std::map 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 struct register_type; + + private: // native type + template + static void register_native_type() { + if (register_type::invoke()) return; + h5_type_to_c_equivalence[h5::h5_type_from_C(T()).getId()] = type_code(); + } + + };// object class + + // --------------------- type registering --------------------------------- + + template struct _object::register_type : _object::register_type{}; + + template struct _object::register_type { + static bool invoke() { // returns true if already registered + size_t code = type_code(); + if (is_initialised(code)) return true; + type_code_to_type_name[code] = make_type_name(); + type_name_to_type_code[make_type_name()]= code; + code_to_deserialization_fnts[code] = [](std::string const &s) { return _object( triqs::deserialize(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 struct _object::register_type>{ + static bool invoke() { + typedef arrays::array_c A; + typedef arrays::array Aa; + if (is_initialised(type_code())) return true; + type_code_to_type_name[type_code()] = make_type_name(); + type_name_to_type_code[make_type_name()]= type_code(); + code_to_deserialization_fnts[type_code()] = [](std::string const &s) { return _object( triqs::deserialize(s),"");}; + //code_to_h5_read_fnts[type_code()] = [](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()] = [](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(), R)] = type_code(); + auto h5_scheme = get_triqs_hdf5_data_scheme(Aa()); + if (h5_scheme != "") h5_scheme_to_code[h5_scheme] = type_code(); + return false; + } + }; + + // --------------------- arithmetic operations are deleted for _object --------------------------------- + +#define DELETE_OP(op)\ + template \ + typename std::enable_if< std::is_same::value || std::is_same::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 struct extract_strict { + typedef typename _object_collapse_type::type T_stored; + static bool is_possible (_object const &obj) { return obj.has_type(); } + static T invoke(_object const &obj) { + if (! is_possible(obj)) + TRIQS_RUNTIME_ERROR<<"extraction of "<< obj.name() << "impossible : type mismatch. Got a "<(); + return T(* static_cast(obj.get_void_ptr())); + } + }; + + // --------------------- extraction with more relaxed type checking for C++ --------------------------------- + + template T extract(_object const &obj); + + template T lex_cast_from_string(_object const &obj) { + std::string s = extract(obj); + try { return boost::lexical_cast(s); } + catch(boost::bad_lexical_cast &) { TRIQS_RUNTIME_ERROR << " extraction : can not read the string "<(); } + } + + template struct lexical_cast_make_sense : std::is_arithmetic{}; + //template constexpr bool lexical_cast_make_sense() { return std::is_arithmetic::value; } + + template T extract1(_object const &obj, std::false_type) { + typedef typename _object_collapse_type::type coll_t; + if (! obj.has_type()) + TRIQS_RUNTIME_ERROR<<"extraction of "<< obj.name() << " impossible : type mismatch. Got "<(); + return * static_cast(obj.get_void_ptr()); + } + + template 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::value) && (obj.has_type())) { return lex_cast_from_string(obj); } + return extract1(obj, std::false_type()); + } + + template T extract(_object const &obj) { + return extract1(obj, std::integral_constant::value>()); + } + + template<> // specialize for double since we can make int -> double conversion + inline double extract(_object const & obj) { + if (obj.has_type()) return * static_cast(obj.get_void_ptr()); + if (obj.has_type()) {return lex_cast_from_string(obj); } +#define TRANSFORM_TYPE(T) if (obj.has_type()) return extract(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 "< // special case to size_t +// inline size_t extract(_object const & obj) { return extract(obj);} + + // --------------- _object cast op implementation --------------------------------------- + +#define CAST_OPERATOR(r, data, T) inline _object::operator T () const{ return extract(*this);} + BOOST_PP_SEQ_FOR_EACH(CAST_OPERATOR, nil , TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST); +#undef CAST_OPERATOR + +}} +#endif diff --git a/triqs/parameters/parameters.cpp b/triqs/parameters/parameters.cpp new file mode 100644 index 00000000..91fd0d13 --- /dev/null +++ b/triqs/parameters/parameters.cpp @@ -0,0 +1,106 @@ +#include "./parameters.hpp" +#include + +namespace triqs { namespace utility { + + void h5_read ( h5::group F, std::string const & subgroup_name, parameters & p){ + auto gr = F.open_group(subgroup_name); + std::vector 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 <second(gr,x); + } + else { + parameters p2; + h5_read (gr,x,p2); + p[x] = p2; + } + } + for (auto & x : ds_name) { + //std::cerr << " loading : "<< x <> missing; + std::vector> wrong_t; + std::vector> no_deft; + +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + std::vector desc{"key:", "description:"}; + std::vector tdesc{"key:", "expected type:", "actual type:"}; +#else + std::vector desc; desc.push_back("key:"); desc.push_back("description:"); + std::vector tdesc; tdesc.push_back("key:"); tdesc.push_back("expected type:"); tdesc.push_back("actual type:"); +#endif + + 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)){ +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + no_deft.push_back({key}); +#else + { std::vector v; v.push_back(key); no_deft.push_back(v);} +#endif + } + } + } + + 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); +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + missing.push_back({key, pdef.doc(key)}); +#else + { std::vector v; v.push_back(key); v.push_back(pdef.doc(key)); missing.push_back(v);} +#endif + } + 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); +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + wrong_t.push_back({key, pvp.second.type_name(), (*this)[key].type_name()}); +#else + { std::vector v; v.push_back(key); v.push_back(pvp.second.type_name()); v.push_back((*this)[key].type_name()); + wrong_t.push_back(v);} +#endif + + } + } + 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); + + } + +}} + diff --git a/triqs/parameters/parameters.hpp b/triqs/parameters/parameters.hpp new file mode 100644 index 00000000..663ab990 --- /dev/null +++ b/triqs/parameters/parameters.hpp @@ -0,0 +1,127 @@ +/******************************************************************************* + * + * 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_PARAMS_H +#define TRIQS_UTILITY_PARAMS_H +#include "./opaque_object_h5.hpp" +#include "./defaults.hpp" +namespace triqs { namespace utility { + /** + * 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 + * 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 + * arithmetic type, a boost::lexical_cast is attempted. + * 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);} + + private: + typedef std::map map_t; + map_t object_map; + std::map documentation; + + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::make_nvp("object_map",object_map); } + + 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 & k) const { return object_map.find(k) != object_map.end();} + + /// + _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; + } + + /// + _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; + } + + 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); + } + + ///read from an hdf5 archive + friend void h5_read ( h5::group F, std::string const & subgroup_name, parameters & p); + + friend std::ostream & operator << (std::ostream & out, parameters const & p) { + out<< "{"; + for (auto & pvp : p.object_map) out<< pvp.first << " : " << pvp.second<< ", "; + return out<<"}"; + } + + /** + * 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 static void register_type() { _object::register_type::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); + + }; + +}} +#endif diff --git a/triqs/python_tools/CMakeLists.txt b/triqs/python_tools/CMakeLists.txt new file mode 100644 index 00000000..e69de29b diff --git a/triqs/python_tools/array_interface.hpp b/triqs/python_tools/array_interface.hpp new file mode 100644 index 00000000..554268e6 --- /dev/null +++ b/triqs/python_tools/array_interface.hpp @@ -0,0 +1,65 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAY_INTERFACE_H +#define TRIQS_ARRAY_INTERFACE_H + +#include +#include + +namespace triqs { namespace arrays { + + template + struct array_c: public triqs::python_tools::cython_proxy > { + + typedef triqs::python_tools::cython_proxy> B; + array_c(): B() {} + array_c(array_c const &a): B(a) {}; + array_c(array_view const &a): B(a) {}; + template explicit array_c(Args && ... args): B(std::forward(args)...) {} + + }; + + template + struct matrix_c: public triqs::python_tools::cython_proxy> { + + typedef triqs::python_tools::cython_proxy> B; + matrix_c(): B() {} + matrix_c(matrix_c const &a): B(a) {}; + matrix_c(matrix_view const &a): B(a) {}; + template explicit matrix_c(Args && ... args): B(std::forward(args)...) {} + + }; + + template + struct vector_c: public triqs::python_tools::cython_proxy> { + + typedef triqs::python_tools::cython_proxy> B; + vector_c(): B() {} + vector_c(vector_c const &a): B(a) {}; + vector_c(vector_view const &a): B(a) {}; + template explicit vector_c(Args && ... args): B(std::forward(args)...) {} + + }; + + +}}//namespace triqs +#endif + diff --git a/triqs/python_tools/boost_object.hpp b/triqs/python_tools/boost_object.hpp new file mode 100644 index 00000000..3f431dcb --- /dev/null +++ b/triqs/python_tools/boost_object.hpp @@ -0,0 +1,21 @@ +#include +#include + +namespace triqs { namespace python_tools { + +// A simple wrapper +class boost_object { + + boost::python::handle<> hdl; + + public: + + boost_object(PyObject * py_ob) : hdl(boost::python::borrowed(py_ob)) {} + + operator boost::python::object () { return boost::python::object(hdl); } + operator boost::python::list () { return boost::python::list(hdl); } + operator boost::python::dict () { return boost::python::dict(hdl); } + +}; + +}} diff --git a/triqs/python_tools/cython_proxy.hpp b/triqs/python_tools/cython_proxy.hpp new file mode 100644 index 00000000..c50ccb4b --- /dev/null +++ b/triqs/python_tools/cython_proxy.hpp @@ -0,0 +1,44 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_PYTHON_CYTHON_PROXY_H +#define TRIQS_PYTHON_CYTHON_PROXY_H +#include + +namespace triqs { namespace python_tools { + + // Wrap a C++ view into an object which has *value* semantics + // operator = remapped to <<= + // This class must be friend of V, to use the private default constructor. + template class cython_proxy : public V { + public: + cython_proxy() : V(typename V::non_view_type()) {} + cython_proxy(V const &v) : V(v){}; + cython_proxy(cython_proxy const & cp) : V(cp) {}; + template explicit cython_proxy(Args && ... args) : V (std::forward(args)...){} + cython_proxy & operator = ( cython_proxy const & cp ) { this->rebind(cp); return *this;} + cython_proxy & operator = ( V const & v ) { this->rebind(v); return *this;} + template void operator << ( V2 && v) { V::operator=( std::forward(v) );} + }; + + +}}//namespace triqs +#endif + diff --git a/triqs/python_tools/inserter_in_map.hpp b/triqs/python_tools/inserter_in_map.hpp new file mode 100644 index 00000000..b6d0b1b7 --- /dev/null +++ b/triqs/python_tools/inserter_in_map.hpp @@ -0,0 +1,45 @@ +/******************************************************************************* + * + * 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 . + * + ******************************************************************************/ +#ifndef TRIQS_PYTHON_TOOLS_INSERTER_MAP_H +#define TRIQS_PYTHON_TOOLS_INSERTER_MAP_H +#include +#include + +namespace triqs { namespace python_tools { + + template struct inserter_in_map { + T * p; + inserter_in_map(T & x) : p(&x) {} + void operator()(std::string const & key, U const & x) { (*p)[key] = x; } + }; + + template struct inserter_in_map2 { + T * p; + inserter_in_map2(T & x) : p(&x) {} + void operator()(std::string const & key, PyObject * ob) { (*p)[key] = U(ob); } + }; + + template struct printer { + std::string operator()(T const & x) { std::stringstream fs; fs<. + * + ******************************************************************************/ + +#include "callbacks.hpp" +#include "signal_handler.hpp" +#include +#include + +namespace triqs { + namespace utility { + + bool clock_callback_impl(boost::posix_time::ptime const & end_time) { + return (!triqs::signal_handler().empty()) || boost::posix_time::second_clock::local_time() > end_time; + } + + bool false_callback_impl() { return (!triqs::signal_handler().empty());} + + boost::function clock_callback(int time_in_seconds) { + return (time_in_seconds>0 ? + boost::bind(&clock_callback_impl, boost::posix_time::second_clock::local_time() + boost::posix_time::seconds(time_in_seconds)) : + boost::function (&false_callback_impl)); + } + + } +}; + diff --git a/triqs/utility/callbacks.hpp b/triqs/utility/callbacks.hpp new file mode 100644 index 00000000..92655e5f --- /dev/null +++ b/triqs/utility/callbacks.hpp @@ -0,0 +1,34 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef TRIQS_TOOLS_MC_CALLBACKS_H +#define TRIQS_TOOLS_MC_CALLBACKS_H +#include +#include + +namespace triqs { namespace utility { + + boost::function clock_callback(int time_in_seconds); + +}} +#endif + diff --git a/triqs/utility/compiler_details.hpp b/triqs/utility/compiler_details.hpp new file mode 100644 index 00000000..bbf139b3 --- /dev/null +++ b/triqs/utility/compiler_details.hpp @@ -0,0 +1,39 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_COMPILER_DETAILS_H +#define TRIQS_COMPILER_DETAILS_H + +#ifdef __GNUC__ +#define restrict __restrict__ +#endif + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#define TRIQS_USE_STATIC_ASSERT +//#define USE_VARIADIC_TEMPLATES +#endif + +#ifndef TRIQS_USE_STATIC_ASSERT +#include "boost/static_assert.hpp" +#define static_assert(X,MESS) BOOST_STATIC_ASSERT((X)) +#endif + +#endif + diff --git a/triqs/utility/complex_ops.hpp b/triqs/utility/complex_ops.hpp new file mode 100644 index 00000000..b88220d4 --- /dev/null +++ b/triqs/utility/complex_ops.hpp @@ -0,0 +1,20 @@ +#ifndef TRIQS_UTILITY_COMPLEX_OPS_H +#define TRIQS_UTILITY_COMPLEX_OPS_H +#include + +namespace std { // has to be in the right namespace for ADL ! + +template std::complex operator+(std::complex const & a, long b) { return a+T(b);} +template std::complex operator+(long a, std::complex const & b) { return T(a)+b;} +template std::complex operator-(std::complex const & a, long b) { return a-T(b);} +template std::complex operator-(long a, std::complex const & b) { return T(a)-b;} +template std::complex operator*(std::complex const & a, long b) { return a*T(b);} +template std::complex operator*(long a, std::complex const & b) { return T(a)*b;} +template std::complex operator/(std::complex const & a, long b) { return a/T(b);} +template std::complex operator/(long a, std::complex const & b) { return T(a)/b;} +} + +#endif + + + diff --git a/triqs/utility/concept_tools.hpp b/triqs/utility/concept_tools.hpp new file mode 100644 index 00000000..73cf7a84 --- /dev/null +++ b/triqs/utility/concept_tools.hpp @@ -0,0 +1,51 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_CONCEPT_TOOLS_H +#define TRIQS_UTILITY_CONCEPT_TOOLS_H +#include +#include +#include +#include + +#define TRIQS_CONCEPT_TAGNAME(MyBeautifulConcept) MyBeautifulConcept##__concept_tag + +#define TRIQS_MODEL_CONCEPT(MyBeautifulConcept) TRIQS_CONCEPT_TAGNAME(MyBeautifulConcept) + +#define TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(MyBeautifulConcept) \ + struct TRIQS_CONCEPT_TAGNAME(MyBeautifulConcept) {};\ + template struct MyBeautifulConcept : boost::is_base_of {}; + +#define TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R_AUX(r, data, i, elem) BOOST_PP_COMMA_IF(i) TRIQS_CONCEPT_TAGNAME(elem) + +#define TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R(MyBeautifulConcept,Rs) \ + struct TRIQS_CONCEPT_TAGNAME(MyBeautifulConcept) : BOOST_PP_SEQ_FOR_EACH_I (TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R_AUX,nil,Rs) {};\ + template struct MyBeautifulConcept : boost::is_base_of {}; + +#ifdef TRIQS_COMPILE_TIME_DEBUG +#define TRIQS_ASSERT_MODEL_CONCEPT(MyBeautifulConcept,T) BOOST_CONCEPT_ASSERT((BCC_##MyBeautifulConcept)); +#else +#define TRIQS_ASSERT_MODEL_CONCEPT(MyBeautifulConcept,T) +#endif + +namespace triqs { namespace utility { +}} +#endif + diff --git a/triqs/utility/count_type_occurrence.hpp b/triqs/utility/count_type_occurrence.hpp new file mode 100644 index 00000000..fbb97cd1 --- /dev/null +++ b/triqs/utility/count_type_occurrence.hpp @@ -0,0 +1,42 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_COUNT_OCCUR_H +#define TRIQS_UTILITY_COUNT_OCCUR_H +namespace triqs { + + /// count_type_occurrence::value is the number of Args deriving or equal to T + + template struct count_type_occurrence; + + template struct count_type_occurrence : + std::integral_constant < int, std::is_base_of::value + count_type_occurrence::value>{}; + + template struct count_type_occurrence : std::integral_constant{}; + + template struct count_type_occurrence_not; + + template struct count_type_occurrence_not : + std::integral_constant < int, !(std::is_base_of::value) + count_type_occurrence_not::value>{}; + + template struct count_type_occurrence_not : std::integral_constant{}; + +} +#endif diff --git a/triqs/utility/crash_logger.hpp b/triqs/utility/crash_logger.hpp new file mode 100644 index 00000000..7d96f6ed --- /dev/null +++ b/triqs/utility/crash_logger.hpp @@ -0,0 +1,95 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_CRASH_LOGGER_H +#define TRIQS_UTILITY_CRASH_LOGGER_H +#include "./first_include.hpp" +#include +#include +#include +#include +#include +#include +#include "./typeid_name.hpp" +#include "./scope_guard.hpp" +#include "../h5.hpp" + +namespace triqs { namespace utility { + + /** + * Usage : + * + * Suppose we have objects a,b,c ... which are all H5_Serializable + * Then : + * { // a scope, whatever + * auto log = crash_logger("dump.h5"); + * log(a,"a")(b,"b")(c,"c"); // <---- pls make a macro here ! + * // ... do some work + * log.dismiss(); + * } + * + * Now : if the calculation proceeds correctly, nothing happens. log is destroyed. + * if however the calculation does not reach the dismiss, e.g. an exception occurs + * then log is destroyed without a dismiss and it will dump all objects in the hdf5 file. + * + * "some work" can be as complex as needed... + * + */ +class crash_logger { + std::string filename_; + std::vector>> guards; + std::vector names; + public : + /// + crash_logger(std::string filename) : filename_(filename){} + crash_logger(const crash_logger&) = delete; + crash_logger(crash_logger&&) = default; + crash_logger& operator=(const crash_logger&) = delete; + crash_logger& operator=(crash_logger && x) { using std::swap; swap(guards, x.guards); swap(names,x.names); return *this;} + /// + template crash_logger & operator()(Obj const & obj, std::string name) { + names.push_back(name); + guards.emplace_back([&obj,this, name](){ + using triqs::h5::h5_write; // to have the proper overload for scalar type !! + try { h5_write( h5::group(H5::H5File(this->filename_.c_str(),H5F_ACC_RDWR)), name, obj); } + catch(H5::Exception const & e) { std::cerr << "An hdf5 exception has occurred in crash_logger : I can not recover : error is " <0) && (guards.front().active())) { + std::cerr << "crash_logger : I am destroyed without being dismissed. Dumping the objects : "; + for (auto & x : names) std::cerr<< "\""<< x <<"\" "; + std::cerr<< std::endl; + H5::H5File(this->filename_.c_str(),H5F_ACC_TRUNC); // create the file + } + } + catch(...) {} // just in case ... destructor can not throw + } + /// + void dismiss() {for (auto & g : guards) g.dismiss();} +}; + + +}} +#endif diff --git a/triqs/utility/draft/value_view.hpp b/triqs/utility/draft/value_view.hpp new file mode 100644 index 00000000..d57eac5b --- /dev/null +++ b/triqs/utility/draft/value_view.hpp @@ -0,0 +1,98 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_VALUE_VIEW_H +#define TRIQS_UTILITY_VALUE_VIEW_H +#include +#include +#include + +namespace triqs { + + /// a class to keep a value and the view on it in a manner similar to arrays, gf, etc... + template class value_view; + + template class value_view { + + std::shared_ptr p; + friend class value_view; + + public: + typedef void has_view_type_tag; // Idiom : ValueView + typedef value_view view_type; + typedef value_view non_view_type; + typedef typename std::remove_cv::type >::type value_type; + value_view( non_view_type const & a) { p = a.p;} + value_view( view_type const & a) { p = a.p;} + void rebind( view_type const &X) { p = X.p; } + + T & operator()() { return *p;} + T const & operator()() const { return *p;} + operator T() { return *p;} + operator T const() const { return *p;} + value_view & operator=(view_type const & x) { if (!p) rebind(x); else { *p = *x.p;} return *this;} + value_view & operator=(non_view_type const & x) { if (!p) rebind(x); else { *p = *x.p;} return *this;} + value_view & operator=(T const & x) { *p = x; return *this;} + + friend void h5_write (arrays::h5::group_or_file fg, std::string p, value_view const & v) { h5_write(fg,p,v()); } + friend void h5_read (arrays::h5::group_or_file fg, std::string p, value_view & v) { h5_read (fg,p,v()); } + // Boost serialization. Can I use std::shared_ptr directly ? Or use boost::shared_ptr + friend class boost::serialization::access; + template + void save(Archive & ar, const unsigned int version) const { ar << boost::serialization::make_nvp("data",*p); } + template + void load(Archive & ar, const unsigned int version) { T x; ar >> x; p = std::make_shared(x); } + BOOST_SERIALIZATION_SPLIT_MEMBER(); + }; + + template class value_view { + std::shared_ptr p; + friend class value_view; + public: + typedef void has_view_type_tag; // Idiom : ValueView + typedef value_view view_type; + typedef value_view non_view_type; + typedef typename std::remove_cv::type >::type value_type; + value_view( non_view_type const & a) { p = std::make_shared(*a.p);} + value_view( view_type const & a) { p = std::make_shared(*a.p);} + template explicit value_view(Args&&... args) {p = std::make_shared(std::forward(args)...);} + T & operator()() { return *p;} + T const & operator()() const { return *p;} + operator T() { return *p;} + operator T const() const { return *p;} + value_view& operator=(view_type const & x) { *p = *x.p;return *this;} + value_view& operator=(non_view_type const & x) { *p = *x.p;return *this;} + value_view& operator=(T const & x) { *p = x; return *this;} + + friend void h5_write (arrays::h5::group_or_file fg, std::string p, value_view const & v) { h5_write(fg,p,v()); } + friend void h5_read (arrays::h5::group_or_file fg, std::string p, value_view & v) { h5_read(fg,p,v()); } + + // Boost serialization. Can I use std::shared_ptr directly ? Or use boost::shared_ptr + friend class boost::serialization::access; + template + void save(Archive & ar, const unsigned int version) const { ar << boost::serialization::make_nvp("data",*p); } + template + void load(Archive & ar, const unsigned int version) { T x; ar >> x; p = std::make_shared(x); } + BOOST_SERIALIZATION_SPLIT_MEMBER(); + }; + +}//namespace triqs +#endif + diff --git a/triqs/utility/dressed_iterator.hpp b/triqs/utility/dressed_iterator.hpp new file mode 100644 index 00000000..7c6da422 --- /dev/null +++ b/triqs/utility/dressed_iterator.hpp @@ -0,0 +1,113 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_ITERATOR_DRESSING_H +#define TRIQS_UTILITY_ITERATOR_DRESSING_H +#include "./first_include.hpp" +#include +#include +#include "./macros.hpp" + +namespace triqs { namespace utility { + + /** + * Usage : + * + * Suppose we have : + * - an iterator of type IteratorType + * - a little struct that views the data pointed to by it using a set of references, + * like e.g. : + * + * struct _dress {double const & tau; int & a; _dress ( it_type const & it); }; + * + * then dressed_iterator is : + * + * - a bidirectional or forward iterator (depending whether IteratorType is), STL compliant (generated by boost::iterator_facade). + * - that is dereferenced to a _dress. + * + * Example : See doc or test/utility/iterator_dressing.cpp ... + * + * + * Variant : one can keep in the iterator a pointer to anything (typically the parent container) + * which may be useful in some cases (e.g. writing cyclic iterators) + * See iterator_dressing3 for an example + */ + template< typename IteratorType, typename Dressing, typename DressingAuxiliaryArgumentPtrType = void> struct dressed_iterator; + + namespace details { + template< typename IteratorType> struct is_bidir: std::is_same{}; + } + + // specialization when a aux data is present + template< typename IteratorType, typename Dressing, typename DressingAuxiliaryArgumentPtrType> + struct dressed_iterator : public boost::iterator_facade, Dressing, + typename std::conditional::value, boost::bidirectional_traversal_tag, boost::forward_traversal_tag>::type, Dressing > { + public : + dressed_iterator () {} + template dressed_iterator (T const & it, DressingAuxiliaryArgumentPtrType * aux): _it(it), _aux(aux) {} + dressed_iterator (dressed_iterator const & it) = default; + dressed_iterator (dressed_iterator && it) = default; + dressed_iterator & operator = (dressed_iterator const & it) =default; + dressed_iterator & operator = (dressed_iterator && it) noexcept { using std::swap; swap(it._it, this->_it); swap(this->_aux, it._aux); return *this;} + //dressed_iterator (IteratorType const & it, DressingAuxiliaryArgumentPtrType * aux): _it(it), _aux(aux) {} + IteratorType const & get() const { return _it;} + IteratorType & get() { return _it;} + operator IteratorType() const { return _it;} + DressingAuxiliaryArgumentPtrType * get_aux() { return _aux;} + const DressingAuxiliaryArgumentPtrType * get_aux() const { return _aux;} + private: + friend class boost::iterator_core_access; + void increment(){ ++_it;} + template::value> + ENABLE_IFC(BiDir) decrement(){ --_it;} + bool equal(dressed_iterator const & other) const { return(other._it==_it);} + Dressing dereference() const { return Dressing(_it,_aux); } + IteratorType _it; + DressingAuxiliaryArgumentPtrType * _aux;// keep a pointer to maintain assignment of iterator ! + }; + + + // specialisation when no auxiliary data is present + template< typename IteratorType, typename Dressing> + struct dressed_iterator : public boost::iterator_facade, + Dressing, typename std::conditional::value, boost::bidirectional_traversal_tag, boost::forward_traversal_tag>::type, Dressing > { + public : + dressed_iterator () {} + template dressed_iterator (T const & it): _it(it) {} + dressed_iterator (dressed_iterator const & it) = default; + dressed_iterator (dressed_iterator && it) = default; + dressed_iterator & operator = (dressed_iterator const & it) =default; + dressed_iterator & operator = (dressed_iterator && it) noexcept { using std::swap; swap(it._it, this->_it); return *this;} + //dressed_iterator (IteratorType const & it): _it(it) {} + IteratorType const & get() const { return _it;} + IteratorType & get() { return _it;} + operator IteratorType() const { return _it;} + private: + friend class boost::iterator_core_access; + void increment(){ ++_it;} + template::value> + ENABLE_IFC(BiDir) decrement(){ --_it;} + bool equal(dressed_iterator const & other) const { return(other._it==_it);} + Dressing dereference() const { return Dressing(_it); } + IteratorType _it; + }; + +}} +#endif diff --git a/triqs/utility/exceptions.hpp b/triqs/utility/exceptions.hpp new file mode 100644 index 00000000..2b7145a7 --- /dev/null +++ b/triqs/utility/exceptions.hpp @@ -0,0 +1,49 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef TRIQS_EXCEPTIONS_H +#define TRIQS_EXCEPTIONS_H + +#include "./stack_trace.hpp" +#include +#include +#include + +namespace triqs { + + class runtime_error : public std::exception { + std::string acc; + public: + runtime_error() throw() :std::exception() {} + virtual ~runtime_error() throw() {} + template runtime_error & operator <<( T const & x) { std::stringstream f; f<. + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_EXPRESSION_TEMPLATE_TOOLS_H +#define TRIQS_UTILITY_EXPRESSION_TEMPLATE_TOOLS_H +#include +#include +namespace triqs { namespace utility { + + namespace tags { struct plus{}; struct minus{}; struct multiplies{}; struct divides{}; } + +// The basic operations put in a template.... + template struct operation; + template<> struct operation { + template auto operator()(L const & l, R const & r) const -> decltype(l+r) { return l+r;} + static const char name = '+'; + }; + template<> struct operation { + template auto operator()(L const & l, R const & r) const -> decltype(l-r) { return l-r;} + static const char name = '-'; + }; + template<> struct operation { + template auto operator()(L const & l, R const & r) const -> decltype(l*r) { return l*r;} + static const char name = '*'; + }; + template<> struct operation { + template auto operator()(L const & l, R const & r) const -> decltype(l/r) { return l/r;} + static const char name = '/'; + }; + + // The scalar ... + template struct is_in_ZRC : std::is_arithmetic {}; + template<> struct is_in_ZRC : std::true_type {}; + template struct is_in_ZRC > : std::true_type {}; + + template + struct type_of_mult{ + typedef decltype ( std::declval::type>() * std::declval::type>() ) type; + }; + +}}//namespace triqs::utility +#endif diff --git a/triqs/utility/factory.hpp b/triqs/utility/factory.hpp new file mode 100644 index 00000000..341dff95 --- /dev/null +++ b/triqs/utility/factory.hpp @@ -0,0 +1,97 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_FACTORY_H +#define TRIQS_UTILITY_FACTORY_H +#include +#include +#include "./macros.hpp" +#include "./std_vector_expr_template.hpp" + +namespace triqs { namespace utility { + + template + struct factories { + template < typename U> static T invoke( U && x) { return T(std::forward(x));} + }; + + template + struct factories >{ + typedef std::vector R; + + static R invoke(R && x) { return R(std::move(x));} + + static R invoke(R const & x) { return R(x);} + + static R invoke(R & x) { return R(x);} + + template static R invoke( std::vector && v) { + static_assert(std::is_constructible::value, "Can not make std::vector from std::vector"); + R r; r.reserve(v.size()); + for (auto & x : v) r.push_back(std::move(x)); + return r; + } + + template + static TYPE_ENABLE_IF(R,ImmutableStdVector) invoke( VectorType const & v) { + static_assert(std::is_constructible::value, "Can not make std::vector from the proposed type"); + R r; r.reserve(v.size()); + for(size_t i=0; i static R invoke( std::vector const & v) { + static_assert(std::is_constructible::value, "Can not make std::vector from std::vector"); + R r; r.reserve(v.size()); + for (auto & x : v) r.push_back(T(x)); + return r; + } + */ + }; + + template T factory(U && ... x) { return factories::invoke(std::forward(x)...);} + + // redondant : done with x =factory(x) + // + /* template + struct gal_assign { + template < typename U> static void invoke(T & x, U && y) { x = std::forward(y);} + }; + + template + struct gal_assign> { + typedef std::vector R; + static void invoke(R & x, R && y) { x=std::move(y);} + static void invoke(R & x, R const & y) { x=y;} + template static R invoke( R &r, std::vector && v) { + static_assert(std::is_constructible::value, "Can not assign std::vector && -> std::vector"); + r.clear(); r.reserve(v.size()); + for (auto & x : v) r.push_back(std::move(x)); + } + template static R invoke( R &r, std::vector const & v) { + static_assert(std::is_constructible::value, "Can not assign std::vector const & -> std::vector"); + r.clear(); r.reserve(v.size()); + for (auto & x : v) r.push_back(x); + } + }; + */ + +}}//namespace triqs +#endif diff --git a/triqs/utility/first_include.hpp b/triqs/utility/first_include.hpp new file mode 100644 index 00000000..57e152be --- /dev/null +++ b/triqs/utility/first_include.hpp @@ -0,0 +1,43 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_FIRST_INCLUDE_PYTHON_H +#define TRIQS_ARRAYS_FIRST_INCLUDE_PYTHON_H + +#ifdef TRIQS_BUILDING_LIBRARY +#include +#else +#include +#endif + +// FOR DEBUG ONLY : detection of the version of numpy is automatic. +// Uncomment to use the old API ANYWAY +//#define TRIQS_NUMPY_VERSION_LT_17 + +#ifndef TRIQS_NUMPY_VERSION_LT_17 +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#endif + +// including python first remove some warning +#ifdef TRIQS_WITH_PYTHON_SUPPORT +#include "Python.h" +#endif + +#endif diff --git a/triqs/utility/formatted_output.hpp b/triqs/utility/formatted_output.hpp new file mode 100644 index 00000000..b85368e6 --- /dev/null +++ b/triqs/utility/formatted_output.hpp @@ -0,0 +1,54 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by H. Hafermann + * + * 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 . + * + ******************************************************************************/ +#ifndef TRIQS_FORMATTED_OUTPUT_H +#define TRIQS_FORMATTED_OUTPUT_H + +#include +#include +#include +#include +#include + +namespace triqs { namespace utility { + + inline std::string print_formatted(std::vector> const &out){ + std::vector max_len; + std::ostringstream str; + + for(auto const &s : out){ + max_len.resize(out[0].size(),0); + for(std::size_t i=0; imax_len[i]) max_len[i]=s[i].length(); + } + for(auto const &s : out){ + for(std::size_t i=0; i. + * + ******************************************************************************/ + +// Compiler independant call to Fortran names +#ifndef TRIQS_BIND_FORTRAN_LOWERCASE +#define TRIQS_FORTRAN_MANGLING( id ) id##_ +#else +#error "I do not know what to do with this fortran mangling !" + // ??? +#endif diff --git a/triqs/utility/function_arg_ret_type.hpp b/triqs/utility/function_arg_ret_type.hpp new file mode 100644 index 00000000..d47e8622 --- /dev/null +++ b/triqs/utility/function_arg_ret_type.hpp @@ -0,0 +1,67 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_TRAITS_FUNCTION_H +#define TRIQS_UTILITY_TRAITS_FUNCTION_H +#include +#include +#include + +namespace triqs { namespace utility { + + /** + * Detect argument and return type of a callable object, + * as long as its operator () is not overloaded + * + * \tparam Fun The callable object (object, lambda, etc...) + * + * \return + * * arg::type is the type of the i th argument + * * decay_arg::type is the std::decay<> of the type of the i-th argument + * * result_type is the return type of the function + * * constexpr int arity is the arity + * + * Example : + * Object with such a call : + * + * R operator()( int const &, double ) + * + * result_type = R + * arg<0> = int const & + * arg<1> = double + * decay_arg<0> = int + * decay_arg<1> = double + */ + template + struct function_arg_ret_type : public function_arg_ret_type {}; + + template + struct function_arg_ret_type { + static constexpr int arity = sizeof...(Args); + typedef ReturnType result_type; + template struct arg : std::tuple_element>{}; + template struct decay_arg : std::tuple_element::type...>>{}; + }; + + template + struct function_arg_ret_type : function_arg_ret_type{}; + +}} +#endif diff --git a/triqs/utility/has_traits.hpp b/triqs/utility/has_traits.hpp new file mode 100644 index 00000000..735e553b --- /dev/null +++ b/triqs/utility/has_traits.hpp @@ -0,0 +1,60 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ + +//#include +#include + +/** + * Usage : + * - The macro TRIQS_MAKE_TRAIT_HAS_METHOD ( ReturnType, ArgTypeList, Name, NickName ) + * defines a trait called has_method_NickName such that : + * has_method_NickName::value is true iff + * ReturnType T::Name(ArgTypeList) + * is a valid signature + * + * - The macro TRIQS_MAKE_TRAIT_HAS_CONST_METHOD ( ReturnType, ArgTypeList, Name, NickName ) + * defines a trait called has_method_NickName such that : + * has_method_NickName::value is true iff + * ReturnType T::Name(ArgTypeList) const + * is a valid signature + * + * - Where : + * ArgTypeList is a boost preprocessor sequence e.g. + * TRIQS_MAKE_TRAIT_HAS_CONST_METHOD (void, (int)(double)(string), Truc, Truc) + * makes the trait to check if a object A has method : + * void A::Truc(int,double,string) const + * + */ +#define TRIQS_MAKE_TRAIT_HAS_METHOD_AUX(r,s,p,XX) BOOST_PP_COMMA_IF(p) XX +#define TRIQS_MAKE_TRAIT_HAS_METHOD_IMPL( ReturnType, ArgTypeList, Name, NickName, CONST )\ + template struct has_method_##NickName {\ + typedef char yes[1]; typedef char no[2];\ + template struct SFINAE {};\ + template static yes& Test(SFINAE*);\ + template static no& Test(...);\ + static const bool value = sizeof(Test(0)) == sizeof(yes);\ + }; +#define TRIQS_MAKE_TRAIT_HAS_METHOD( ReturnType, ArgTypeList, Name, NickName) TRIQS_MAKE_TRAIT_HAS_METHOD_IMPL(ReturnType,ArgTypeList,Name,NickName,) +#define TRIQS_MAKE_TRAIT_HAS_CONST_METHOD( ReturnType, ArgTypeList, Name, NickName) TRIQS_MAKE_TRAIT_HAS_METHOD_IMPL(ReturnType,ArgTypeList,Name,NickName,const) +//#define TRIQS_MAKE_TRAIT_HAS_METHOD_TPL( ReturnType, ArgTypeList, TPL,Name, NickName) TRIQS_MAKE_TRAIT_HAS_METHOD_IMPL(ReturnType,ArgTypeList,Name,NickName,,TPL) +//#define TRIQS_MAKE_TRAIT_HAS_CONST_METHOD_TPL( ReturnType, ArgTypeList, TPL, Name, NickName) TRIQS_MAKE_TRAIT_HAS_METHOD_IMPL(ReturnType,ArgTypeList,Name,NickName,const,TPL) + + diff --git a/triqs/utility/legendre.hpp b/triqs/utility/legendre.hpp new file mode 100644 index 00000000..eeb4964c --- /dev/null +++ b/triqs/utility/legendre.hpp @@ -0,0 +1,108 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by L. Boehnke, M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef LEGENDRE_asiowuer +#define LEGENDRE_asiowuer + +#include +#include +#include +#include + +namespace triqs { +namespace utility { + +const std::complex i_c(0.0,1.0); +const double pi = boost::math::constants::pi(); + +// This is T_{nl} following Eq.(E2) of our paper +inline std::complex legendre_T(int n, int l) { + + // we assume n positive. if we need n negative we can fix this here + assert(n >= 0); + + // note: cyl_bessel_j(l,x) give the Bessel functions of the first kind J_l (x) + // one then gets the spherical Bessel with j_l (x) = \sqrt{\pi / (2x)} J_{l+0.5} (x) + return (sqrt(2*l+1)/sqrt(2*n+1)) * exp(i_c*(n+0.5)*pi) * pow(i_c,l) * boost::math::cyl_bessel_j(l+0.5,(n+0.5)*pi); + +} + +// This is t_l^p following Eq.(E8) of our paper +inline double legendre_t(int l, int p) { + + // p is the 1/omega power, it can't be negative + assert(p > 0); + + // in these two cases we can directly give back 0 + if ((l+p)%2 == 0 || p > l+1) return 0.0; + + // the factorials are done here + double f = 1; + for (int i = l+p-1; (i > l-p+1) && (i > 1); i--) f *= i; + for (int i = p-1; i > 1; i--) f /= i; + + return pow( double(-1),double(p) ) * 2 * sqrt(2*l+1) * f; + +} + + +/* + Generates the Legendre polynomials + P_0(x) = 1.0 + P_1(x) = x + n P_{n} = (2n-1) x P_{n-1}(x) - (n-1) P_{n-2}(x) +*/ +class legendre_generator { + + double _x; + uint n; + double cyclicArray[2]; + +public: + + double next() { + if (n>1) + { + uint eo=(n)%2; + cyclicArray[eo]=((2*n-1)*_x*cyclicArray[1-eo]-(n-1)*cyclicArray[eo])/n; + n++; + return cyclicArray[eo]; + } + else + { + n++; + return cyclicArray[n-1]; + } + } + + void reset (double x) { + _x=x; + n=0; + cyclicArray[0]=1.0; + cyclicArray[1]=x; + } + +}; + +}}; + +#endif diff --git a/triqs/utility/macros.hpp b/triqs/utility/macros.hpp new file mode 100644 index 00000000..8bc662bf --- /dev/null +++ b/triqs/utility/macros.hpp @@ -0,0 +1,40 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_MACROS_H +#define TRIQS_UTILITY_MACROS_H + +#include +#include + +#define TYPE_ENABLE_IF(Type,...) typename boost::enable_if < __VA_ARGS__ , Type >::type +#define TYPE_ENABLE_IFC(Type,...) typename boost::enable_if_c < __VA_ARGS__ , Type >::type +#define TYPE_DISABLE_IF(Type,...) typename boost::disable_if< __VA_ARGS__ , Type >::type +#define TYPE_DISABLE_IFC(Type,...) typename boost::disable_if_c< __VA_ARGS__ , Type >::type + +#define ENABLE_IF(...) typename boost::enable_if < __VA_ARGS__ , void >::type +#define ENABLE_IFC(...) typename boost::enable_if_c < __VA_ARGS__ , void >::type +#define DISABLE_IF(...) typename boost::disable_if< __VA_ARGS__ , void >::type +#define DISABLE_IFC(...) typename boost::disable_if_c< __VA_ARGS__ , void >::type + +#define DECL_AND_RETURN(...) -> decltype(__VA_ARGS__) { return __VA_ARGS__;} + +#endif + diff --git a/triqs/utility/mini_vector.hpp b/triqs/utility/mini_vector.hpp new file mode 100644 index 00000000..ae866ffb --- /dev/null +++ b/triqs/utility/mini_vector.hpp @@ -0,0 +1,147 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_MINI_VECTOR_H +#define TRIQS_ARRAYS_MINI_VECTOR_H +#include "./first_include.hpp" +#include +#include "./compiler_details.hpp" +#include "./exceptions.hpp" +#include +#include + +#define TRIQS_MINI_VECTOR_NRANK_MAX 10 + +namespace triqs { namespace utility { + + template + class mini_vector { + T _data[Rank]; + friend class boost::serialization::access; + template void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::make_nvp("_data",_data); } + void init() { for (int i=0;i mini_vector(const mini_vector & x){ *this = x; } + + mini_vector(const std::vector & v){ + if (v.size()!=Rank) + TRIQS_RUNTIME_ERROR<< "mini_vector construction : vector size incorrect : expected "< + mini_vector & operator=(const mini_vector & x){ for (int i=0;i to_vector () const { std::vector V(Rank); for (int i=0;i append (T const & x) const { + mini_vector res; + for (int i=0;i front_append (T const & x) const { + mini_vector res; + for (int i=0;i pop () const { + mini_vector res; + for (int i=0;i front_pop () const { + mini_vector res; + for (int i=1;i + bool operator ==(mini_vector const & v1, mini_vector const & v2) { + for (int i=0;i bool operator !=(mini_vector const & v1, mini_vector const & v2) { return (!(v1==v2));} + + template + mini_vector join (mini_vector const & v1, mini_vector const & v2) { + mini_vector res; + for (int i=0;i + T1 dot_product(mini_vector const & v1, mini_vector const & v2) { + T1 res=0; + for (int i=0;i. + * + ******************************************************************************/ + +#ifndef TRIQS_UTILITY_PADE_APPROXIMANTS_H +#define TRIQS_UTILITY_PADE_APPROXIMANTS_H + +#include "pade_approximants.hpp" +#include +#include + +namespace triqs { namespace utility { + +typedef std::complex dcomplex; + +// This implementation is based on a Fortran code written by +// A. Poteryaev +// +// The original algorithm is described in +// H. J. Vidberg, J. W. Serene. J. Low Temp. Phys. 29, 3-4, 179 (1977) + +struct gmp_complex { + mpf_class re, im; + gmp_complex operator* (const gmp_complex &rhs){ return { rhs.re*re-rhs.im*im, rhs.re*im+rhs.im*re }; } + friend gmp_complex inverse (const gmp_complex &rhs){ mpf_class d=rhs.re*rhs.re + rhs.im*rhs.im; return { rhs.re/d, -rhs.im/d}; } + gmp_complex operator/ (const gmp_complex &rhs){ return (*this)*inverse(rhs); } + gmp_complex operator+ (const gmp_complex &rhs){ return { rhs.re + re, rhs.im + im }; } + gmp_complex operator- (const gmp_complex &rhs){ return { re - rhs.re, im - rhs.im }; } + friend mpf_class real(const gmp_complex &rhs) { return rhs.re; } + friend mpf_class imag(const gmp_complex &rhs) { return rhs.im; } + gmp_complex& operator= (const std::complex &rhs) { re = real(rhs); im = imag(rhs); return *this; } + friend std::ostream & operator << (std::ostream & out,gmp_complex const & r) { return out << " gmp_complex("< z_in; // Input complex frequency points + arrays::vector a; // Pade coefficients + + public: + + static const int GMP_default_prec = 256; // Precision of GMP floats to use during a Pade coefficients calculation. + + pade_approximant(const arrays::vector & z_in_, const arrays::vector & u_in): + z_in(z_in_), a(z_in.size()) { + + int N = z_in.size(); + + // Change the default precision of GMP floats. + unsigned long old_prec = mpf_get_default_prec(); + mpf_set_default_prec(GMP_default_prec); // How do we determine it? + + arrays::array g(N,N); + gmp_complex MP_0 = {0.0, 0.0}; + g() = MP_0; + for (int f = 0; f. + * + ******************************************************************************/ +#ifndef TRIQS_PYTHON_EXTRACTOR_H +#define TRIQS_PYTHON_EXTRACTOR_H +#include + +namespace triqs { namespace utility { namespace python { + + template + class extractor { + T const * _c; + public : + extractor (PyObject * x) { + if (!PyCObject_Check(x)) TRIQS_RUNTIME_ERROR<< " Internal error : extractor contructed from a wrong type !!!!!"; + _c = static_cast(PyCObject_AsVoidPtr(x)); + } + T const & operator() () const { return *_c;} + }; + +}}} +#endif diff --git a/triqs/utility/report_stream.hpp b/triqs/utility/report_stream.hpp new file mode 100644 index 00000000..2d6ff1f6 --- /dev/null +++ b/triqs/utility/report_stream.hpp @@ -0,0 +1,77 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_REPORT_STREAM_H +#define TRIQS_UTILITY_REPORT_STREAM_H +#include +#include + +namespace triqs { namespace utility { + + /** + * \brief Output stream with flexible verbosity level. + * + * This class behaves pretty much like a standard ostream but you can also + * set some verbosity level + * + * Example: + * + * report_stream rep(2); // this creates a report stream w/ verbosity 2 + * rep << "Hello" << endl; // this prints Hello + * rep(2) << "Hello2" << endl; // this prints Hello2 + * rep(3) << "Hello3" << endl; // this doesn't print anything because the verbosity < 3 + * + */ + class report_stream { + + std::ostream * out; + int verbosity; + + public: + + report_stream(std::ostream * out_, int verbosity_ = 1): out(out_), verbosity(verbosity_) {} + + report_stream operator () (int n) { + return report_stream(out, verbosity-n+1); + } + + template + report_stream & operator << (T const & x) { + if (verbosity > 0) (*out)< > CoutType; + + // this is the function signature of std::endl + typedef CoutType& (*StandardEndLine)(CoutType&); + + // define an operator<< to take in std::endl + report_stream & operator << (StandardEndLine manip) { + // call the function, but we cannot return it's value + if (verbosity > 0) manip(*out); + return *this; + } + + }; + +}} +#endif diff --git a/triqs/utility/scope_guard.hpp b/triqs/utility/scope_guard.hpp new file mode 100644 index 00000000..fbf99ca8 --- /dev/null +++ b/triqs/utility/scope_guard.hpp @@ -0,0 +1,51 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_SCOPE_GUARD_H +#define TRIQS_UTILITY_SCOPE_GUARD_H + +namespace triqs { namespace utility { + +// adapted from A. Alexandrescu talk, C++ & beyond 2013. +template +class scope_guard { + Fun f_; + bool active_; + public: + scope_guard(Fun f) : f_(std::move(f)) , active_(true) {} + ~scope_guard() { if (active_) f_(); } + void dismiss() { active_ = false; } + bool active() const { return active_;} + scope_guard() = delete; +#ifdef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + private: + scope_guard(const scope_guard&) = default; + public: +#else + scope_guard(const scope_guard&) = delete; +#endif + scope_guard(scope_guard&& rhs) : f_(std::move(rhs.f_)) , active_(rhs.active_) { rhs.dismiss(); } + scope_guard& operator=(const scope_guard&) = delete; + scope_guard& operator=(scope_guard&& rhs) { using std::swap; swap(f_,rhs.f_); swap(active_, rhs.active_); return *this;} +}; + +template scope_guard scopeGuard(Fun f) { return scope_guard(std::move(f)); } +}} +#endif diff --git a/triqs/utility/serialization.hpp b/triqs/utility/serialization.hpp new file mode 100644 index 00000000..1afa726b --- /dev/null +++ b/triqs/utility/serialization.hpp @@ -0,0 +1,74 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_SERIAL_H +#define TRIQS_SERIAL_H +#include +#include +//#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace triqs { + + // serialize obj into an std::string + template std::string serialize (T const & obj) { + std::string serial_str; + boost::iostreams::back_insert_device inserter(serial_str); + boost::iostreams::stream > s(inserter); + //boost::archive::binary_oarchive oa(s); + boost::archive::text_oarchive oa(s); + oa << obj; + s.flush(); + return serial_str; + } + + template T deserialize (std::string const & serial_str) { + T obj; + // wrap buffer inside a stream and deserialize serial_str into obj + boost::iostreams::basic_array_source device(serial_str.data(), serial_str.size()); + boost::iostreams::stream > s(device); + //boost::archive::binary_iarchive ia(s); + boost::archive::text_iarchive ia(s); + ia >> obj; + return obj; + } + + template void deserialize_into_view (std::string const & serial_str, T & x) { + typename non_view_type_if_exists_else_type::type obj; + // wrap buffer inside a stream and deserialize serial_str into obj + boost::iostreams::basic_array_source device(serial_str.data(), serial_str.size()); + boost::iostreams::stream > s(device); + boost::archive::text_iarchive ia(s); + //boost::archive::binary_iarchive ia(s); + ia >> obj; + x= typename view_type_if_exists_else_type::type (obj); + } +} +#endif + diff --git a/triqs/utility/signal_handler.cpp b/triqs/utility/signal_handler.cpp new file mode 100644 index 00000000..54e3e5ac --- /dev/null +++ b/triqs/utility/signal_handler.cpp @@ -0,0 +1,72 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#include "signal_handler.hpp" +//#include +#include +#include +//#include +//#include +// volatile sig_atomic_t signal_handler::keep_going; + + +namespace triqs { + + /* + namespace signal_details { + // The signal handler just clears the flag and re-enables itself. + // to replace with settimer if needed + void catch_alarm (int sig) + { + MySignalHandler::keep_going = 0; + signal (sig, Catch_alarm); + } + } + */ + std::vector signal_handler::signals_list; + + signal_handler::signal_handler() { + static bool initialized; + if (initialized) return; + //keep_going = 1; /* Establish a handler for SIGALRM signals. */ + static struct sigaction action; + memset(&action, 0, sizeof(action)); + action.sa_handler = &signal_handler::slot; + sigaction(SIGINT, &action, NULL); + sigaction(SIGTERM, &action, NULL); + sigaction(SIGXCPU, &action, NULL); + sigaction(SIGQUIT, &action, NULL); + sigaction(SIGUSR1, &action, NULL); + sigaction(SIGUSR2, &action, NULL); + sigaction(SIGSTOP, &action, NULL); + //signal (SIGALRM, _MYSIGNAL::Catch_alarm); + //alarm (0); + initialized = true; + } + + void signal_handler::slot(int signal) { + std::cerr << "Received signal " << signal << std::endl; + signals_list.push_back(signal); + } + +} + diff --git a/triqs/utility/signal_handler.hpp b/triqs/utility/signal_handler.hpp new file mode 100644 index 00000000..d671b093 --- /dev/null +++ b/triqs/utility/signal_handler.hpp @@ -0,0 +1,43 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef TRIQS_SIGNAL_HANDLER_H +#define TRIQS_SIGNAL_HANDLER_H +#include +#include +#include + +namespace triqs { + + class signal_handler { + static std::vector signals_list; + //static volatile sig_atomic_t keep_going; + public: + signal_handler(); + bool empty(){ return (signals_list.size() ==0); } + int top(){ return signals_list.back(); } + void pop(){ return signals_list.pop_back(); } + static void slot(int signal); + }; +} + +#endif diff --git a/triqs/utility/stack_trace.cpp b/triqs/utility/stack_trace.cpp new file mode 100644 index 00000000..a6f7c01b --- /dev/null +++ b/triqs/utility/stack_trace.cpp @@ -0,0 +1,104 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#include "./stack_trace.hpp" +#include + +#ifndef TRIQS_TRACE_MAX_FRAMES +#define TRIQS_TRACE_MAX_FRAMES 50 +#endif + +#ifdef __GNUC__ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "./typeid_name.hpp" + +namespace triqs { namespace utility { + +//#define TRIQS_STACKTRACE_WITH_GDB +#ifdef TRIQS_STACKTRACE_WITH_GDB + + std::string stack_trace() { + std::ostringstream buffer; + char pid_buf[30]; + sprintf(pid_buf, "%d", getpid()); + char name_buf[512]; + name_buf[readlink("/proc/self/exe", name_buf, 511)]=0; + int child_pid = fork(); + if (!child_pid) { + dup2(2,1); // redirect output to stderr + buffer << "stack trace for "< strs; + boost::split(strs, symbol, boost::is_any_of("\t ()+"), boost::token_compress_on); + for (std::vector::const_iterator it = strs.begin(); it !=strs.end(); ++it) + buffer << " "<. + * + ******************************************************************************/ + +#ifndef TRIQS_UTILITY_TRACE_H +#define TRIQS_UTILITY_TRACE_H +#include +#include + +namespace triqs { namespace utility { + + std::string stack_trace(); + +}} +#endif + + diff --git a/triqs/utility/std_vector_expr_template.hpp b/triqs/utility/std_vector_expr_template.hpp new file mode 100644 index 00000000..69ffbcca --- /dev/null +++ b/triqs/utility/std_vector_expr_template.hpp @@ -0,0 +1,118 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_STD_VECTOR_EXPR_TEMPL_H +#define TRIQS_STD_VECTOR_EXPR_TEMPL_H +#include +#include +#include +#include +namespace triqs { namespace utility { + + // a trait to identify the std::vector ... + TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(ImmutableStdVector); + template struct ImmutableStdVector> : std::true_type{}; + + namespace expr_temp_vec_tools { + template struct scalar_wrap { + typedef S value_type; + S s; scalar_wrap(S const &s_):s(s_){} + S operator[](size_t i) const { return s;} + friend std::ostream &operator <<(std::ostream &sout, scalar_wrap const &expr){return sout << expr.s; } + }; + + // Combine the two sizes of LHS and RHS : need to specialize where there is a scalar + struct combine_size { + template + size_t operator() (L const & l, R const & r) const { + if (!(l.size() == r.size())) TRIQS_RUNTIME_ERROR << "size mismatch : ";//<< l.size()<<" vs" < size_t operator() (scalar_wrap const & w, R const & r) const {return r.size();} + template size_t operator() (L const & l, scalar_wrap const & w) const {return l.size();} + }; + + template struct keeper_type : std::conditional::value, scalar_wrap, T const &> {}; + + template + std::vector make_vector(V const & v) { + std::vector res; res.reserve(v.size()); + for (size_t i =0; i struct std_vec_expr : triqs::utility::ImmutableStdVector__concept_tag { + typedef typename triqs::utility::expr_temp_vec_tools::keeper_type::type L_t; + typedef typename triqs::utility::expr_temp_vec_tools::keeper_type::type R_t; + typedef typename std::result_of(typename std::remove_reference::type::value_type, + typename std::remove_reference::type::value_type)>::type value_t; + typedef value_t value_type; + L_t l; R_t r; + template std_vec_expr(LL && l_, RR && r_) : l(std::forward(l_)), r(std::forward(r_)) {} + size_t size() const { return triqs::utility::expr_temp_vec_tools::combine_size()(l,r); } + value_type operator[](size_t i) const { return triqs::utility::operation()(l[i] , r[i]);} + friend std::ostream &operator <<(std::ostream &sout, std_vec_expr const &expr){return sout << "("<::name << " "< make_vector(std_vec_expr const & v) { return triqs::utility::expr_temp_vec_tools::make_vector(v);} + }; + + // ------------------------------------------------------------------- + //a special case : the unary operator ! + template struct std_vec_expr_unary : triqs::utility::ImmutableStdVector__concept_tag { + typedef typename triqs::utility::expr_temp_vec_tools::keeper_type::type L_t; + typedef typename L_t::value_type value_type; + L_t l; + template std_vec_expr_unary(LL && l_) : l(std::forward(l_)) {} + size_t size() const { return l.size(); } + value_type operator[](size_t i) const { return -l[i];} + friend std::ostream &operator <<(std::ostream &sout, std_vec_expr_unary const &expr){return sout << '-'< make_vector(std_vec_expr_unary const & v) { return triqs::utility::expr_temp_vec_tools::make_vector(v);} + }; + + // ------------------------------------------------------------------- + // Now we can define all the C++ operators ... +#define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \ + template\ + typename std::enable_if::value && triqs::utility::TRAIT2 ::value, std_vec_expr>::type\ + operator OP (A1 const & a1, A2 const & a2) { return std_vec_expr(a1,a2);} + + DEFINE_OPERATOR(plus, +, ImmutableStdVector,ImmutableStdVector); + DEFINE_OPERATOR(minus, -, ImmutableStdVector,ImmutableStdVector); + DEFINE_OPERATOR(multiplies, *, ImmutableStdVector,ImmutableStdVector); + DEFINE_OPERATOR(multiplies, *, is_in_ZRC,ImmutableStdVector); + DEFINE_OPERATOR(multiplies, *, ImmutableStdVector,is_in_ZRC); + DEFINE_OPERATOR(divides, /, ImmutableStdVector,ImmutableStdVector); + DEFINE_OPERATOR(divides, /, is_in_ZRC,ImmutableStdVector); + DEFINE_OPERATOR(divides, /, ImmutableStdVector,is_in_ZRC); +#undef DEFINE_OPERATOR + + // the unary is special + template typename std::enable_if::value, std_vec_expr_unary>::type + operator - (A1 const & a1) { return std_vec_expr_unary(a1);} + +} +#endif + + + diff --git a/triqs/utility/time_pt.hpp b/triqs/utility/time_pt.hpp new file mode 100644 index 00000000..70c86f0a --- /dev/null +++ b/triqs/utility/time_pt.hpp @@ -0,0 +1,117 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by M. Ferrero, O. Parcollet, I. Krivenko + * + * 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 . + * + ******************************************************************************/ +#ifndef TRIQS_CTQMC_KRYLOV_TIME_PT_HPP +#define TRIQS_CTQMC_KRYLOV_TIME_PT_HPP + +#include +#include +#include +#include + +namespace triqs { namespace utility { + + /// A point on a very thin grid, as uint64_t + struct time_pt { + + time_pt() { beta = 1; val =0; n = 0;} + explicit time_pt(double b) { beta = b; val =0; n = 0;} + + private : + // too dangerous because of rounding to be left public + time_pt(double v, double beta_) { beta = beta_; val =v; n = std::floor(Nmax*(v/beta));} + time_pt(uint64_t n_, double beta_, bool) { beta = beta_; val = beta*(double(n_)/Nmax); n = n_;} + + public : + + // random case : to be improved, using rng only for integer for reproducibility.... + template static time_pt random(RNG & rng, T1 l, T2 beta_) { return time_pt(rng(double(l)), double(beta_));} + + time_pt (time_pt const &) = default; + time_pt (time_pt && x) = default; + time_pt & operator = (time_pt const &) = default ; +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + time_pt & operator = (time_pt && x) = default; +#else + time_pt & operator = (time_pt && x) noexcept { using std::swap; swap(n,x.n); swap(beta, x.beta); swap(val, x.val); return *this;} +#endif + + //this is also dangerous for reproducibility + time_pt & operator = (double v) = delete; + + // factories + static time_pt make_beta(double beta_) { time_pt r; r.beta = beta_; r.n = Nmax; r.val = beta_; return r;} + static time_pt make_zero(double beta_) { time_pt r; r.beta = beta_; r.n = 0; r.val = 0; return r;} + static time_pt make_from_double(double x, double beta_) { return time_pt(x,beta_);} + static time_pt epsilon(double beta) { return time_pt(1,beta,true);} + static time_pt epsilon(time_pt const & beta) { return time_pt(1,beta.beta,true);} + + bool operator == (const time_pt & tp) const { return n == tp.n; } + bool operator != (const time_pt & tp) const { return n != tp.n; } + bool operator < (const time_pt & tp) const { return n < tp.n; } + bool operator <= (const time_pt & tp) const { return n <= tp.n; } + bool operator > (const time_pt & tp) const { return n > tp.n; } + bool operator >= (const time_pt & tp) const { return n >= tp.n; } + + // adding and substracting is cyclic on [0, beta] + inline friend time_pt operator+(time_pt const & a, time_pt const & b) { return time_pt(a.n + b.n, a.beta, true); } + inline friend time_pt operator-(time_pt const & a, time_pt const & b) { uint64_t n = (a.n>= b.n ? a.n - b.n : Nmax - (b.n - a.n)); return time_pt(n, a.beta,true); } + + //unary + inline friend time_pt operator-(time_pt const & a) { uint64_t n = Nmax - a.n; return time_pt(n, a.beta,true); } + + // division by integer + inline friend time_pt div_by_int(time_pt const & a, size_t b) { return time_pt(a.n/ b, a.beta, true); } + + // floor_div(x,y) = floor (x/y), but computed on the grid. + inline friend size_t floor_div(time_pt const & a, time_pt const & b){return a.n/b.n;} + + // only EXPLICIT cast + explicit operator double() const {return val;} // cast to a double + + friend std::ostream & operator<< (std::ostream & out, time_pt const & p) { return out << p.val << " [time_pt : beta = "<< p.beta<< " n = "<< p.n<<"]" ; } + + private: + static constexpr uint64_t Nmax = std::numeric_limits::max(); + uint64_t n; + double val, beta; + }; + + // all operations below decay to double + inline double operator*(time_pt const & a, time_pt const & b) { return double(a)*double(b); } + inline double operator/(time_pt const & a, time_pt const & b) { return double(a)/double(b); } + +#define IMPL_OP(OP) \ + inline double operator OP(time_pt const & x, double y) {return static_cast(x) OP y;} \ + inline double operator OP(double y, time_pt const & x) {return y OP static_cast(x);} + IMPL_OP(+); IMPL_OP(-); IMPL_OP(*); IMPL_OP(/); +#undef IMPL_OP + + + // all other operations : first cast into a double and do the operation +/*#define IMPL_OP(OP) \ + template auto operator OP(time_pt const & x, T y) -> decltype(double(0) OP y) {return static_cast(x) OP y;} \ + template auto operator OP(T y, time_pt const & x) -> decltype(y OP double(0)) {return y OP static_cast(x);} \ + IMPL_OP(+); IMPL_OP(-); IMPL_OP(*); IMPL_OP(/); +#undef IMPL_OP*/ + +}} +#endif + diff --git a/triqs/utility/timer.hpp b/triqs/utility/timer.hpp new file mode 100644 index 00000000..67262a48 --- /dev/null +++ b/triqs/utility/timer.hpp @@ -0,0 +1,46 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ + +#ifndef TIMER_OP_H_238rj238rh +#define TIMER_OP_H_238rj238rh + +#include + +namespace triqs { +namespace utility { + +class timer { + clock_t Clock1,Clock2; + bool running; +public: + timer():running(false) {} + void start() { running= true; Clock1 = clock();} + void stop() { Clock2 = clock(); running = false;} + operator double() const {return (Clock2 - Clock1)/CLOCKS_PER_SEC;} + }; +} +} + + +#endif + + diff --git a/triqs/utility/tuple_tools.hpp b/triqs/utility/tuple_tools.hpp new file mode 100644 index 00000000..d9a24866 --- /dev/null +++ b/triqs/utility/tuple_tools.hpp @@ -0,0 +1,164 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_TUPLE_TOOLS_H +#define TRIQS_UTILITY_TUPLE_TOOLS_H +#include +#include +#include + +namespace triqs { namespace tuple { + +/** + * apply(f, t) + * f : a callable object + * t a tuple + * Returns : f(t[0], t[1], ...) + * Equivalent to f(*t) in python .... + * Q : what about constructor + */ + template struct apply_impl { + template + auto operator()(F && f, T const & t, Args && ... args) + DECL_AND_RETURN( apply_impl()(std::forward(f),t, std::get(t), std::forward(args)...)); + }; + + template struct apply_impl<-1,T> { + template + auto operator()(F && f, T const & t, Args && ... args) DECL_AND_RETURN( std::forward(f)(std::forward(args)...)); + }; + + template + auto apply (F && f, T const & t) DECL_AND_RETURN( apply_impl::value-1,T>()(std::forward(f),t)); + + //template + //ReturnType apply(ReturnType(ClassType::*f)(Args...) const, T const & t) { return apply([f](Args const & ... args) { return (*f)(args...);} ,t);} + + template + ReturnType apply( ReturnType(*f)(Args...), T const & t) { return apply([f](Args const & ... args) { return (*f)(args...);} ,t);} + + /** + * for_each(f, t) + * f: a callable object + * t: a tuple + * calls f on all tuple elements: f(x) for all x in t + */ + template struct for_each_impl { + template + void operator()(T const & t, F && f) { + f(std::get::value-1-pos>(t)); + for_each_impl()(t, f); + } + }; + + template<> + struct for_each_impl<0> { + template + void operator() (T const & t, F && f) { f(std::get::value-1>(t)); } + }; + + template + void for_each(T const & t, F && f) { + for_each_impl::value-1>()(t, f); + } + + /** + * apply_on_zip(f, t1,t2) + * f : a callable object + * t1, t2 two tuples of the same size + * Returns : [f(i,j) for i,j in zip(t1,t2)] + */ + template struct apply_on_zip_impl { + template + auto operator()(F && f, T1 const & t1, T2 const & t2, Args && ... args) + DECL_AND_RETURN( apply_on_zip_impl()(std::forward(f),t1, t2, f(std::get(t1),std::get(t2)), std::forward(args)...)); + }; + + template struct apply_on_zip_impl<-1,T1,T2> { + template + auto operator()(F && f, T1 const & t1, T2 const & t2, Args && ... args) DECL_AND_RETURN( std::make_tuple(std::forward(args)...)); + }; + + template + auto apply_on_zip (F && f,T1 const & t1, T2 const & t2) DECL_AND_RETURN( apply_on_zip_impl::value-1,T1,T2>()(std::forward(f),t1,t2)); + + /** + * apply_on_tuple(f, t1,t2,t3) + * f : a callable object + * t1, t2 two tuples of the same size + * Returns : [f(i,j) for i,j in zip(t1,t2)] + */ + template struct apply_on_zip3_impl { + template + auto operator()(F && f, T1 const & t1, T2 const & t2, T3 const & t3, Args && ... args) + DECL_AND_RETURN( apply_on_zip3_impl()(std::forward(f),t1, t2, t3, f(std::get(t1),std::get(t2),std::get(t3)), std::forward(args)...)); + }; + + template struct apply_on_zip3_impl<-1,T1,T2,T3> { + template + auto operator()(F && f, T1 const & t1, T2 const & t2, T3 const & t3, Args && ... args) DECL_AND_RETURN( std::make_tuple(std::forward(args)...)); + }; + + template + auto apply_on_zip3 (F && f,T1 const & t1, T2 const & t2, T3 const & t3) DECL_AND_RETURN( apply_on_zip3_impl::value-1,T1,T2,T3>()(std::forward(f),t1,t2,t3)); + + /** + * fold(f, t1, init) + * f : a callable object + * t a tuple + * Returns : f(x0,f(x1,f(....)) on the tuple + */ + template struct fold_impl { + template + auto operator()(F && f, T & t, R && r ) + DECL_AND_RETURN( fold_impl()(std::forward(f),t, f(std::get(t), std::forward(r)))); + }; + + template struct fold_impl<-1,T> { + template R operator()(F && f, T & t, R && r) {return std::forward(r);} + }; + + template + auto fold (F && f,T & t, R && r) DECL_AND_RETURN( fold_impl::value-1,T>()(std::forward(f),t,std::forward(r))); + template + auto fold (F && f,T const & t, R && r) DECL_AND_RETURN( fold_impl::value-1,T const>()(std::forward(f),t,std::forward(r))); + + /** + * fold_on_zip(f, t1, t2, init) + * f : a callable object + * t1, t2 two tuples of the same size + * Returns : f(x0,y0,f(x1,y1,,f(....)) for t1 = (x0,x1 ...) and t2 = (y0,y1...). + */ + template struct fold_on_zip_impl { + template + auto operator()(F && f, T1 const & t1, T2 const & t2, R && r ) + DECL_AND_RETURN( fold_on_zip_impl()(std::forward(f),t1,t2, f(std::get(t1), std::get(t2), std::forward(r)))); + }; + + template struct fold_on_zip_impl<-1,T1,T2> { + template R operator()(F && f, T1 const & t1, T2 const & t2, R && r) {return std::forward(r);} + }; + + template + auto fold_on_zip (F && f,T1 const & t1, T2 const & t2, R && r) DECL_AND_RETURN( fold_on_zip_impl::value-1,T1,T2>()(std::forward(f),t1,t2,std::forward(r))); + +}} +#endif + diff --git a/triqs/utility/typeid_name.hpp b/triqs/utility/typeid_name.hpp new file mode 100644 index 00000000..b72b0e53 --- /dev/null +++ b/triqs/utility/typeid_name.hpp @@ -0,0 +1,65 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_TYPE_ID_NAME_H +#define TRIQS_TYPE_ID_NAME_H + +#include +#include + +#ifdef __GNUC__ +#include +#endif + +#include + +namespace triqs { namespace utility { + + inline std::string demangle(const char * name) { + std::stringstream fs; +#ifdef __GNUC__ + int status; + char * demangled = abi::__cxa_demangle(name, NULL, NULL, &status); + if (!status) { + std::string res(demangled); + boost::erase_all(res,", boost::tuples::null_type"); + boost::erase_all(res,", -1"); + boost::erase_all(res,", void"); + fs<< res; + free(demangled); + } else fs<< name; + //fs< + std::string typeid_name(T const & A) { return demangle(typeid(A).name());} + + template + std::string typeid_name() { return demangle(typeid(std::declval()).name());} + +}} +#endif diff --git a/triqs/utility/view_tools.hpp b/triqs/utility/view_tools.hpp new file mode 100644 index 00000000..63d3095f --- /dev/null +++ b/triqs/utility/view_tools.hpp @@ -0,0 +1,71 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_UTILITY_VIEWTOOLS_H +#define TRIQS_UTILITY_VIEWTOOLS_H +#include + +namespace triqs { + +// keep old solution for a while to check portability and then remove tag +#define TRIQS_DETECT_VIEWS +#ifdef TRIQS_DETECT_VIEWS + + template void nop(T ...){}; + template struct has_view : std::false_type {}; + template struct has_view(),std::declval()))> : std::true_type {}; + + template::value> struct non_view_type_if_exists_else_type; + template struct non_view_type_if_exists_else_type {typedef T type;}; + template struct non_view_type_if_exists_else_type {typedef typename T::non_view_type type;}; + + template::value> struct view_type_if_exists_else_type; + template struct view_type_if_exists_else_type {typedef T type;}; + template struct view_type_if_exists_else_type {typedef typename T::view_type type;}; + + template::value> struct const_view_type_if_exists_else_type; + template struct const_view_type_if_exists_else_type {typedef T type;}; + template struct const_view_type_if_exists_else_type {typedef const typename T::view_type type;}; + // template struct const_view_type_if_exists_else_type {typedef const typename T::view_type type;}; + +#else + + template struct non_view_type_if_exists_else_type {typedef T type;}; + template struct non_view_type_if_exists_else_type {typedef typename T::non_view_type type;}; + + template struct view_type_if_exists_else_type {typedef T type;}; + template struct view_type_if_exists_else_type {typedef typename T::view_type type;}; + + template struct const_view_type_if_exists_else_type {typedef T type;}; + template struct const_view_type_if_exists_else_type {typedef const typename T::view_type type;}; + // template struct const_view_type_if_exists_else_type {typedef const typename T::view_type type;}; + +#endif + + // replacement of std::plus for views ... + template struct add_views : std::binary_function { + T operator() (const T& x, const T& y) const + { typename T::non_view_type r(x); r =r + y; return r;} + }; + + +}//namespace triqs +#endif +

    () << std::endl; + std::cout << P() << std::endl; + std::cout << P() << std::endl; + +#define COMPOSE(P1,P2)\ + std::cout << " composing " << P() << " and "<< P() << " = "<< P() << std::endl ; + +#define INVERSE(P1)\ + std::cout << "inverse of "<< P() << " = "<< P() << std::endl;\ + std::cout << " checking "<< P() << std::endl; + COMPOSE(p,p); + COMPOSE(p2,p2); + INVERSE(p); + INVERSE(p2); + INVERSE(pc); + +#define ID(n)\ + std::cout << " identity :" << P() << std::endl ;\ + std::cout << " ridentity :" << P() << std::endl<. + * + ******************************************************************************/ + +#include "./common.hpp" +#include "./src/array.hpp" +#include + +//using std::cout; using std::endl; +//using namespace triqs::arrays; +#include + +static_assert( ! std::is_pod< triqs::arrays::array >::value, "POD pb"); + +int main(int argc, char **argv) { + + + triqs::arrays::array A (2,3); + + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + { A(i,j) = 10*i+ j; } + + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + std::cout<<"A "< + +using std::cout; using std::endl; +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + triqs::arrays::matrix A(5,5,FORTRAN_LAYOUT); + + A() = 2; + std::cout<<"A = "< AA(A); AA = 2; + std::cout<<"A = "<. + * + ******************************************************************************/ + +#include "./common.hpp" +#include "./src/array.hpp" +#include +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +#include +#include + +int main(int argc, char **argv) { + + + + array A (2,3); + + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + A(i,j) = 10*i+ j; + + array_view SL( A(0,range(0,3))); + std::cout<<"A = "<> A>> SL; + // archive and stream closed when destructors are called + } + std::cout<<"A is "<. + * + ******************************************************************************/ +#include "./common.hpp" +#include +#include +#include +#include +#include + +using namespace triqs::arrays; +using namespace triqs::arrays::permutations; + +template struct P { + static constexpr ull value = F; + friend std::ostream & operator <<( std::ostream & out, P const & s) { + //out << "Permutation of size " << permutations::size(s.value) << " : "<< std::hex; + out << std::hex; + s.print(out, std::integral_constant()); + return out << std::dec; + } + + template void print( std::ostream & out, std::integral_constant) const { out << apply(this->value,c); print(out, std::integral_constant());} + void print( std::ostream & out, std::integral_constant) const {} +}; + +template void test() { + + typedef indexmaps::cuboid::slicing_TO_order::sliced_memory_order S1; + constexpr auto s1 = S1::value; + //std::cout << " sliced "<< std::hex<< S1::value << " " <() << std::endl; + std::cout << P() << std::endl; + //std::cout << "mashk "<< std::hex<(); + test< permutation(0,1,2) ,permutation(0,1,2,3), range, range,int, range>(); + test< permutations::identity(4) ,permutation(0,1,2,3), range, range, range, range>(); + //test< permutation(0,1,2,3) ,permutation(0,1,2,3), range, range, range, range>(); + test< 0 ,permutation(0,1,2,3), int, int, int, int> (); + + std::cout << " c order " << std::endl ; + test< permutation(1,0) ,permutation(3,2,1,0), int, range,int, range>(); + test< permutation(2,1,0) ,permutation(3,2,1,0), int, range, range, range>(); + test< permutation(2,1,0) ,permutation(3,2,1,0), range,int, range, range>(); + test< permutation(2,1,0) ,permutation(3,2,1,0), range, range,int, range>(); + test< permutation(2,1,0) ,permutation(3,2,1,0), range, range, range, int>(); + test< permutation(3,2,1,0) ,permutation(3,2,1,0), range, range, range, range>(); + test< 0 ,permutation(3,2,1,0), int, int, int, int> (); + + test< permutation(0), permutation(0,1), int, range>(); + + std::cout << " custom order " << std::endl ; + test< permutation(1,0) ,permutation(0,3,1,2), int, range,int, range>(); + test< permutation(2,0,1) ,permutation(0,3,1,2), int, range, range, range>(); + test< permutation(0,2,1) ,permutation(0,3,1,2), range,int, range, range>(); + test< permutation(0,2,1) ,permutation(0,3,1,2), range, range,int, range>(); + test< permutation(0,1,2) ,permutation(0,3,1,2), range, range, range, int>(); + test< permutation(0,3,1,2) ,permutation(0,3,1,2), range, range, range, range>(); + test< 0 ,permutation(0,3,1,2), int, int, int, int> (); + + std::cout << " ----------- custom order ------------- " << std::endl ; + + std::cout << " ---- 0 int "<< std::endl ; + test< permutation(2,0,3,1) ,permutation(2,0,3,1), range, range, range, range>(); + + std::cout << " ---- 1 int "<< std::endl ; + test< permutation(1,2,0) ,permutation(2,0,3,1), int, range, range, range>(); + test< permutation(1,0,2) ,permutation(2,0,3,1), range,int, range, range>(); + test< permutation(0,2,1) ,permutation(2,0,3,1), range, range,int, range>(); + test< permutation(2,0,1) ,permutation(2,0,3,1), range, range, range, int>(); + + std::cout << " ---- 2 int "<< std::endl ; + test< permutation(0,1) ,permutation(2,0,3,1), int, int, range, range>(); + test< permutation(1,0) ,permutation(2,0,3,1), int, range,int, range>(); + test< permutation(1,0) ,permutation(2,0,3,1), int, range,range, int>(); + test< permutation(0,1) ,permutation(2,0,3,1), range,int, int, range>(); + test< permutation(1,0) ,permutation(2,0,3,1), range,int, range, int>(); + test< permutation(0,1) ,permutation(2,0,3,1), range, range,int, int>(); + + std::cout << " ---- 3 int "<< std::endl ; + test< permutation(0) ,permutation(2,0,3,1), range, int, int, int>(); + test< permutation(0) ,permutation(2,0,3,1), int,range, int, int>(); + test< permutation(0) ,permutation(2,0,3,1), int, int,range, int>(); + test< permutation(0) ,permutation(2,0,3,1), int, int, int, range>(); + + std::cout << " ---- 4 int "<< std::endl ; + test< 0 ,permutation(2,0,3,1), int, int, int, int> (); + std::cout << " OK "<< std::endl ; + +} diff --git a/test/triqs/arrays/src b/test/triqs/arrays/src new file mode 120000 index 00000000..a8efa258 --- /dev/null +++ b/test/triqs/arrays/src @@ -0,0 +1 @@ +../../../triqs/arrays \ No newline at end of file diff --git a/test/triqs/arrays/swap.cpp b/test/triqs/arrays/swap.cpp new file mode 100644 index 00000000..1206ebe4 --- /dev/null +++ b/test/triqs/arrays/swap.cpp @@ -0,0 +1,85 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/array.hpp" +#include "./src/vector.hpp" +#include + +namespace tqa=triqs::arrays; + +int main(int argc, char **argv) { + + + + std::cout << "With swap"<< std::endl; + { + triqs::arrays::vector V(3), W(4);; + V() = 3; W()=4; + + auto VV = V(tqa::range (0,2)); + auto VW = W(tqa::range (0,2)); + + std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + swap(V,W); + std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + swap(VV,VW); + std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + + } + + std::cout << "With std::swap"<< std::endl; + + { + triqs::arrays::vector V(3), W(4);; + V() = 3; W()=4; + + auto VV = V(tqa::range (0,2)); + auto VW = W(tqa::range (0,2)); + + std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + std::swap(V,W); + std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + + // This does NOT compile, the std::swap specialization is deleted. + //std::swap(VV,VW); + //std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + + } + std::cout << "With deep_swap"<< std::endl; + + { + triqs::arrays::vector V(3), W(3);; + V() = 3; W()=4; + + auto VV = V(tqa::range (0,2)); + auto VW = W(tqa::range (0,2)); + + std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + deep_swap(V,W); + std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + deep_swap(VV,VW); + std::cout << "V = "<< V << " W = " << W<< " V view "<< VV<< " W view "<< VW<< std::endl; + + } + + + return 0; +} diff --git a/test/triqs/arrays/swap.output b/test/triqs/arrays/swap.output new file mode 100644 index 00000000..8f0af2b8 --- /dev/null +++ b/test/triqs/arrays/swap.output @@ -0,0 +1,11 @@ +With swap +V = [3,3,3] W = [4,4,4,4] V view [3,3] W view [4,4] +V = [4,4,4,4] W = [3,3,3] V view [3,3] W view [4,4] +V = [4,4,4,4] W = [3,3,3] V view [4,4] W view [3,3] +With std::swap +V = [3,3,3] W = [4,4,4,4] V view [3,3] W view [4,4] +V = [4,4,4,4] W = [3,3,3] V view [3,3] W view [4,4] +With deep_swap +V = [3,3,3] W = [4,4,4] V view [3,3] W view [4,4] +V = [4,4,4] W = [3,3,3] V view [4,4] W view [3,3] +V = [3,3,4] W = [4,4,3] V view [3,3] W view [4,4] diff --git a/test/triqs/arrays/tridiag.cpp b/test/triqs/arrays/tridiag.cpp new file mode 100644 index 00000000..28f4699b --- /dev/null +++ b/test/triqs/arrays/tridiag.cpp @@ -0,0 +1,60 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#include "./common.hpp" +#include "./src/matrix.hpp" +#include "./src/asserts.hpp" +#include "./src/linalg/matmul.hpp" +#include "./src/linalg/eigenelements.hpp" +#include "./src/blas_lapack/stev.hpp" +#include +#include +using namespace triqs::arrays; +using namespace triqs; + +int main(int argc, char **argv) { + + arrays::vector D (5), DD(4); + for (size_t i=0; i<5; ++i) {D(i) = 3.2*i+2.3;} + for (size_t i=0; i<4; ++i) {DD(i) = 2.4*(i+1.82) + 0.78;} + + auto R = range(0,5); + + blas::tridiag_worker w(10); + w(D,DD); + std::cerr<<" values = "<< w.values()< +using std::cout; using std::endl; +using namespace triqs::arrays; + +int main(int argc, char **argv) { + triqs::arrays::vector V(5); + for (int i =0; i<5; ++i) V[i] = i+1; + V *=2; + std::cout<< V< V2(5,-2.3); + std::cout<< V2<. + * + ******************************************************************************/ + +#include "./common.hpp" + +#include "./src/vector.hpp" +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + + triqs::arrays::vector V(5); + + for (int i =0; i<5; ++i) + V(i) = i+1; + + V *=2; + + std::cout<< V<. + * + ******************************************************************************/ + +#include "./common.hpp" + +#include "./src/vector.hpp" +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + triqs::arrays::vector V(5), W; + + for (int i =0; i<5; ++i) + V(i) = i+1; + + std::cout<< V< A(3); + A() = 10; + W(range(0,6,2)) = A; + std::cout<< W < + +using std::cout; using std::endl; +using namespace triqs::arrays; + +int main(int argc, char **argv) { + + + + { + std::cout<<"test doc eg"< *p = new array (2,3); // create an array p + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + (*p)(i,j) = 10*i+ j; + array_view B(*p); // making a view + delete p; // p is gone... + B(0,0) = 314; + std::cout< A (2,3); + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + A(i,j) = 10*i+ j; + + array_view AA (A); + + std::cout<<"A is "< SL( A(0,range(0,3))); + array_view SL2( A(1,range(0,2))); + array_view SL2b( A(1,range(1,3))); + + std::cout<<"SLICE : A(0,range(0,3)) "< SL( A(range(0,2),0)); + array_view SL2( A(range(0,2),1)); + + std::cout<<"SLICE : A(range(0,2),0)) "< V(A); + std::cout<< V(0,0)<. + * + ******************************************************************************/ +#include "./common.hpp" +#define ARRAY_DEBUG_SLICE +#define TRIQS_ARRAYS_USE_OLD_KEY_EVAL + +#include "./src/array.hpp" +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +/// +template +void print_in_indexmap_order (std::ostream & out, IM const & im, A const & a) { + out<<"["; + for (typename IM::iterator it(im); it; ++it) out< +void f(AA & A) { + + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + for (int k=0; k<4; ++k) + A(i,j,k) = 100*(i+1)+ 10*(j+1) + (k+1); + + print_in_indexmap_order(std::cout,A.indexmap(),A);std::cout< > > A0 (2,3,4); + //array > > A1 (2,3,4); + //array > > A2 (2,3,4); + + // permutation in triqs::arrays + array A0 (2,3,4); + array A1 (2,3,4); + array A2 (2,3,4); + array A3 (2,3,4); + array A4 (2,3,4,FORTRAN_LAYOUT); + + f(A0); + f(A1); + f(A2); + f(A3); + f(A4); + } + + catch (const char * ERR) { + + std::cout<<"Error is "<. + * + ******************************************************************************/ + +#include "./common.hpp" +#include "./src/array.hpp" +#include + +using std::cout; using std::endl; +using namespace triqs::arrays; + +#include +#include +#include + +bool te(int x) { return (x<25);} + +int main(int argc, char **argv) { + + + array A (2,3); + for (int i =0; i<2; ++i) + for (int j=0; j<3; ++j) + A(i,j) = 10*i+ j; + + std::vector > VV; + VV.push_back(A); + + std::map > MAP; + MAP["1"] = A; + std::cout<<"printing map"< V (10); + array B(V.size()), C(V.size()); + + //put something in V + for (unsigned int i =0; i<10; ++i) V[i] = 10+i; + + // copy to B. Iterators on array are STL compliant so STL algorithms work. + std::copy(V.begin(),V.end(),B.begin()); + std::cout<<" B = "<< B<(std::cout,",")); + + // countif + std::cout<<" B= "<< B< + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) const { return make_expr_call (std::ref(*this),args...);} + + template< typename... Args> + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) { return make_expr_call (std::ref(*this),args...);} + + template friend void triqs_clef_auto_assign (F7 & x, Fnt f) { x.v++; std::cerr<< " called triqs_clef_auto_assign "<< f(1,2,3,4,5,6,7)< x1_; +triqs::clef::placeholder <2> x2_; +triqs::clef::placeholder <3> x3_; +triqs::clef::placeholder <4> x4_; +triqs::clef::placeholder <5> x5_; +triqs::clef::placeholder <6> x6_; +triqs::clef::placeholder <7> x7_; +triqs::clef::placeholder <8> x8_; + +int main() { + + F7 f(7), g(8), h(7); + TEST(tql::eval(f(x1_,x2_,x3_,x4_,x5_,x6_,x7_),x_ =1, y_ =2)); + +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << x1_ + x2_ + x3_ + x4_ + x5_ + x6_ + x7_ ; +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << x1_ + 2*x2_ + x3_ + x4_ + x5_ + x6_ + x7_ ; +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << x1_ + 2*x2_ + 4*x3_ + x4_ + x5_ + x6_ + x7_ + g(x1_,x2_,x3_,x4_,x5_,x6_,x7_)* h(x1_,x2_,x3_,x4_,x5_,x6_,x7_) ; +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << x1_ + 2*x2_ + 4*x3_ + 8*x4_ + x5_ + x6_ + x7_ + g(x1_,x2_,x3_,x4_,x5_,x6_,x7_)* h(x1_,x2_,x3_,x4_,x5_,x6_,x7_) ; + +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << x1_ + x2_ -x3_ + x4_ + x5_ + x6_ + x7_ ; +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << x1_ + 2*x2_ + x3_ + x4_ - x5_ + x6_ + x7_ ; +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << x1_ + 2*x2_ + 4*x3_ + x4_ - x5_ + x6_ + x7_ + g(x1_,x2_,x3_,x4_,x5_,x6_,x7_)* h(x1_,x2_,x3_,x4_,x5_,x6_,x7_) ; +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << g(x1_,x2_,x3_,x4_,x5_,x6_,x7_)/ h(x1_,x2_,x3_,x4_,x5_,x6_,x7_) + g(x1_,x2_,x3_,x4_,x5_,x6_,x7_)* h(x1_,x2_,x3_,x4_,x5_,x6_,x7_) ; + +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << x1_ + x2_ -x3_ + x4_ + x5_ + x6_ - x7_ ; +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << x1_ + 2*x2_ + x3_ + x4_ - x5_ + x6_ - x7_ ; +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << x1_ + 2*x2_ + 4*x3_ + x4_ - x5_ + x6_ + x7_ - g(x1_,x2_,x3_,x4_,x5_,x6_,x7_)* h(x1_,x2_,x3_,x4_,x5_,x6_,x7_) ; +f(x1_,x2_,x3_,x4_,x5_,x6_,x7_) << g(x1_,x2_,x3_,x4_,x5_,x6_,x7_)/ h(x1_,x2_,x3_,x4_,x5_,x6_,x7_) - g(x1_,x2_,x3_,x4_,x5_,x6_,x7_)* h(x1_,x2_,x3_,x4_,x5_,x6_,x7_) ; + +} diff --git a/test/triqs/clef/F7.output b/test/triqs/clef/F7.output new file mode 100644 index 00000000..3cb059f8 --- /dev/null +++ b/test/triqs/clef/F7.output @@ -0,0 +1 @@ +(tql::eval(f(x1_,x2_,x3_,x4_,x5_,x6_,x7_),x_ =1, y_ =2)) ---> F7(1, 2, _3, _4, _5, _6, _7) diff --git a/test/triqs/clef/array_as_value.output b/test/triqs/clef/array_as_value.output new file mode 100644 index 00000000..c5a6a798 --- /dev/null +++ b/test/triqs/clef/array_as_value.output @@ -0,0 +1,16 @@ +(tqa::make_array( tql::eval( 2.0*x_ , x_ =A) )) ---> [2,4,6] +(tqa::make_array( tql::eval(2.0*x_ , x_ =3*A) )) ---> [6,12,18] +(tqa::make_array( tql::eval (A + 2*x_ , x_ =A) )) ---> [3,6,9] +(( tql::eval (A + 2*x_ , x_ =A) )) ---> ([1,2,3] + 2 * [1,2,3]) +(A(i_)) ---> [1,2,3](x4,) +(tql::eval( A(i_), i_=1)) ---> 2 +(tql::eval( B(i_,j_) , i_ = 1, j_ = 1)) ---> 10 + +[[0,1] + [10,11]] + +[[0,10] + [1,11]] + +[[0,-2] + [1,-1]] diff --git a/test/triqs/clef/array_as_value_long.output b/test/triqs/clef/array_as_value_long.output new file mode 100644 index 00000000..53a1e81a --- /dev/null +++ b/test/triqs/clef/array_as_value_long.output @@ -0,0 +1,13 @@ +(tqa::make_array( tql::eval( 2.0*x_ , x_ =A) )) ---> [2,4,6] +(tqa::make_array( tql::eval(2.0*x_ , x_ =3*A) )) ---> [6,12,18] +(tqa::make_array( tql::eval (A + 2*x_ , x_ =A) )) ---> [3,6,9] +(( tql::eval (A + 2*x_ , x_ =A) )) ---> ([1,2,3] + 2 * [1,2,3]) +(A(i_)) ---> [1,2,3](x4,) +(tql::eval( A(i_), i_=1)) ---> 2 +(tql::eval( B(i_,j_) , i_ = 1, j_ = 1)) ---> 10 + +[[0,1] + [10,11]] + +[[0,50] + [1,51]] diff --git a/test/triqs/clef/chain_call.cpp b/test/triqs/clef/chain_call.cpp new file mode 100644 index 00000000..86c35ea8 --- /dev/null +++ b/test/triqs/clef/chain_call.cpp @@ -0,0 +1,50 @@ +#include "./common.hpp" + +#include + +struct F2_vec { + std::vector vec; + F2_vec(size_t siz=0): vec (siz) {} + F2_vec(F2_vec const & x): vec(x.vec) {} + + F2 const & operator()(size_t i) const { return vec[i];} + + template< typename... Args> + typename triqs::clef::result_of::make_expr_call::type + operator()( Args&&... args ) const { return triqs::clef::make_expr_call (*this,args...);} + + template + friend void triqs_clef_auto_assign (F2_vec const & x, Fnt f) { + for (size_t i=0; i< x.vec.size(); ++i) triqs_clef_auto_assign(x.vec[i], f(i)); } + + friend std::ostream & operator<<(std::ostream & out, F2_vec const & x) { return out<<"F2_vec";} +}; + +triqs::clef::placeholder <4> i_; + +using namespace triqs::clef; +int main() { + + F2_vec V(3); + + //double x=1,y=2; + + { + auto expr = V(i_)(x_,y_); + std::cout<<"expr = "<< expr<< std::endl; + + TEST( tql::eval(expr, x_=2,y_=3, i_=0)); + TEST( tql::eval(expr, x_=2)); + TEST( tql::eval(expr, x_=2,i_=1)); + TEST( tql::eval(expr, x_=2,y_=3)); + TEST( tql::eval( tql::eval(expr, x_=2,y_=3) , i_=0) ); + std::cout<<"-------------"< 23 +(tql::eval(expr, x_=2)) ---> F2_vec(_4)(2, _2) +(tql::eval(expr, x_=2,i_=1)) ---> F2(2, _2) +(tql::eval(expr, x_=2,y_=3)) ---> F2_vec(_4)(2, 3) +(tql::eval( tql::eval(expr, x_=2,y_=3) , i_=0)) ---> 23 +------------- diff --git a/test/triqs/clef/common.hpp b/test/triqs/clef/common.hpp new file mode 100644 index 00000000..4369a405 --- /dev/null +++ b/test/triqs/clef/common.hpp @@ -0,0 +1,67 @@ +#include +#include +#define TEST(X) std::cout << BOOST_PP_STRINGIZE((X)) << " ---> "<< (X) < + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) const { return make_expr_call (std::ref(*this),args...);} + + template< typename... Args> + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) { return make_expr_call (std::ref(*this),args...);} + + template friend void triqs_clef_auto_assign (F1 & x, Fnt f) { x.v++; std::cerr<< " called triqs_clef_auto_assign "<< f(100)< v_ptr; + + F1b(double v_): v_ptr (new double(v_)) {v=v_;} // on purpose, I avoid adding a default constructor ! + F1b (F1b const & x) { v_ptr = x.v_ptr; v = x.v; std::cerr<< " F1 COPY "< + typename triqs::clef::result_of::make_expr_call::type + operator()( Args&&... args ) { return triqs::clef::make_expr_call (*this,args...);} + + template friend void triqs_clef_auto_assign (F1b & x, Fnt f) { (*(x.v_ptr))++; std::cerr<< " called triqs_clef_auto_assign "<< f(100)< + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) const { return make_expr_call (std::ref(*this),args...);} + + template< typename... Args> + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) { return make_expr_call (std::ref(*this),args...);} + + template friend void triqs_clef_auto_assign (F2 const & x, Fnt f) { std::cerr<< " called F2 triqs_clef_auto_assign "<< f(10,20)< x_; +triqs::clef::placeholder <2> y_; +triqs::clef::placeholder <3> z_; +namespace tql= triqs::clef; + diff --git a/test/triqs/clef/function.cpp b/test/triqs/clef/function.cpp new file mode 100644 index 00000000..4008912e --- /dev/null +++ b/test/triqs/clef/function.cpp @@ -0,0 +1,38 @@ +#include "./common.hpp" + +int main() { + F1 f(7); + + TEST((x_ >> (2*x_ +1) )(10)); + + triqs::clef::function f2; + f2(x_,y_) = x_ + y_; + TEST(f2(2,3)); + f2(x_,y_) << x_ + 2*y_; + TEST(f2(2,3)); + + std::function ff2(f2); + TEST(ff2(2,3)); + + triqs::clef::function f1 ( f(x_) + 2*x_ ,x_); + TEST(f1(3)); + + triqs::clef::function g2; + g2(x_,y_) << x_ - y_ + f2(x_,2*y_); + TEST(g2(2,3)); + + std::function ff8 = make_function( x_ + y_, x_, y_); + TEST(ff8(2,3)); + + std::function f3; + f3 = x_>> f(x_) + 2*x_; + TEST(f3(3)); + + auto h = make_function( 2*x_ + y_ + 1, x_); + // is a lazy expression expression with placeholder y_, returning a function... + std::cout << tql::eval(h, y_=1) << std::endl; + TEST(tql::eval( h, y_=1) (10)); + TEST(h); + +} + diff --git a/test/triqs/clef/function.output b/test/triqs/clef/function.output new file mode 100644 index 00000000..b66f5012 --- /dev/null +++ b/test/triqs/clef/function.output @@ -0,0 +1,11 @@ +((x_ >> (2*x_ +1) )(10)) ---> 21 +(f2(2,3)) ---> 5 +(f2(2,3)) ---> 8 +(ff2(2,3)) ---> 8 +(f1(3)) ---> 36 +(g2(2,3)) ---> 13 +(ff8(2,3)) ---> 5 +(f3(3)) ---> 36 +lazy function : (_1) --> (((2 * _1) + 1) + 1) +(tql::eval( h, y_=1) (10)) ---> 22 +(h) ---> lazy function : (_1) --> (((2 * _1) + _2) + 1) diff --git a/test/triqs/clef/general.cpp b/test/triqs/clef/general.cpp new file mode 100644 index 00000000..a14761fc --- /dev/null +++ b/test/triqs/clef/general.cpp @@ -0,0 +1,107 @@ +#include "./common.hpp" + +double x=1,y=2; + +template < typename Expr > +void test1( Expr expr) { + TEST(expr); + TEST(eval( expr, x_=5)); + std::cout<<"-------------"< +void test2( Expr const & expr) { + // std::cout << " type is " << triqs::utility::typeid_name(expr) << std::endl; + std::cout<< " ------ start test2 -----------------"<y_ , 2*x_ , y_) ,x_=1, y_=3)); +} + std::cout << (x_ < y_) < (5 * _1) +(eval( expr, x_=5)) ---> 25 +------------- + ------ start test2 ----------------- +(expr) ---> (_1 + (2 * _2)) +(eval(expr,x_ =1, y_ =2)) ---> 5 +(eval(expr,x_ =1)) ---> (1 + (2 * _2)) +(eval(expr,x_ =x_ + y_)) ---> ((_1 + _2) + (2 * _2)) +(eval( eval ( expr,x_ =x_ + y_), x_ = 1, y_ = 2)) ---> 7 + ------ start test2 ----------------- +(expr) ---> ((_1 + (2 * _2)) + _1) +(eval(expr,x_ =1, y_ =2)) ---> 6 +(eval(expr,x_ =1)) ---> ((1 + (2 * _2)) + 1) +(eval(expr,x_ =x_ + y_)) ---> (((_1 + _2) + (2 * _2)) + (_1 + _2)) +(eval( eval ( expr,x_ =x_ + y_), x_ = 1, y_ = 2)) ---> 10 + ------ start test2 ----------------- +(expr) ---> ((_1 / 2) + (2 * _2)) +(eval(expr,x_ =1, y_ =2)) ---> 4.5 +(eval(expr,x_ =1)) ---> (0.5 + (2 * _2)) +(eval(expr,x_ =x_ + y_)) ---> (((_1 + _2) / 2) + (2 * _2)) +(eval( eval ( expr,x_ =x_ + y_), x_ = 1, y_ = 2)) ---> 5.5 + ------ start test2 ----------------- +(expr) ---> F1(_1) +(eval(expr,x_ =1, y_ =2)) ---> 10 +(eval(expr,x_ =1)) ---> 10 +(eval(expr,x_ =x_ + y_)) ---> F1((_1 + _2)) +(eval( eval ( expr,x_ =x_ + y_), x_ = 1, y_ = 2)) ---> 30 + ------ start test2 ----------------- +(expr) ---> (F1(_1) + (2 * _2)) +(eval(expr,x_ =1, y_ =2)) ---> 14 +(eval(expr,x_ =1)) ---> (10 + (2 * _2)) +(eval(expr,x_ =x_ + y_)) ---> (F1((_1 + _2)) + (2 * _2)) +(eval( eval ( expr,x_ =x_ + y_), x_ = 1, y_ = 2)) ---> 34 + ------ start test2 ----------------- +(expr) ---> ((1 / F1(_1)) + (2 * _2)) +(eval(expr,x_ =1, y_ =2)) ---> 4.1 +(eval(expr,x_ =1)) ---> (0.1 + (2 * _2)) +(eval(expr,x_ =x_ + y_)) ---> ((1 / F1((_1 + _2))) + (2 * _2)) +(eval( eval ( expr,x_ =x_ + y_), x_ = 1, y_ = 2)) ---> 4.03333 +4 = 4 +12 = 12 +9 = 9 +9 = 9 +12 = 12 +------------- + f.v before assign 7 + f.v after assign 8 +------------- + fb.v before assign 7 7 + fb.v after assign 7 8 +------------- +expr = (F2(_1, _2) + (2 * _2)) +eval(expr,x_ =1, y_ =2) = 16 and it should be 16 + tmp =F2(2, _2) +another = F2(2, _2) +another = 12 +------------- +(eval( if_else( true , 2*x_ , y_) , x_=1, y_=3)) ---> 2 +(eval( if_else( false , 2*x_ , y_) ,x_=1, y_=3)) ---> 3 +(eval( if_else( x_>y_ , 2*x_ , y_) ,x_=1, y_=3)) ---> 3 +(_1 < _2) diff --git a/test/triqs/clef/lazy.cpp b/test/triqs/clef/lazy.cpp new file mode 100644 index 00000000..196e38a0 --- /dev/null +++ b/test/triqs/clef/lazy.cpp @@ -0,0 +1,34 @@ +#include "./common.hpp" +#include + +using namespace triqs::clef; + +triqs::clef::placeholder <10> i_; +triqs::clef::placeholder <11> j_; + +int main() { + + std::vector V(3), W(3); + V[0]=14; V[1]=2; V[2]=3; + std::cout<< "V = "<< V[0]<<" "< > v2 (3, std::vector(2)); + + lazy(v2)[i_][j_] << (i_ + j_ + 1); + + for (size_t u=0; u 14 +V = 2 3 4 +W = 2 4 6 +11 +22 +22 +33 +33 +44 diff --git a/test/triqs/clef/lazy_function.cpp b/test/triqs/clef/lazy_function.cpp new file mode 100644 index 00000000..a8dbf7be --- /dev/null +++ b/test/triqs/clef/lazy_function.cpp @@ -0,0 +1,46 @@ +#include "./common.hpp" + +int main() { + + { + auto r = x_ >> 2 ; + auto r3 = r(3) ; + std::cout<<"expr = "<< r3 << std::endl; + std::cout<<"-------------"<> expr ; + std::cerr<<"expr = "<< r4 << std::endl; + auto r3 = r(3) ; + std::cout<<"expr = "<< r3 << std::endl; + std::cout<<"-------------"<> x_ + 2*y_) ); + TEST( x_ >> (y_ >> x_ + 2*y_ )); + auto r = y_ >> x_ + 2*y_ ; + std::cout<<" r >> = "<< r << std::endl; + auto r2 = x_ >> r ; + std::cout<<" r2 >> = "<< r2 << std::endl; + } + { + auto expr = x_ + 2*y_; + std::cout<<"expr = "<< expr<< std::endl; + auto r= make_function(expr , x_) ; + auto r2= tql::eval( r , y_ = 2) ; + auto r3 = r2(3) ; + std::cout<<"expr = "<< r3 << std::endl; + TEST( tql::eval ( make_function(x_ + 2*y_ , x_) , y_ = 2) (3)); + TEST( make_function(x_ + 2 , x_) (3)); + std::cout<<"-------------"< + +double foo(double x) { return x/2;} +int foo(int x) { return x/2;} + +double bar(double x, double y) { return x+y;} + +namespace triqs { namespace clef { + + using ::foo; + using ::bar; + + template + typename std::enable_if::value,T>::type + inc (T const & x) { return x+1;} +// using ::inc; + // moving the declaration up and using using:: does not work on gcc4.4 + // however not using using:: does not work on icc 11 ! + + TRIQS_CLEF_MAKE_FNT_LAZY (bar) ; + TRIQS_CLEF_MAKE_FNT_LAZY ( inc) ; + TRIQS_CLEF_MAKE_FNT_LAZY ( foo) ; + }} + +namespace tql= triqs::clef; +int main() { + using std::cout; using std::endl; + TEST ( tql::eval ( cos(x_) ,x_=2) ); + TEST ( tql::eval ( cos(2*x_+1) ,x_=2) ); + TEST ( tql::eval ( abs(2*x_-1) ,x_=2) ); + TEST ( tql::eval ( abs(2*x_-1) ,x_=-2) ); + TEST ( tql::eval ( floor(2*x_-1) ,x_=2.3) ); + TEST ( tql::eval ( pow(2*x_+1,2) ,x_=2.0) ); + TEST ( tql::eval ( foo(2*x_+1) , x_ = 2) ); + TEST ( tql::eval ( foo(2*x_+1) , x_ = 2.0) ); + TEST ( tql::eval ( bar(2*x_+1,x_ -1) , x_ = 2) ); + TEST ( tql::eval ( inc(2*x_+1) , x_ = 2) ); +} + diff --git a/test/triqs/clef/math_functions.output b/test/triqs/clef/math_functions.output new file mode 100644 index 00000000..e6a0eb22 --- /dev/null +++ b/test/triqs/clef/math_functions.output @@ -0,0 +1,10 @@ +(tql::eval ( cos(x_) ,x_=2)) ---> -0.416147 +(tql::eval ( cos(2*x_+1) ,x_=2)) ---> 0.283662 +(tql::eval ( abs(2*x_-1) ,x_=2)) ---> 3 +(tql::eval ( abs(2*x_-1) ,x_=-2)) ---> 5 +(tql::eval ( floor(2*x_-1) ,x_=2.3)) ---> 3 +(tql::eval ( pow(2*x_+1,2) ,x_=2.0)) ---> 25 +(tql::eval ( foo(2*x_+1) , x_ = 2)) ---> 2 +(tql::eval ( foo(2*x_+1) , x_ = 2.0)) ---> 2.5 +(tql::eval ( bar(2*x_+1,x_ -1) , x_ = 2)) ---> 6 +(tql::eval ( inc(2*x_+1) , x_ = 2)) ---> 6 diff --git a/test/triqs/clef/test1.cpp b/test/triqs/clef/test1.cpp new file mode 100644 index 00000000..95c2eb17 --- /dev/null +++ b/test/triqs/clef/test1.cpp @@ -0,0 +1,106 @@ +#include +#include +using namespace triqs::clef; + +triqs::clef::placeholder <1> x_; +triqs::clef::placeholder <2> y_; +triqs::clef::placeholder <3> z_; +namespace tql= triqs::clef; + +struct F1{ + double v; + F1(double v_): v(v_){} + F1(F1 const &) = delete; // non copyable + double operator() (double x) const { return 10*x;} + + template< typename... Args> + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) const { return make_expr_call (std::ref(*this),args...);} + + template< typename... Args> + typename triqs::clef::result_of::make_expr_call,Args...>::type + operator()( Args&&... args ) { return make_expr_call (std::ref(*this),args...);} + + template friend void triqs_clef_auto_assign (F1 & x, Fnt f) { x.v++; std::cerr<< " called triqs_clef_auto_assign "<< f(100)< "<< (X) < +void test1( Expr expr) { + TEST(expr); + TEST(eval( expr, x_=5)); + TEST(eval( expr, y_=5, x_=9)); + TEST(eval( expr, x_=5, y_=9)); + std::cout<<"-------------"< +void test2( Expr const & expr) { + // std::cout << " type is " << triqs::utility::typeid_name(expr) << std::endl; + std::cout<< " ------ start test2 -----------------"<::value < (beta, Fermion, make_shape(1,1), 100); + triqs::clef::placeholder<0> om_; + G(om_) << 1./(om_ - 2.1); + + + //auto omega_mesh = make_mesh(); + //auto tail = ; + //auto G2 = make_gf(omega_mesh, make_shape(1,1), tail) ; + + + /* ---------- Fourier transform ---------------------*/ + auto Gt = make_gf (beta, Fermion, make_shape(1,1), Ntau, full_bins); + Gt() = lazy_inverse_fourier(G); + + TEST(Gt(0.0)); + + TEST(Gt.data()); + //TEST(Gt.mesh());//does not work: mesh has no << + TEST(Gt.mesh().index_to_point(0)); + TEST(Gt.mesh().index_to_point(1)); + + + /* -------- Read/write -----------------------------*/ + /* print_to_file("Gtau.dat", Gt); + H5::H5File hfile("store_G.h5",H5F_ACC_TRUNC); + h5_write(hfile, "G_tau", Gt); + auto Gt2 = make_gf (beta, Fermion, make_shape(1,1)); + h5_read(hfile, "G_tau", Gt2); + + H5::H5File file2("store_G2.h5",H5F_ACC_TRUNC); + h5_write(file2, "G_tau", Gt2); + + //TEST(Gt==Gt2);//does not work: no == operator +*/ + + /* ------------ other example ----------*/ + + //auto G = make_gf (beta, Fermion, make_shape(1,1)); + //triqs::clef::placeholder<0> om_; + //triqs::vec + //G(om_) << 1./(om_ - 2.1); + + + //auto Gt = make_gf (beta, Fermion, make_shape(2,2), n_tau, full_bins); + //auto Gt = make_gf (beta, Fermion, make_shape(2,2), n_max); +} + +void test_1(){ + + + double beta=10; + /* ----- Fourier ----- */ + size_t N1=1; + size_t N2=1; + size_t size_ = 5; + long order_min=-1; + triqs::gf::local::tail t(N1,N2, size_, order_min); + t(1)=1; + + auto Gt = make_gf (beta, Fermion, make_shape(1,1),100,full_bins, t); + auto Gw = make_gf (beta, Fermion, make_shape(1,1),100, t); + + Gt() = lazy_inverse_fourier(Gw); +} + +int main() { + + test_0(); + test_1(); + +} + + + + diff --git a/test/triqs/gf/vector_expr_temp.cpp b/test/triqs/gf/vector_expr_temp.cpp new file mode 100644 index 00000000..4caa05a3 --- /dev/null +++ b/test/triqs/gf/vector_expr_temp.cpp @@ -0,0 +1,20 @@ +#include +#include + +int main() { + + std::vector V1, V2; + + for(size_t i = 0; i<5; ++i) V1.push_back(i); + for(size_t i = 0; i<5; ++i) V2.push_back(2-i); + + for (size_t i =0; i<5; ++i) std::cout << (V1+ 2*V2)[i] << std::endl ; + + //auto V3 = make_vector(V1/2); + std::vector V3; +V3 = make_vector(V1 - V2/2.5); + + for (auto &x: V3) std::cout << x << std::endl ; + +} + diff --git a/test/triqs/gf/wrap_tech.cpp b/test/triqs/gf/wrap_tech.cpp new file mode 100644 index 00000000..3785e79c --- /dev/null +++ b/test/triqs/gf/wrap_tech.cpp @@ -0,0 +1,23 @@ +#include + +struct infty {}; + +template struct wrap { + T x; + wrap(T const & x_): x(x_) {} + operator infty() const { return infty();} + operator T () const { return x;} +}; + + +double g(infty) { return 3;} +double f(double) { return 30;} + +int main() { + + wrap w(2); + std::cout << w +1 < +#include +#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK + +using namespace triqs::utility; + +int main() { + + parameters P,P2; + parameter_defaults pdef; + + pdef.required + ( "A", int(), "really ?") + ; + + pdef.optional + ( "B", short(0), " short ") + ( "C", 1u, " unsigned short ") + ( "D", int(2), " int ") + ( "E", 3u, " unsigned int ") + ( "F", long(4), " long ") + ( "G", 5ll, " long ") + ( "H", float(6), " float ") + ( "I", double(7.8), " doube ") + // ( "K", std::complex(12), " double complex ") + ( "L", std::string("13"), " string ") + // ( "M", std::vector { 1,4 }, " vector ") + ( "N", double(15), "") + ( "W", int(16), "") + ; + + P["a"] = long(1); + P["d"] = 2.7; + P["s"] = std::string("-14.3"); + P["sc"] = "-14.3"; + + triqs::arrays::array A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2; + triqs::arrays::array B(3); B()=0;B(0) = 3; B(1) = -8; + P["A"] = std::move(A); + P["B"] = B; + + std::cout << P << std::endl; + std::cout << pdef<< 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 << P2 << std::endl; + +} + diff --git a/test/triqs/parameters/mpi_param.cpp b/test/triqs/parameters/mpi_param.cpp new file mode 100644 index 00000000..4f282e8b --- /dev/null +++ b/test/triqs/parameters/mpi_param.cpp @@ -0,0 +1,40 @@ +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +using namespace triqs::utility; + +int main(int argc, char* argv[]) { + boost::mpi::environment env(argc, argv); + boost::mpi::communicator world; + + parameters P; + + if (world.rank() == 0) { + P["a"] = long(1); + P["d"] = 2.7; + P["s"] = std::string("-14.3"); + } + + 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; +} + + + + + + + + diff --git a/test/triqs/parameters/param.cpp b/test/triqs/parameters/param.cpp new file mode 100644 index 00000000..582d925f --- /dev/null +++ b/test/triqs/parameters/param.cpp @@ -0,0 +1,169 @@ +#include +#include +#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK + +using namespace triqs; +using namespace triqs::utility; + using triqs::arrays::array; + +// what is the concept of things that can be put in the dict ? +struct my_obj { + int i; + my_obj(int i_) { i=i_;} + + my_obj() { i=0;} + my_obj(my_obj const & x) { i = x.i;} + my_obj(my_obj && x) { std::swap(i,x.i);} +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + my_obj & operator = (my_obj && x)= default; +#else + my_obj & operator = (my_obj && x) { i = x.i; return *this;} +#endif + + // h5 operation + friend std::string get_triqs_hdf5_data_scheme( my_obj const&) { return "myobject_is_nice";} + + friend void h5_write ( h5::group F, std::string const & subgroup_name, my_obj const & p){ + h5::group gr = F.create_group(subgroup_name); + gr.write_triqs_hdf5_data_scheme(p); + h5_write(gr,"data",p.i); + } + + friend void h5_read ( h5::group F, std::string const & subgroup_name, my_obj & p){ + auto gr = F.open_group(subgroup_name); + h5_read(gr,"data",p.i); + } + + // print + friend std::ostream & operator << (std::ostream & out, my_obj const & p) { return out<< "myobject("< + void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::make_nvp("i",i); } +}; + +// just to make the object printable +namespace std { + template + std::ostream & operator << (std::ostream & out, std::map const &) { return out << "map";} +} + +namespace std { + template + std::string get_triqs_hdf5_data_scheme (std::map const &) { + using triqs::get_triqs_hdf5_data_scheme;// for the basic types, not found by ADL + std::stringstream fs; + fs<<"map<"<"; + return fs.str(); + } +} + +int main() { + + try { + + parameters P; + + 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 mm; + mm["qwe"] = 123; + P["mm"] = mm; + std::cout << " map = "<< P["mm"]<< std::endl ; + std::cout << "123 = "<>(P["mm"])["qwe"]<< std::endl ; + + // raises an error as it should ... + //std::cout << utility::extract(P["d"]) << std::endl; + + triqs::arrays::array A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2; + triqs::arrays::array B(3); B()=0;B(0) = 3; B(1) = -8; + triqs::arrays::matrix U(2,2);U()=1.; + P["U"] = U; + triqs::arrays::vector 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 C; + C = extract(P["B"]); + std::cout << "C" << C << std::endl; + + array, 1> aa(3); + 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::cout << j << std::endl ; + std::cout << x << std::endl; + std::cout << y << std::endl ; + 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["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; + + { + H5::H5File file( "ess.h5", H5F_ACC_TRUNC ); + 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(s); + { + H5::H5File file( "ess3.h5", H5F_ACC_TRUNC ); + h5_write( file, "Parameters", P3); + } + + parameters P4; + parameters::register_type>(); + std::cout << "P4 before : "<< P4<< std::endl ; + { + H5::H5File file( "ess.h5", H5F_ACC_RDONLY ); + h5_read( file.openGroup("/"), "Parameters", P4); + } + { + H5::H5File file( "ess_relo.h5", H5F_ACC_TRUNC ); + h5_write( file.openGroup("/"), "Parameters", P4); + } + std::cout << "P4 after : "<< P4<< std::endl ; + + std::cout << "map retrieval "<>(P4["mm"])["qwe"]<< std::endl ; + + //std::cout << triqs::deserialize,1>>(utility::extract(P4["aa"])) << std::endl ; + } + catch(triqs::runtime_error const &e) { std::cout << "exception occurred "<< e.what()<< std::endl ;} + //catch(std::exception const &e) { std::cout << "exception occurred "<< e.what()<< std::endl ;} + + return 0; +} diff --git a/test/triqs/parameters/param2.cpp.no-built b/test/triqs/parameters/param2.cpp.no-built new file mode 100644 index 00000000..c27292e9 --- /dev/null +++ b/test/triqs/parameters/param2.cpp.no-built @@ -0,0 +1,131 @@ +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +using namespace triqs::utility; +namespace tqa=triqs::arrays; + + + +void somefunc(parameters P){//pass by value + std::cout << P["a"] << std::endl; +} + + +//useful to change _object to param or parameter +//and define the concept of a parameter +//this way we can explicitly define functions of +//parameters instead of native types + +void somefunc(param p){//pass a single parameter by value + std::cout << p << std::endl; +} + + + +int main(int argc, char* argv[]) { + mpi::environment env(argc, argv); + mpi::communicator world; + + parameters P; + + if (mpi.rank() == 0) { + + P ( "B", short(0), " short ") + ( "C", unsigned short(1), " unsigned short ") + ( "D", int(2), " int ") + ( "E", unsigned int(3), " unsigned int ") + ( "F", long(4), " long ") + ( "G", long long(5), " long ") + ( "H", float(6), " float ") + ( "I", double(7.8), " doube ") + ( "I", long double(9.10), " long double ") + ( "J", std::complex(11), " single complex ") + ( "K", std::complex(12), " double complex ") + ( "L", std::string("13"), " string ") + ( "M", std::vector x{ 1,4 }, " vector ") + ( "N", double(15)) + ( "W", int(16)) + ; + + P.set_default("U", std::string("U")) + ("V", std::string("V")); + + P.set_default("W", std::string("W")); //warning: parameter has been set and will shadow default value + + P.set_default("X", std::string("X")); + P.set_default("Y", std::string("Y")); + P.set_default("Z", std::string("Z"), " Z "); + + std::cout << P["U"] << std::endl; + + if(!P.is_default("X") throw TRIQS_RUNTIME_ERROR << "parameter " << P["X"] << " not a default parameter" << std::endl; + + P["Y"] = 0.815; //must remove default status + if(P.is_default("Y")) throw TRIQS_RUNTIME_ERROR << "parameter " << P["X"] << " is still a default parameter" << std::endl; + + }//rank=0 + + mpi::broadcast(world,P,0); + + if (world.rank() == 0) + std::cout << "rank 0" << std::endl << P << std::endl ; + + if (world.rank() == 1) + std::cout << "rank 1" << std::endl << P << std::endl ; + + if (world.rank() == 0) { + + somefunc(P); //check that copying works (pass by value) + + param p(4.0); //declare a single parameter + somefunc(p); //check that copying works (pass by value) + + param p2=P["A"]; //creation of a param from the type in P["A"] + + P["T"] = p2; //this should not register the type as param but as the type of P["A"] + if(type_hash_code(P["T"]) != type_hash_code(P["A"])) throw TRIQS_RUNTIME_ERROR << "types don't match" << std::endl; + + param p3 = p2; //no call of any cast operator + if(p2==p3) std::cout << "ok." << std::endl; + if(p2!=p3) throw TRIQS_RUNTIME_ERROR << "param value mismatch" << std::endl; + + parameters P2(P); + parameters P3; //new parameter list + P3=P; //deep copy + + if(P2==P) std::cout << "ok." << std::endl; + if(P2!=P) TRIQS_RUNTIME_ERROR << "parameter lists are not equal" << std::endl; + if(P3!=P) TRIQS_RUNTIME_ERROR << "parameter lists are not equal" << std::endl; + + P2["ABC"]=5.0; + if(P2==P) TRIQS_RUNTIME_ERROR << "parameter lists shouldn't be equal" << std::endl; + + tqa::array A(2,2); + P2["ArrayA"] = A; + P2["ArrayB"] = tqa::array B(3,3); + P2["ArrayC"] = P2["ArrayA"] + P2["ArrayB"]; + + } // rank==0 + + return 0; +} + + + + + + + + diff --git a/test/triqs/parameters/param_array.cpp b/test/triqs/parameters/param_array.cpp new file mode 100644 index 00000000..e6a1f8d7 --- /dev/null +++ b/test/triqs/parameters/param_array.cpp @@ -0,0 +1,46 @@ +#include +#include +#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 A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2; + triqs::arrays::array B(3); B()=0;B(0) = 3; B(1) = -8; + triqs::arrays::matrix U(2,2);U()=1.; + P["U"] = U; + triqs::arrays::vector 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 C; + C = extract(P["B"]); + std::cout << "C" << C << std::endl; + + // testing that I can extract a view and modify it. + triqs::arrays::array_view VC = extract>(P["B"]); + std::cout << "VC" << VC << std::endl; + VC(0) *=2; + + C = extract(P["B"]); + std::cout << "C" << C << std::endl; + + { + H5::H5File file( "ess.h5", H5F_ACC_TRUNC ); + h5_write( file, "Parameters", P); + } + + return 0; +} diff --git a/test/triqs/parameters/param_array.output b/test/triqs/parameters/param_array.output new file mode 100644 index 00000000..3b724bb4 --- /dev/null +++ b/test/triqs/parameters/param_array.output @@ -0,0 +1,7 @@ +A +[[1.3,0] + [0,-8.2]] +B[3,-8,0] +C[3,-8,0] +VC[3,-8,0] +C[6,-8,0] diff --git a/test/triqs/parameters/simple_p.cpp b/test/triqs/parameters/simple_p.cpp new file mode 100644 index 00000000..32c580b4 --- /dev/null +++ b/test/triqs/parameters/simple_p.cpp @@ -0,0 +1,27 @@ +#include +#include +#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK + +using namespace triqs::utility; + + +int main() { + + parameters P; + + P["a"] = long(1); + P["d"] = 2.7; + P["s"] = std::string("-14.3"); + + long j = P["a"]; + double x = P["d"]; + double y = P["a"]; + double z = P["s"]; + + std::cout << j << std::endl ; + std::cout << x << std::endl; + std::cout << y << std::endl ; + std::cout << z << std::endl ; + + return 0; +} diff --git a/test/triqs/utility/CMakeLists.txt b/test/triqs/utility/CMakeLists.txt new file mode 100644 index 00000000..917a5baf --- /dev/null +++ b/test/triqs/utility/CMakeLists.txt @@ -0,0 +1,2 @@ +all_tests() + diff --git a/test/triqs/utility/crash_logger.cpp b/test/triqs/utility/crash_logger.cpp new file mode 100644 index 00000000..c60ec56e --- /dev/null +++ b/test/triqs/utility/crash_logger.cpp @@ -0,0 +1,64 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#include +#include +#include +using namespace triqs; + +class A { + int i; + public : + A() : i(8) {} + friend void h5_write (h5::group g, std::string const & name, A const & a) { + auto gr = g.create_group(name); + //throw " hi hi hi"; + h5_write(gr,"i", a.i); + } + void make_exp() { throw std::runtime_error("hi hi hi ");} +}; + +void f() { + + int i =3; + double d =-2.3; + A a; + + auto log = triqs::utility::crash_logger ("rr.h5"); + log(a,"a")(i,"i")(d,"d"); + + //try { + throw std::runtime_error(std::string("an exception occurs")); + // } + //catch(...) { } + + //a.make_exp(); + + log.dismiss(); +} + +int main(int argc, char **argv) { + + try { + f(); + } + catch(std::exception const & e) { std::cerr << e.what() << std::endl ;} + +} diff --git a/test/triqs/utility/function_arg_ret_type.cpp b/test/triqs/utility/function_arg_ret_type.cpp new file mode 100644 index 00000000..adb4aa36 --- /dev/null +++ b/test/triqs/utility/function_arg_ret_type.cpp @@ -0,0 +1,42 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#include +#include +#include +using namespace triqs; + +template struct F { T operator()(T const &x) { return 2*x;} }; + +int main(int argc, char **argv) { + + auto lambda = [](int const & i) { return double(i*10); }; + + typedef utility::function_arg_ret_type traits; + + static_assert(std::is_same::value, "err"); + static_assert(std::is_same::type>::value, "err"); + static_assert(std::is_same::type>::value, "err"); + + typedef utility::function_arg_ret_type> traits2; + static_assert(std::is_same::type>::value, "err"); + + return 0; +} diff --git a/test/triqs/utility/iterator_dressing.cpp b/test/triqs/utility/iterator_dressing.cpp new file mode 100644 index 00000000..93a3cce0 --- /dev/null +++ b/test/triqs/utility/iterator_dressing.cpp @@ -0,0 +1,74 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#include +#include +#include +using namespace triqs::utility; + +struct S { + + typedef std::map m_t; + typedef m_t::const_iterator mcit_t; + typedef m_t::iterator mit_t; + m_t m; + + struct _cdress {double const & tau; int const & a; _cdress( mcit_t const & it): tau(it->first), a(it->second){} }; + struct _dress {double const & tau; int & a; _dress ( mit_t const & it) : tau(it->first), a(it->second){} }; + + // const iterator + struct const_iterator : public dressed_iterator< mcit_t,_cdress> { + const_iterator (mcit_t it): dressed_iterator(it) {} + }; + const_iterator begin() const { return m.begin();} + const_iterator end() const { return m.end();} + + //iterator + struct iterator : public dressed_iterator< mit_t,_dress> { + iterator (mit_t it = mit_t()): dressed_iterator(it) {} + }; + iterator begin() { return m.begin();} + iterator end() { return m.end();} + +}; + + +int main() { + + S s; + s.m.insert(std::make_pair(8.4,2)); + s.m.insert(std::make_pair(1.3,1)); + + for (auto const & p : s) std::cout << p.tau << " -- "<< p.a << std::endl; + //for (auto const & p : s.m) std::cout << p.first << " -- "<< p.second << std::endl; + + auto it = s.begin(); + std::cout << it->tau << std::endl ; + ++it; + std::cout << it->tau << std::endl ; + --it; + std::cout << it->tau << std::endl ; + + it-> a *=10; + + for (auto const & p : s) + std::cout << p.tau << " -- "<< p.a << std::endl; + +} diff --git a/test/triqs/utility/iterator_dressing.output b/test/triqs/utility/iterator_dressing.output new file mode 100644 index 00000000..ecc6b83d --- /dev/null +++ b/test/triqs/utility/iterator_dressing.output @@ -0,0 +1,7 @@ +1.3 -- 1 +8.4 -- 2 +1.3 +8.4 +1.3 +1.3 -- 10 +8.4 -- 2 diff --git a/test/triqs/utility/iterator_dressing3.cpp b/test/triqs/utility/iterator_dressing3.cpp new file mode 100644 index 00000000..c9930c98 --- /dev/null +++ b/test/triqs/utility/iterator_dressing3.cpp @@ -0,0 +1,69 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#include +#include +#include +using namespace triqs::utility; + +struct S { + + typedef std::map m_t; + typedef m_t::const_iterator mcit_t; + typedef m_t::iterator mit_t; + m_t m; + + struct _cdress {double const & tau; int const & a; m_t const * m; _cdress( mcit_t const & it, m_t const * mm): tau(it->first), a(it->second),m(mm){} }; + + // const iterator with cyclic condition + struct const_iterator : public dressed_iterator< mcit_t,_cdress, m_t const> { + const_iterator (mcit_t it, m_t const * m): dressed_iterator(it,m) {} + friend const_iterator next_cyclic(const_iterator it) { + ++it; + if (it.get() == it.get_aux()->end()) return const_iterator(it.get_aux()->begin(),it.get_aux()); + else return it; + } + }; + const_iterator begin() const { return const_iterator(m.begin(),&m);} + const_iterator end() const { return const_iterator(m.end(),&m);} + +}; + + + +int main() { + + S s; + s.m.insert(std::make_pair(8.4,2)); + s.m.insert(std::make_pair(1.3,1)); + + for (auto const & p : s) std::cout << p.tau << " -- "<< p.a << std::endl; + //for (auto const & p : s.m) std::cout << p.first << " -- "<< p.second << std::endl; + + auto it = s.begin(); + std::cout << it->tau << std::endl ; + ++it; + std::cout << it->tau << std::endl ; + it = next_cyclic(it); + std::cout << it->tau << std::endl ; + + +} diff --git a/test/triqs/utility/iterator_dressing3.output b/test/triqs/utility/iterator_dressing3.output new file mode 100644 index 00000000..04d73689 --- /dev/null +++ b/test/triqs/utility/iterator_dressing3.output @@ -0,0 +1,5 @@ +1.3 -- 1 +8.4 -- 2 +1.3 +8.4 +1.3 diff --git a/test/triqs/utility/iterator_dressing_2.cpp b/test/triqs/utility/iterator_dressing_2.cpp new file mode 100644 index 00000000..325e92c5 --- /dev/null +++ b/test/triqs/utility/iterator_dressing_2.cpp @@ -0,0 +1,91 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#include +#include +#include +using namespace triqs::utility; + +struct data{ +int a; +mutable int b; +}; + +struct S { + + typedef std::map m_t; + typedef m_t::const_iterator mcit_t; + typedef m_t::iterator mit_t; + m_t m; + + struct _cdress {double const & tau; int const & a; int & b ; _cdress( mcit_t const & it): tau(it->first), a(it->second.a), b(it->second.b){} }; + struct _dress {double const & tau; int & a; int & b; _dress ( mit_t const & it) : tau(it->first), a(it->second.a), b(it->second.b){} }; + + // const iterator + struct const_iterator : public dressed_iterator< mcit_t,_cdress> { + const_iterator (mcit_t it = mcit_t()): dressed_iterator(it) {} + }; + const_iterator begin() const { return m.begin();} + const_iterator end() const { return m.end();} + + //iterator + struct iterator : public dressed_iterator< mit_t,_dress> { + iterator (mit_t it = mit_t()): dressed_iterator(it) {} + }; + iterator begin() { return m.begin();} + iterator end() { return m.end();} + +}; + + +int main() { + + S s; + s.m.insert(std::make_pair(8.4,data{1,2})); + s.m.insert(std::make_pair(1.3,data{3,4})); + + for (auto const & p : s) std::cout << p.tau << " -- "<< p.a << std::endl; + //for (auto const & p : s.m) std::cout << p.first << " -- "<< p.second << std::endl; + + auto it = s.begin(); + std::cout << it->tau << std::endl ; + ++it; + std::cout << it->tau << std::endl ; + --it; + std::cout << it->tau << std::endl ; + + it-> a *=10; + + S const & s2(s); + + for (auto const & p : s2) + std::cout << p.tau << " "<< p.a << " " << p.b << std::endl; + + auto it2 = s2.begin(); + std::cout << it2->tau << std::endl ; + it2->b *= -1; + //it2->a *= -1; + + for (auto const & p : s2) + std::cout << p.tau << " "<< p.a << " " << p.b << std::endl; + + +} diff --git a/test/triqs/utility/qmc_time_t_test.cpp b/test/triqs/utility/qmc_time_t_test.cpp new file mode 100644 index 00000000..61390712 --- /dev/null +++ b/test/triqs/utility/qmc_time_t_test.cpp @@ -0,0 +1,58 @@ +#include + +#include + +using triqs::utility::time_pt; + +void print_me (double x) { std::cout << " print " << x<< std::endl ;} + +int main(int argc, char **argv) +{ + time_pt zero (40); + time_pt beta = time_pt::make_beta(40); + + auto t1 = time_pt::make_from_double(10,40), t2 = time_pt::make_from_double(30,40); + + std::cout << "zero: " << zero << std::endl; + std::cout << "beta: " << beta << std::endl; + std::cout << "t1: " << t1 << "" << std::endl; + std::cout << "t2: " << t2 << "" << std::endl; + + std::cout << "t1 + t2: " << t1+t2 << "" << std::endl; + std::cout << "t1 + t2 - (as double) : " << t1+t2 - (double(t1) + double(t2)) << "" << std::endl; + + std::cout << "t1 - t2: " << t1-t2 << "" << std::endl; + std::cout << "t1 - t2 - (as double) : " << t1-t2 - (double(t1) - double(t2)) << "" << std::endl; + + std::cout << "t1 * t2: " << t1*t2 << "" << std::endl; + std::cout << "t1 * t2 - (as double) : " << t1*t2 - (double(t1) * double(t2)) << "" << std::endl; + + std::cout << "t1 / t2: " << t1/t2 << "" << std::endl; + std::cout << "t1 / t2 - (as double) : " << t1/t2 - (double(t1) / double(t2)) << "" << std::endl; + + std::cout << "t1 + beta: " << t1 + beta << "" << std::endl; + std::cout << "t1 - beta: " << t1 - beta << "" << std::endl; + + print_me(double(t1));// to check explicit cast + + std::cout << " -t1: " << - t1 << "" << std::endl; + + std::cout << "epsilon: " << time_pt::epsilon(beta) << "" << std::endl; + std::cout << "- epsilon: " << - time_pt::epsilon(beta) << "" << std::endl; + std::cout << "t1 - epsilon :" << t1- time_pt::epsilon(beta) << "" << std::endl; + + std::cout << " num limit max " << std::numeric_limits::max() <::max()-2; + n++; + std::cout << " num limit-1 " << n <. + * + ******************************************************************************/ +#include +#include +#include +#include +#include + +struct fun { + double operator()(int i, double x, double y, int k) { return 6*k + i - 1.3*x + 2*y;} +}; + +struct fun2 { + double operator()(double x, double y) { return x+y;} +}; + +struct print_t { + template + void operator()(T x) { std::cerr << x << " "; } + std::string s; +}; + +struct A { +template + std::string str(T1 const & x, T2 const &y) const { std::stringstream fs; fs << "the string is "<< x<<" " << y; return fs.str();} +}; + +std::string my_print_str(int x, int y) { std::stringstream fs; fs << "the string is "<< x<< " " << y; return fs.str();} + + +int main(int argc, char **argv) { + + auto t = std::make_tuple(1,2.3,4.3,8); + auto t2 = std::make_tuple(1,2,3,4); + auto t1 = std::make_tuple(1,2.3,4.3,8); + + { + triqs::tuple::for_each(t, print_t()); + std::cerr << std::endl; + } + + { + auto res = triqs::tuple::apply(fun(),t); + std::cerr << " f(t) =" << res << std::endl ; + if ( std::abs((res - fun()(1,2.3,4.3,8))) > 1.e-13) throw std::runtime_error(" "); + } + + { + auto r = triqs::tuple::apply_on_zip(fun2(),t1,t2); + std::cerr << " [f(a,b) for (a,b) in zip(t1,t2)] =" + << std::get<0>(r) << " " + << std::get<1>(r) << " " + << std::get<2>(r) << " " + << std::get<3>(r) << std::endl; + } + + { + auto res = triqs::tuple::fold([](double x,double r) { return x+r;}, t, 0); + std::cerr << " " << res << std::endl ; + if ( std::abs((res - 15.6)) > 1.e-13) throw std::runtime_error(" "); + } + + { + auto res = triqs::tuple::fold_on_zip([](double x, double y, double r) { return x+ 2*y +r;}, t1,t2, 0); + std::cerr << " " << res << std::endl ; + if ( std::abs((res - 35.6)) > 1.e-13) throw std::runtime_error(" "); + } + + { + auto res = triqs::tuple::apply(my_print_str, std::make_tuple(1,2)); + std::cerr << " " << res << std::endl ; + } + + { + using namespace std::placeholders; + A a; + auto res = triqs::tuple::apply(std::bind(&A::str,a,_1,_2), std::make_tuple(1,2)); + res = triqs::tuple::apply(std::mem_fn(&A::str), std::make_tuple(a,1,2)); + std::cerr << " " << res << std::endl ; + } + +} + diff --git a/test/triqs/utility/view_tools.cpp b/test/triqs/utility/view_tools.cpp new file mode 100644 index 00000000..0e7d1578 --- /dev/null +++ b/test/triqs/utility/view_tools.cpp @@ -0,0 +1,48 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#include +#include +#include +#include +using namespace triqs; +using namespace triqs::arrays; +using namespace triqs::utility; + +template struct check { + static_assert(std::is_same::type >::value, "err"); + static_assert(std::is_same::type >::value, "err"); +}; + +int main(int argc, char **argv) { + + static_assert(has_view< array > ::value, " err"); + static_assert(has_view< array_view > ::value, " err"); + static_assert(has_view< matrix > ::value, " err"); + static_assert(!has_view< double > ::value, " err"); + + check> (); + check>(); + check>(); + check>(); + + return 0; +} + diff --git a/triqs/CMakeLists.txt b/triqs/CMakeLists.txt new file mode 100644 index 00000000..b5dc6277 --- /dev/null +++ b/triqs/CMakeLists.txt @@ -0,0 +1,37 @@ +# Add C11 flag +# leave it here because boost has to be compiled without the flags because of boost python ?? +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + +# all .cpp files to get the dependencies +FILE(GLOB_RECURSE ALLSOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) +FOREACH(CPP ${ALLSOURCES}) + set_property (GLOBAL APPEND PROPERTY TRIQS_LIB_CPP_SOURCES_LIST "${CMAKE_CURRENT_SOURCE_DIR}/${CPP}") +ENDFOREACH(CPP ${ALLSOURCES}) +get_property(ALLSOURCES GLOBAL PROPERTY TRIQS_LIB_CPP_SOURCES_LIST) + +# compile every subdirectory +add_all_subdirectories_with_cmakelist() + +# The lib will be build from the sources +IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +SET( LINK_RT "") +else() +SET( LINK_RT "-lrt") +endif() +add_library(triqs ${ALLSOURCES}) +target_link_libraries (triqs ${LINK_RT} ${TRIQS_LINK_LIBS} ) + +# Install library +install(TARGETS triqs DESTINATION lib) + +# all .hpp files... +FILE(GLOB_RECURSE ALLHEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.hpp) + +# Install headers in good include dir +FOREACH(HEADER ${ALLHEADERS}) + get_filename_component(P ${HEADER} PATH) + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/${HEADER}" DESTINATION "include/triqs/${P}") + #MESSAGE(STATUS "I will install ${HEADER} of ${P}") +ENDFOREACH(HEADER ${ALLHEADERS}) + + diff --git a/triqs/arrays.hpp b/triqs/arrays.hpp new file mode 100644 index 00000000..fcf27b4e --- /dev/null +++ b/triqs/arrays.hpp @@ -0,0 +1,41 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_ALL_H +#define TRIQS_ARRAYS_ALL_H + +// The basic classes +#include +#include +#include + +// +//#include +#include + +// HDF5 interface +#include + +// Linear algebra ?? Keep here ? +//#include +//#include + +#endif + diff --git a/triqs/arrays/CMakeLists.txt b/triqs/arrays/CMakeLists.txt new file mode 100644 index 00000000..d16dbb56 --- /dev/null +++ b/triqs/arrays/CMakeLists.txt @@ -0,0 +1,2 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../) + diff --git a/triqs/arrays/algorithms.hpp b/triqs/arrays/algorithms.hpp new file mode 100644 index 00000000..4ffa84d6 --- /dev/null +++ b/triqs/arrays/algorithms.hpp @@ -0,0 +1,73 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_ALGORITHMS_H +#define TRIQS_ARRAYS_ALGORITHMS_H +#include +#include +#include +#include "./functional/fold.hpp" +#include + +#define TRIQS_FIX_CLANG30_linux + +namespace triqs { namespace arrays { + + // get_first_element(a) returns .. the first element, i.e. a(0,0,0...) +#define ZERO(z, n, text) 0 +#define IMPL(z, N, unused)\ + template typename std::enable_if::type get_first_element(ArrayType const & A) \ + { return A(BOOST_PP_ENUM(N,ZERO,0));} + BOOST_PP_REPEAT_FROM_TO(1,ARRAY_NRANK_MAX , IMPL, nil); +#undef IMPL +#undef ZERO + + template + typename A::value_type max_element(A const &a) { +#ifdef TRIQS_FIX_CLANG30_linux + typedef typename A::value_type const & T; + return fold ( static_cast(std::max)) ( a, get_first_element(a)); //a[typename A::domain_type::index_value_type()]); +#else + return fold ( std::max) ( a, get_first_element(a)); //a[typename A::domain_type::index_value_type()]); +#endif + } + + template + typename A::value_type min_element(A const &a) { +#ifdef TRIQS_FIX_CLANG30_linux + typedef typename A::value_type const & T; + return fold ( static_cast(std::min)) ( a, get_first_element(a)); //a[typename A::domain_type::index_value_type()]); +#else + return fold ( std::min) ( a, get_first_element(a)); //a[typename A::domain_type::index_value_type()]); +#endif + } + + template + typename A::value_type sum(A const & a) { return fold ( std::plus()) (a); } + + template + typename A::value_type prod(A const & a) { return fold ( std::multiplies()) (a,1); } + + +}}//namespace triqs::arrays + +#endif + + diff --git a/triqs/arrays/array.hpp b/triqs/arrays/array.hpp new file mode 100644 index 00000000..c14b8339 --- /dev/null +++ b/triqs/arrays/array.hpp @@ -0,0 +1,207 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_ARRAY_H +#define TRIQS_ARRAYS_ARRAY_H +#include +#include "indexmaps/cuboid/map.hpp" +#include "indexmaps/cuboid/slice.hpp" +#include "impl/indexmap_storage_pair.hpp" +#include "impl/assignment.hpp" +#include "impl/flags.hpp" +namespace triqs { namespace arrays { + + template class array_view; + template class array; + + // ---------------------- array_view -------------------------------- + +#define IMPL_TYPE indexmap_storage_pair< indexmaps::cuboid::map, \ + storages::shared_block, Opt, TraversalOrder, Tag::array_view > + + template + class array_view : Tag::array_view, TRIQS_MODEL_CONCEPT(MutableCuboidArray), public IMPL_TYPE { + static_assert( Rank>0, " Rank must be >0"); + public: + typedef typename IMPL_TYPE::indexmap_type indexmap_type; + typedef typename IMPL_TYPE::storage_type storage_type; + typedef array_view view_type; + typedef array non_view_type; + typedef void has_view_type_tag; + + /// Build from an IndexMap and a storage + template array_view (indexmap_type const & Ind,S const & Mem): IMPL_TYPE(Ind, Mem) {} + + /// Copy constructor + array_view(array_view const & X): IMPL_TYPE(X.indexmap(),X.storage()) {} + + /// Build from anything that has an indexmap and a storage compatible with this class + template array_view(const ISP & X): IMPL_TYPE(X.indexmap(),X.storage()) {} + +#ifdef TRIQS_WITH_PYTHON_SUPPORT + /// Build from a numpy.array (X is a borrowed reference) : throws if X is not a numpy.array + explicit array_view (PyObject * X): IMPL_TYPE(X, false, "array_view "){} +#endif + + array_view () = delete; + + // Move + array_view(array_view && X) { this->swap_me(X); } + + /// Swap + friend void swap( array_view & A, array_view & B) { A.swap_me(B);} + + /// Rebind the view + void rebind (array_view const & X) { this->indexmap_ = X.indexmap_; this->storage_ = X.storage_;} + + /// Assignment. The size of the array MUST match exactly, except in the empty case + template array_view & operator=(RHS const & X) { triqs_arrays_assign_delegation(*this,X); return *this; } + + /// + array_view & operator=(array_view const & X) { triqs_arrays_assign_delegation(*this,X); return *this; } //without this, the standard = is synthetized... + + // Move assignment not defined : will use the copy = since view must copy data + + TRIQS_DEFINE_COMPOUND_OPERATORS(array_view); + }; + + //------------------------------- array --------------------------------------------------- + + template + class array: Tag::array, TRIQS_MODEL_CONCEPT(MutableCuboidArray), public IMPL_TYPE { + public: + typedef typename IMPL_TYPE::value_type value_type; + typedef typename IMPL_TYPE::storage_type storage_type; + typedef typename IMPL_TYPE::indexmap_type indexmap_type; + typedef array_view view_type; + typedef array non_view_type; + typedef void has_view_type_tag; + + /// Empty array. + explicit array(memory_layout ml = memory_layout(IMPL_TYPE::indexmap_type::traversal_order)) :IMPL_TYPE(ml){} + + /// From a domain + explicit array( typename indexmap_type::domain_type const & dom, memory_layout ml = memory_layout(IMPL_TYPE::indexmap_type::traversal_order)): + IMPL_TYPE(indexmap_type(dom,ml)){} + +#ifdef TRIQS_DOXYGEN + /// Construction from the dimensions. NB : the number of parameters must be exactly rank (checked at compile time). + array (size_t I_1, .... , size_t I_rank); +#else +#define IMPL(z, NN, unused) \ + explicit array (BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), size_t I_),memory_layout ml = memory_layout(IMPL_TYPE::indexmap_type::traversal_order)): \ + IMPL_TYPE(indexmap_type(mini_vector(BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), I_)),ml)) {\ + static_assert(IMPL_TYPE::rank-1==NN,"array : incorrect number of variables in constructor");} + BOOST_PP_REPEAT(ARRAY_NRANK_MAX , IMPL, nil) +#undef IMPL +#endif + + // Makes a true (deep) copy of the data. + array(const array & X): IMPL_TYPE(X.indexmap(),X.storage().clone()) {} + + // Move + explicit array(array && X) { this->swap_me(X); } + + /** + * Build a new array from X.domain() and fill it with by evaluating X. X can be : + * - another type of array, array_view, matrix,.... (any pair) + * - a expression : e.g. array A = B+ 2*C; + */ + template + array(const T & X, TYPE_ENABLE_IF(memory_layout, ImmutableArray) ml = memory_layout(IMPL_TYPE::indexmap_type::traversal_order)): + IMPL_TYPE(indexmap_type(X.domain(),ml)) { triqs_arrays_assign_delegation(*this,X); } + +#ifdef TRIQS_WITH_PYTHON_SUPPORT + ///Build from a numpy.array X (or any object from which numpy can make a numpy.array). Makes a copy. + explicit array (PyObject * X): IMPL_TYPE(X, true, "array "){} +#endif + + // build from a init_list + template + array(std::initializer_list const & l, typename std::enable_if::type * dummy =0): + IMPL_TYPE(indexmap_type(mini_vector(l.size()),memory_layout(IMPL_TYPE::indexmap_type::traversal_order))) { + size_t i=0; + for (auto const & x : l) (*this)(i++) = x; + } + + template + array (std::initializer_list> const & l, typename std::enable_if::type * dummy =0): + IMPL_TYPE(memory_layout(IMPL_TYPE::indexmap_type::traversal_order)) { + size_t i=0,j=0; int s=-1; + for (auto const & l1 : l) { if (s==-1) s= l1.size(); else if (s != l1.size()) TRIQS_RUNTIME_ERROR << "initializer list not rectangular !";} + IMPL_TYPE::resize(typename IMPL_TYPE::domain_type (mini_vector(l.size(),s))); + for (auto const & l1 : l) { + for (auto const & x : l1) { (*this)(i,j++) = x;} + j=0; ++i; + } + } + + /** + * Resizes the array. NB : all references to the storage is invalidated. + * Does not initialize the array by default: to resize and init, do resize(IND).init() + */ + array & resize (const indexmaps::cuboid::domain_t & l) { IMPL_TYPE::resize(l); return *this; } + + /// Assignement resizes the array. All references to the storage are therefore invalidated. + array & operator=(const array & X) { IMPL_TYPE::resize_and_clone_data(X); return *this; } + + /// Move assignment + array & operator=(array && X) { this->swap_me(X); return *this;} + + /// Swap + friend void swap( array & A, array & B) { A.swap_me(B);} + + /** + * Assignement resizes the array (if necessary). + * All references to the storage are therefore invalidated. + * NB : to avoid that, do make_view(A) = X instead of A = X + */ + template + array & operator=(const RHS & X) { + static_assert(ImmutableArray::value, "Assignment : RHS not supported"); + IMPL_TYPE::resize(X.domain()); + triqs_arrays_assign_delegation(*this,X); + return *this; + } + + TRIQS_DEFINE_COMPOUND_OPERATORS(array); + + };//array class + +#undef IMPL_TYPE + + //---------------------------------------------------------------------------------- + + // how to build the view type .... + template < class V, int R, ull_t Opt, ull_t TraversalOrder > struct ViewFactory< V, R, Opt, TraversalOrder,Tag::array_view > { typedef array_view type; }; + +}}//namespace triqs::arrays + +// The std::swap is WRONG for a view because of the copy/move semantics of view. +// Use swap instead (the correct one, found by ADL). +namespace std { + template + void swap( triqs::arrays::array_view & a , triqs::arrays::array_view & b)= delete; +} + +#include "./expression_template/array_algebra.hpp" + +#endif + diff --git a/triqs/arrays/asserts.hpp b/triqs/arrays/asserts.hpp new file mode 100644 index 00000000..32766494 --- /dev/null +++ b/triqs/arrays/asserts.hpp @@ -0,0 +1,63 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_ASSERTS_H +#define TRIQS_ARRAYS_ASSERTS_H +#include "./functional/map.hpp" +#include "./algorithms.hpp" + +namespace triqs { namespace arrays { + + template inline double assert_abs(T z) { return std::abs(z);} + + template + void assert_all_close( ArrayType1 const & A, ArrayType2 const & B, double precision, bool relative = false) { + typedef typename ArrayType1::value_type F; + auto Abs = map( boost::function (assert_abs) ); + auto r = max_element (Abs(A-B)); + auto r2 = max_element (Abs(A) + Abs(B)); + if ( r > (relative ? precision * r2 : precision) ) + TRIQS_RUNTIME_ERROR<<"assert_all_close error : \n\n"<<".. A = "< 1.e-13) TRIQS_RUNTIME_ERROR << "Test assert_equal : failed"; + } + void assert_close(std::complex x1, std::complex x2 ) { + if (std::abs(x1-x2) > 1.e-13) TRIQS_RUNTIME_ERROR << "Test assert_equal : failed"; + } + + // Put here a macro, to print the expression, the line, etc... + void assert_is_true( bool b) { + if (!b) TRIQS_RUNTIME_ERROR << "Test assert_is_true : failed"; + } + + void assert_is_false( bool b) { + if (b) TRIQS_RUNTIME_ERROR << "Test assert_is_false : failed"; + } + +}} +#endif + diff --git a/triqs/arrays/blas_lapack/axpy.hpp b/triqs/arrays/blas_lapack/axpy.hpp new file mode 100644 index 00000000..886b4cc1 --- /dev/null +++ b/triqs/arrays/blas_lapack/axpy.hpp @@ -0,0 +1,60 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_LAPACK_AXPY_H +#define TRIQS_ARRAYS_BLAS_LAPACK_AXPY_H +#include "./tools.hpp" +//#include "./qcache.hpp" + +namespace triqs { namespace arrays { namespace blas { + + namespace f77 { // overload + + extern "C" { + void TRIQS_FORTRAN_MANGLING(daxpy)(const int & N, const double & alpha, const double * x, const int& incx, double * y, const int& incy); + void TRIQS_FORTRAN_MANGLING(zaxpy)(const int & N, const std::complex & alpha, const std::complex * x, const int& incx, std::complex * y, const int& incy); + } + + inline void axpy (const int & N, const double & alpha, const double* x, const int & incx, double* Y, const int & incy) { + TRIQS_FORTRAN_MANGLING(daxpy)(N, alpha, x, incx, Y, incy); + } + inline void axpy (const int & N, const std::complex & alpha, const std::complex* x, const int & incx, std::complex* Y, const int & incy) { + TRIQS_FORTRAN_MANGLING(zaxpy)(N, alpha, x, incx, Y, incy); + } + } + + /** + * Blas 1: copy + */ + template< typename VTX, typename VTY> + typename std::enable_if< is_blas_lapack_type::value && have_same_value_type< VTX, VTY>::value >::type + axpy (typename VTX::value_type const & alpha ,VTX const & X, VTY & Y) { + static_assert( is_amv_value_or_view_class::value, "blas1 bindings only take vector and vector_view"); + static_assert( is_amv_value_or_view_class::value, "blas1 bindings only take vector and vector_view"); + //if (( X.size() != Y.size()) ) Y.resize(X.size()); + //const_qcache Cx(X); // mettre la condition a la main + //f77::copy(X.size(), Cx().data_start(), Cx().stride(), Y.data_start(), Y.stride()); + f77::axpy(X.size(), alpha, X.data_start(), X.stride(), Y.data_start(), Y.stride()); + } + +}}}// namespace + +#endif + diff --git a/triqs/arrays/blas_lapack/blas_headers.hpp b/triqs/arrays/blas_lapack/blas_headers.hpp new file mode 100644 index 00000000..b81c6c1d --- /dev/null +++ b/triqs/arrays/blas_lapack/blas_headers.hpp @@ -0,0 +1,160 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by M. Ferrero, 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_HEADER_H +#define TRIQS_ARRAYS_BLAS_HEADER_H + +// UNUNSED : just here to keep the old bindings + +/* + +// Declaration of the lapack routines. +extern "C" +{ + void TRIQS_FORTRAN_MANGLING(dgetrf) (int &,int &,double[], int & ,int [],int &); + void TRIQS_FORTRAN_MANGLING(dgetri) (int & , double [], int & ,int [],double [],int & ,int & ); + void TRIQS_FORTRAN_MANGLING(dgetrs) (char *,int & , int & , double [], int & ,int [],double [],int & ,int & ); + + void TRIQS_FORTRAN_MANGLING(zgetrf) (int &,int &,std::complex[], int & ,int [],int &); + void TRIQS_FORTRAN_MANGLING(zgetri) (int & , std::complex [], int & ,int [],std::complex [],int & ,int & ); + void TRIQS_FORTRAN_MANGLING(zgetrs) (char *,int & , int & , std::complex [], int & ,int [],std::complex [],int & ,int & ); + // C <- alpha AB + beta C + void TRIQS_FORTRAN_MANGLING(dgemm) (char *, char *, //TRANSA, TRANSB + int & , // + int & , // + int & , // + double &, //ALPHA, + const double[], // A, + int &, // LDA + const double[], // B + int &, // LDB, + double &, // BETA, + double[], // C + int & // LDC + ); + + void TRIQS_FORTRAN_MANGLING(zgemm) (char *, char *, //TRANSA, TRANSB + int & , // + int & , // + int & , // + std::complex &, //ALPHA, + const std::complex[], // A, + int &, // LDA + const std::complex[], // B + int &, // LDB, + std::complex &, // BETA, + std::complex[], // C + int & // LDC + ); + + void TRIQS_FORTRAN_MANGLING(dgemv)(const char* trans, const int & m, const int & n, const double & alpha, const double A[], int & lda, + const double x[], const int & incx, const double & beta, double y[], const int & incy); + + void TRIQS_FORTRAN_MANGLING(zgemv)(const char* trans, const int & m, const int & n, const std::complex & alpha, const std::complex A[], int & lda, + const std::complex x[], const int & incx, const std::complex & beta, std::complex y[], const int & incy); + + void TRIQS_FORTRAN_MANGLING(zhseqr)( char *,char*, //JOB, COMPZ + int &, // N + int &, //ILO + int &,// IHI + std::complex[], // H + int &, // LDH + std::complex[], //W + std::complex[], //Z + int &, // LDZ + std::complex[], //WORK + int &, // LWORK + int & // INFO + ); + + void TRIQS_FORTRAN_MANGLING(dsyev)(char*,char*, // JOBZ and UPLO + int &, // Matrix Size + double[], // matrix + int&, // LDA of the matrix + double[], // Eigenvalues array + double[], // WORK + int&, // LWORK + int & // INFO + ); + + + void TRIQS_FORTRAN_MANGLING(zheev)(char*,char*, // JOBZ and UPLO + int &, // Matrix Size + std::complex [], // matrix + int&, // LDA of the matrix + double[], // Eigenvalues array + std::complex[], // WORK + int &, // LWORK + double[], // WORK2 + int & // INFO + ); + + void TRIQS_FORTRAN_MANGLING(zgeev)(char*,char*, // JOBVL, JOBVR + int &, // Matrix Size + std::complex [], // matrix + int&, // LDA of the matrix + std::complex[], // Eigenvalues array + std::complex[], // VL + int &, //LDVL + std::complex[], // VR + int &, //LDVR + std::complex[], // WORK + int &, // LWORK + double[], // RWORK + int & // INFO + ); + + + void TRIQS_FORTRAN_MANGLING(zgesdd)(char*, // JOBZ + int &, // M + int &, // N + std::complex [], // matrix + int&, // LDA of the matrix + double[], // Singular values array + std::complex[], // U + int &, //LDU + std::complex[], // VT + int &, //LDVT + std::complex[], // WORK + int &, // LWORK + double[], // RWORK + int [], //IWORK + int & // INFO + ); + + double TRIQS_FORTRAN_MANGLING(dswap)(const int & N , double x[], const int& incx, double y[], const int& incy); + double TRIQS_FORTRAN_MANGLING(dcopy)(const int & N , double x[], const int& incx, double y[], const int& incy); + double TRIQS_FORTRAN_MANGLING(dscal)(const int & N , double & alpha,double x[], const int& incx); + + + double TRIQS_FORTRAN_MANGLING(ddot)(const int & N, double x[], const int& incx, double y[], const int & incy); + double TRIQS_FORTRAN_MANGLING(zdot)(const int & N, std::complex x[], const int& incx, std::complex y[], const int& incy); + + void TRIQS_FORTRAN_MANGLING(dtrmv)(const char & UPLO, const char & TRANS, const char & DIAG, + int & N, double A[], int & LDA, double X[], int & INCX); + void TRIQS_FORTRAN_MANGLING(dgemv)(const char* trans, const int & m, const int & n, const double & alpha, const double A[], int & lda, + const double x[], const int & incx, const double & beta, double y[], const int & incy); + void TRIQS_FORTRAN_MANGLING(dger)(const int &, const int &, const double &, double [], const int &, double [], const int &, double [], const int &); +} +*/ + + +#endif + diff --git a/triqs/arrays/blas_lapack/copy.hpp b/triqs/arrays/blas_lapack/copy.hpp new file mode 100644 index 00000000..d733f8f1 --- /dev/null +++ b/triqs/arrays/blas_lapack/copy.hpp @@ -0,0 +1,77 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_LAPACK_COPY_H +#define TRIQS_ARRAYS_BLAS_LAPACK_COPY_H +#include "./tools.hpp" +//#include "./qcache.hpp" + +namespace triqs { namespace arrays { namespace blas { + + namespace f77 { // overload + + extern "C" { + void TRIQS_FORTRAN_MANGLING(dcopy)(const int & N , const double * x, const int& incx, double * y, const int& incy); + void TRIQS_FORTRAN_MANGLING(zcopy)(const int & N , const std::complex * x, const int& incx, std::complex * y, const int& incy); + } + + inline void copy (const int & N, const double* x, const int & incx, double* Y, const int & incy) { + TRIQS_FORTRAN_MANGLING(dcopy)(N, x, incx, Y, incy); + } + inline void copy (const int & N, const std::complex* x, const int & incx, std::complex* Y, const int & incy) { + TRIQS_FORTRAN_MANGLING(zcopy)(N, x, incx, Y, incy); + } + } + + template< typename VTX, typename VTY> + struct use_blas_copy { + // I do not use cache here... + static constexpr bool are_both_value_view = is_amv_value_or_view_class::value && is_amv_value_or_view_class::value; + static constexpr bool value = are_both_value_view && is_blas_lapack_type::value && have_same_value_type< VTX, VTY>::value; + }; + + + /** + * Blas 1: copy + */ + template< typename VTX, typename VTY> + typename std::enable_if::value >::type + copy (VTX const & X, VTY & Y) { + static_assert( is_amv_value_or_view_class::value, "blas1 bindings only take vector and vector_view"); + static_assert( is_amv_value_or_view_class::value, "blas1 bindings only take vector and vector_view"); + //if (( X.size() != Y.size()) ) Y.resize(X.size()); + //const_qcache Cx(X); // mettre la condition a la main + f77::copy(X.size(), X.data_start(), X.stride(), Y.data_start(), Y.stride()); + //f77::copy(X.size(), Cx().data_start(), Cx().stride(), Y.data_start(), Y.stride()); + } + + // generic version + template< typename VTX, typename VTY> + typename std::enable_if< !use_blas_copy::value >::type + copy (VTX const & X, VTY & Y) { + if (X.size() != Y.size()) TRIQS_RUNTIME_ERROR << "blas copy generic : dimension mismatch "<< X.size() << Y.size(); + const size_t N = X.size(); + for (size_t i = 0; i < N; ++i) Y(i) = X(i); + } + +}}}// namespace + +#endif + diff --git a/triqs/arrays/blas_lapack/dot.hpp b/triqs/arrays/blas_lapack/dot.hpp new file mode 100644 index 00000000..983a9e84 --- /dev/null +++ b/triqs/arrays/blas_lapack/dot.hpp @@ -0,0 +1,128 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_LAPACK_DOT_H +#define TRIQS_ARRAYS_BLAS_LAPACK_DOT_H +#include "./tools.hpp" +//#include "./qcache.hpp" + +namespace triqs { namespace arrays { namespace blas { + + namespace f77 { // overload + + extern "C" { + double TRIQS_FORTRAN_MANGLING(ddot)(const int & N, const double * x, const int& incx, const double * y, const int & incy); + double TRIQS_FORTRAN_MANGLING(zdotc)(const int & N, const std::complex * x, const int& incx, const std::complex * y, const int& incy); + double TRIQS_FORTRAN_MANGLING(zdotu)(const int & N, const std::complex * x, const int& incx, const std::complex * y, const int& incy); + } + + inline double dot (const int & M, const double* x, const int & incx, const double* Y, const int & incy) { + return TRIQS_FORTRAN_MANGLING(ddot)(M, x, incx, Y, incy); + } + //inline std::complex dot (const int & M, const std::complex* x, const int & incx, const std::complex* Y, const int & incy) { + // return TRIQS_FORTRAN_MANGLING(zdotu)(M, x, incx, Y, incy); + // } + + } + + template + struct dispatch { + static constexpr bool are_both_value_view = is_amv_value_or_view_class::value && is_amv_value_or_view_class::value; + static constexpr bool are_both_double = std::is_same::value && std::is_same::value; + static constexpr int value = (are_both_value_view ? (are_both_double ? 0 : 1) : 2); + typedef decltype(std::declval()(0)* std::declval()(0)) result_type; + }; + + /** + * Calls dot product of 2 vectors. + * Takes care of making temporary copies if necessary + */ + template + typename std::enable_if< dispatch::value==0, typename dispatch::result_type>::type + dot (VTX const & X, VTY const & Y) { + //std::cerr << "dot : blas call"<< std::endl ; + static_assert( is_amv_value_or_view_class::value, "blas1 bindings only take vector and vector_view"); + static_assert( is_amv_value_or_view_class::value, "blas1 bindings only take vector and vector_view"); + if (( X.size() != Y.size()) ) TRIQS_RUNTIME_ERROR << "Dimension mismatch in dot size are : X : "< Cx(X); // mettre la condition a la main + //const_qcache Cy(Y); // mettre la condition a la main + return f77::dot(X.size(), X.data_start(), X.stride(), Y.data_start(), Y.stride()); + //return f77::dot(X.size(), Cx().data_start(), Cx().stride(), Cy().data_start(), Cy().stride()); + } + + template< bool Star, typename T> + typename std::enable_if::value && Star,T>::type + _conj(T && x) { return conj(std::forward(x));} + + template< bool Star, typename T> + typename std::enable_if::value && Star),T>::type + _conj(T && x) { return std::forward(x);} + + /** + * Calls dot product of 2 vectors. + * Takes care of making temporary copies if necessary + * general case. Also for complex since there is a bug on some machines (os X, weiss...) for zdotu, zdotc... + * a transcription from netlib zdotu + */ + template< bool Star, typename VTX, typename VTY> + typename std::enable_if< dispatch::value==1, typename dispatch::result_type>::type + dot (VTX const & X, VTY const & Y) { + //std::cerr << "dot: transcription of blas for non uniform type with restrict"<< std::endl ; + if (( X.size() != Y.size()) ) TRIQS_RUNTIME_ERROR << "Dimension mismatch in dot size are : X : "< Cx(X); // mettre la condition a la main + //const_qcache Cy(Y); // mettre la condition a la main + size_t N= X.size(), incx = X.stride(), incy = Y.stride(); + decltype(X(0)*Y(0)) res = 0; + // This only works for object with data (ISP), not only from the concept... + auto * restrict X_ = X.data_start(); + auto * restrict Y_ = Y.data_start(); + if ((incx==1) && (incy==1)) { + for (size_t i=0; i(X_[i]) * Y_[i]; + } + else { // code for unequal increments or equal increments not equal to 1 + for (size_t i=0, ix=0, iy=0; i(X_[ix]) * Y_[iy]; } + } + // general code for the concept. Is it really slower ? cf below + return res; + } + + /** + * Generic case + */ + template< bool Star, typename VTX, typename VTY> + typename std::enable_if< dispatch::value==2, typename dispatch::result_type>::type + dot (VTX const & X, VTY const & Y) { + //std::cerr << "dot : generic case"<< std::endl ; + if (( X.size() != Y.size()) ) TRIQS_RUNTIME_ERROR << "Dimension mismatch in dot size are : X : "<(X(i)) * Y(i); + return res; + } + +} + +template auto dot (VTX const & X, VTY const & Y) DECL_AND_RETURN( blas::dot(X,Y)); +template auto dotc (VTX const & X, VTY const & Y) DECL_AND_RETURN( blas::dot(X,Y)); + +}}// namespace + +#endif + diff --git a/triqs/arrays/blas_lapack/gemm.hpp b/triqs/arrays/blas_lapack/gemm.hpp new file mode 100644 index 00000000..e5186e52 --- /dev/null +++ b/triqs/arrays/blas_lapack/gemm.hpp @@ -0,0 +1,136 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_LAPACK_GEMM_H +#define TRIQS_ARRAYS_BLAS_LAPACK_GEMM_H +#include +#include "./tools.hpp" +#include "./qcache.hpp" + +namespace triqs { namespace arrays { namespace blas { + + using namespace blas_lapack_tools; + namespace f77 { // overload + + extern "C" { + void TRIQS_FORTRAN_MANGLING(dgemm) (char *, char *, const int & , const int & , const int & , const double &, + const double[], const int &, const double[], const int &, const double &, double[], const int & ); + void TRIQS_FORTRAN_MANGLING(zgemm) (char *, char *, const int & , const int & , const int & , const std::complex &, + const std::complex[], const int &, const std::complex[], const int &, const std::complex &, std::complex[], const int & ); + } + + inline void gemm (char trans_a, char trans_b, const int & M, const int & N, const int & K, const double & alpha, + const double* A, const int & LDA, const double* B, const int & LDB, const double & beta, double* C, const int & LDC) { + TRIQS_FORTRAN_MANGLING(dgemm)(&trans_a,&trans_b,M,N,K,alpha, A, LDA, B, LDB, beta, C, LDC); + } + + typedef std::complex dcomplex; + inline void gemm (char trans_a, char trans_b, const int & M, const int & N, const int & K, const dcomplex & alpha, + const dcomplex* A, const int & LDA, const dcomplex* B, const int & LDB, const dcomplex & beta, dcomplex* C, const int & LDC) { + TRIQS_FORTRAN_MANGLING(zgemm)(&trans_a,&trans_b,M,N,K,alpha, A, LDA, B, LDB, beta, C, LDC); + } + } + + template + struct use_blas_gemm { + static_assert(is_amv_value_or_view_class::value, "output of matrix product must be a matrix or matrix_view"); + //static constexpr bool are_both_value_view = is_amv_value_or_view_class::value && is_amv_value_or_view_class::value; + //static constexpr bool value = are_both_value_view && is_blas_lapack_type::value && have_same_value_type< MT1, MT2, MTOut>::value; + static constexpr bool value = is_blas_lapack_type::value && have_same_value_type< MT1, MT2, MTOut>::value; + // if inverse_lazy e.g. it is ok, we will use a cache anyway.... + }; + + /** + * Calls gemm on a matrix or view + * Takes care of making temporary copies if necessary + */ + template + typename std::enable_if< use_blas_gemm::value >::type + gemm (typename MT1::value_type alpha, MT1 const & A, MT2 const & B, typename MT1::value_type beta, MTOut & C) { + //std::cerr << "gemm: blas call "<< std::endl ; + // first resize if necessary and possible + resize_or_check_if_view(C,make_shape(A.dim0(),B.dim1())); + + // now we use qcache instead of the matrix to make a copy if necessary ... + // not optimal : if stride == 1, N ---> use LDA parameters + // change the condition in the qcache construction.... + reflexive_qcache Cc(C); + + if (C.memory_layout_is_c()) { + // then tC = tB tA ! + const_qcache Cb(A); // note the inversion A <-> B + const_qcache Ca(B); // note the inversion A <-> B + if (!(Ca().dim0() == Cb().dim1())) TRIQS_RUNTIME_ERROR << "Dimension mismatch in gemm : A : "<< Ca().shape() <<" while B : "< Ca(A); + const_qcache Cb(B); + if (!(Ca().dim1() == Cb().dim0())) TRIQS_RUNTIME_ERROR << "Dimension mismatch in gemm : A : "<< Ca().shape() <<" while B : "< + void gemm_generic (typename MT1::value_type alpha, MT1 const & A, MT2 const & B, typename MT1::value_type beta, MTOut & C) { + //std::cerr << "gemm: generic call "<< std::endl ; + // first resize if necessary and possible + resize_or_check_if_view(C,make_shape(A.dim0(),B.dim1())); + if (A.dim1() != B.dim0()) TRIQS_RUNTIME_ERROR << "gemm generic : dimension mismatch "<< A.shape() << B.shape(); + C() = 0; + for (int i=0; i + typename std::enable_if< !use_blas_gemm::value >::type + gemm (typename MT1::value_type alpha, MT1 const & A, MT2 const & B, typename MT1::value_type beta, MTOut & C) { + gemm_generic(alpha,A,B,beta,C); + } + +}}}// namespace + + +#endif + diff --git a/triqs/arrays/blas_lapack/gemv.hpp b/triqs/arrays/blas_lapack/gemv.hpp new file mode 100644 index 00000000..4f89cbeb --- /dev/null +++ b/triqs/arrays/blas_lapack/gemv.hpp @@ -0,0 +1,103 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_LAPACK_GEMV_H +#define TRIQS_ARRAYS_BLAS_LAPACK_GEMV_H +#include "./tools.hpp" +#include "./qcache.hpp" + +namespace triqs { namespace arrays { namespace blas { + + using namespace blas_lapack_tools; + namespace f77 { // overload + typedef std::complex dcomplex; + + extern "C" { + void TRIQS_FORTRAN_MANGLING(dgemv)(const char* trans, const int & m, const int & n, const double & alpha, const double A[], int & lda, + const double x[], const int & incx, const double & beta, double y[], const int & incy); + + void TRIQS_FORTRAN_MANGLING(zgemv)(const char* trans, const int & m, const int & n, const std::complex & alpha, const std::complex A[], int & lda, + const std::complex x[], const int & incx, const std::complex & beta, std::complex y[], const int & incy); + } + + inline void gemv (char * trans, const int & M, const int & N, double & alpha, const double* A, int & LDA, + const double* x, const int & incx, double & beta, double* Y, const int & incy) { + TRIQS_FORTRAN_MANGLING(dgemv)(trans, M, N, alpha, A, LDA,x, incx , beta, Y, incy); + } + + inline void gemv (char * trans, const int & M, const int & N, dcomplex & alpha, const dcomplex* A, int & LDA, + const dcomplex* x, const int & incx, dcomplex & beta, dcomplex* Y, const int & incy) { + TRIQS_FORTRAN_MANGLING(zgemv)(trans, M, N, alpha, A, LDA,x, incx , beta, Y, incy); + } + } + + template + struct use_blas_gemv { + static_assert(is_amv_value_or_view_class::value, "output of matrix product must be a matrix or matrix_view"); + //static constexpr bool are_both_value_view = is_amv_value_or_view_class::value && is_amv_value_or_view_class::value; + //static constexpr bool value = are_both_value_view && is_blas_lapack_type::value && have_same_value_type< MT, VT, VTOut>::value; + static constexpr bool value = is_blas_lapack_type::value && have_same_value_type< MT, VT, VTOut>::value; + // cf gemm comment + }; + + /** + * Calls gemv + * Takes care of making temporary copies if necessary + */ + template + typename std::enable_if< use_blas_gemv::value >::type + gemv (typename MT::value_type alpha, MT const & A, VT const & X, typename MT::value_type beta, VTOut & Y) { + //std::cerr << "gemm: blas call "<< std::endl ; + resize_or_check_if_view(Y,make_shape(A.dim0()));// first resize if necessary and possible + const_qcache Ca(A); + const_qcache Cx(X); // mettre la condition a la main + if (!(Ca().dim1() == Cx().size())) TRIQS_RUNTIME_ERROR << "Dimension mismatch in gemv : A : "<< Ca().shape() <<" while X : "< + void gemv_generic (typename MT::value_type alpha, MT const & A, VT const & X, typename MT::value_type beta, VTOut & C) { + //std::cerr << "gemm: generic call "<< std::endl ; + // first resize if necessary and possible + resize_or_check_if_view(C,make_shape(A.dim0())); + if (A.dim1() != X.size()) TRIQS_RUNTIME_ERROR << "gemm generic : dimension mismatch "<< A.dim1() << " vs " << X.size(); + C() = 0; + for (int i=0; i + typename std::enable_if< !use_blas_gemv::value >::type + gemv (typename MT::value_type alpha, MT const & A, VT const & X, typename MT::value_type beta, VTOut & Y) { + gemv_generic(alpha,A,X,beta,Y); + } + +}}}// namespace + + +#endif + diff --git a/triqs/arrays/blas_lapack/ger.hpp b/triqs/arrays/blas_lapack/ger.hpp new file mode 100644 index 00000000..318371a6 --- /dev/null +++ b/triqs/arrays/blas_lapack/ger.hpp @@ -0,0 +1,79 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_LAPACK_GER_H +#define TRIQS_ARRAYS_BLAS_LAPACK_GER_H +#include "./tools.hpp" +#include "./qcache.hpp" + +namespace triqs { namespace arrays { namespace blas { + + using namespace blas_lapack_tools; + namespace f77 { // overload + typedef std::complex dcomplex; + + extern "C" { + void TRIQS_FORTRAN_MANGLING(dger)(const int &M, const int &N, const double &, const double [], const int &, const double [], const int &, double [], const int &); + void TRIQS_FORTRAN_MANGLING(zgeru)(const int &M, const int &N, const dcomplex &, const dcomplex [], const int &, const dcomplex [], const int &, dcomplex [], const int &); + } + + inline void ger (const int & M, const int & N, const double & alpha, const double* x, const int & incx, const double* Y, const int & incy, double* A, const int & LDA) { + TRIQS_FORTRAN_MANGLING(dger)(M, N, alpha, x, incx, Y, incy, A, LDA); + } + inline void ger (const int & M, const int & N, const dcomplex & alpha, const dcomplex* x, const int & incx, const dcomplex* Y, const int & incy, dcomplex* A, const int & LDA) { + TRIQS_FORTRAN_MANGLING(zgeru)(M, N, alpha, x, incx, Y, incy, A, LDA); + } + } + + /** + * Calls ger : A += alpha * x * ty + * Takes care of making temporary copies if necessary + */ + template< typename VTX, typename VTY, typename MT> + typename std::enable_if< is_blas_lapack_type::value && have_same_value_type< VTX, VTY, MT>::value >::type + ger (typename VTX::value_type alpha, VTX const & X, VTY const & Y, MT & A) { + static_assert( is_amv_value_or_view_class::value, "ger : A must be a matrix or a matrix_view"); + if (( A.dim0() != Y.size()) || (A.dim1() != X.size())) TRIQS_RUNTIME_ERROR << "Dimension mismatch in ger : A : "<< A().shape() <<" while X : "< Cx(X); // mettre la condition a la main + const_qcache Cy(Y); // mettre la condition a la main + reflexive_qcache Ca(A); + if (Ca().memory_layout_is_c()) // tA += alpha y tx + f77::ger(get_n_rows(Ca()), get_n_cols(Ca()), alpha, Cy().data_start(), Cy().stride(), Cx().data_start(), Cx().stride(), Ca().data_start(), get_ld(Ca())); + else + f77::ger(get_n_rows(Ca()), get_n_cols(Ca()), alpha, Cx().data_start(), Cx().stride(), Cy().data_start(), Cy().stride(), Ca().data_start(), get_ld(Ca())); + + /* std::cerr << " Meme labout C"<< Ca().memory_layout_is_c() << " "<. + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_LAPACK_GETRF_H +#define TRIQS_ARRAYS_BLAS_LAPACK_GETRF_H +#include +#include "./tools.hpp" +#include "./qcache.hpp" + +namespace triqs { namespace arrays { namespace lapack { + + using namespace blas_lapack_tools; + namespace f77 { // overload + typedef std::complex dcomplex; + + extern "C" { + void TRIQS_FORTRAN_MANGLING(dgetrf) (const int &,const int &,double*, const int & ,int *,int &); + void TRIQS_FORTRAN_MANGLING(zgetrf) (const int &,const int &,std::complex*, const int & ,int *,int &); + } + + inline void getrf (const int & M, const int & N, double* A, const int & LDA, int * ipiv, int & info) { + TRIQS_FORTRAN_MANGLING(dgetrf)(M,N,A,LDA,ipiv,info); + } + inline void getrf (const int & M, const int & N, std::complex* A, const int & LDA, int * ipiv, int & info) { + TRIQS_FORTRAN_MANGLING(zgetrf)(M,N,A,LDA,ipiv,info); + } + } + + /** + * Calls getrf on a matrix or view + * Takes care of making temporary copies if necessary + */ + template + typename std::enable_if< is_blas_lapack_type::value, int >::type + getrf (MT & A, arrays::vector & ipiv, bool assert_fortran_order = false ) { + if (assert_fortran_order && A.memory_layout_is_c()) TRIQS_RUNTIME_ERROR<< "matrix passed to getrf is not in Fortran order"; + reflexive_qcache Ca(A); + auto dm = std::min(Ca().dim0(), Ca().dim1()); + if (ipiv.size() < dm) ipiv.resize(dm); + int info; + f77::getrf ( get_n_rows(Ca()), get_n_cols(Ca()), Ca().data_start(), get_ld(Ca()), ipiv.data_start(), info); + return info; + } +}}}// namespace + +#endif + diff --git a/triqs/arrays/blas_lapack/getri.hpp b/triqs/arrays/blas_lapack/getri.hpp new file mode 100644 index 00000000..da19d2b5 --- /dev/null +++ b/triqs/arrays/blas_lapack/getri.hpp @@ -0,0 +1,71 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_LAPACK_GETRI_H +#define TRIQS_ARRAYS_BLAS_LAPACK_GETRI_H +#include +#include "./tools.hpp" +#include "./qcache.hpp" + +namespace triqs { namespace arrays { namespace lapack { + + using namespace blas_lapack_tools; + namespace f77 { // overload + + extern "C" { + void TRIQS_FORTRAN_MANGLING(dgetri) (const int & , double *, const int & ,int *,double *,const int & ,int & ); + void TRIQS_FORTRAN_MANGLING(zgetri) (const int & , std::complex *, const int & ,int *,std::complex *,const int & ,int & ); + } + + inline void getri (const int & N, double* A, const int & LDA, int * ipiv, double * work, const int & lwork, int & info) { + TRIQS_FORTRAN_MANGLING(dgetri)(N,A,LDA,ipiv,work, lwork, info); + } + inline void getri (const int & N, std::complex* A, const int & LDA, int * ipiv, std::complex * work, const int & lwork, int & info) { + TRIQS_FORTRAN_MANGLING(zgetri)(N,A,LDA,ipiv,work, lwork, info); + } + } + + inline size_t r_round(double x) { return round(x);} + inline size_t r_round(std::complex x) { return round(real(x));} + /** + * Calls getri on a matrix or view + * Takes care of making temporary copies if necessary + */ + template + typename std::enable_if< is_blas_lapack_type::value, int >::type + getri (MT & A, arrays::vector & ipiv) { + //getri (MT & A, arrays::vector & ipiv, arrays::vector & work ) { + reflexive_qcache Ca(A); + auto dm = std::min(Ca().dim0(), Ca().dim1()); + if (ipiv.size() < dm) TRIQS_RUNTIME_ERROR << "getri : error in ipiv size : found "< work(lwork); + f77::getri ( get_n_rows(Ca()), Ca().data_start(), get_ld(Ca()), ipiv.data_start(), work.data_start(), lwork, info); + return info; + } + }}}// namespace + +#endif + diff --git a/triqs/arrays/blas_lapack/qcache.hpp b/triqs/arrays/blas_lapack/qcache.hpp new file mode 100644 index 00000000..1b9be947 --- /dev/null +++ b/triqs/arrays/blas_lapack/qcache.hpp @@ -0,0 +1,154 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_QCACHE_H +#define TRIQS_ARRAYS_QCACHE_H +#include "../matrix.hpp" +#include "../vector.hpp" +#include +namespace triqs { namespace arrays { namespace blas_lapack_tools { + + /** + * Given A, a matrix (or vector/array) it presents via the () operator + * - a const & to the matrix if A is a value class (matrix, vector, array, ..) + * - a const & to a new value class is A is a an expression + * - a const & to a view if A is a view. If the view was not contiguous, it is a view to a + * temporary regrouped value class. + * + * const_qcache is NOT copyable. It should be used in local use only. + * [Rational : in simple case, like A =matrix, it allows to keep only a const &, which is quicker + * + */ + template class const_qcache; + + template struct guarantee_no_copy : boost::mpl::or_< is_amv_value_class, is_vector_view > {}; + template struct may_need_copy : boost::mpl::or_< is_matrix_view > {}; + + // For any data structure for which we can guarantee no copy is need to go to blas/lapack : this is just a ref + template class const_qcache< A, ENABLE_IF(guarantee_no_copy) > { + A const & x; + public: + const_qcache(A const & x_):x(x_){} + const_qcache(const_qcache const &) = delete; + typedef A const & exposed_type; + exposed_type operator()() const {return x;} + }; + + // For any expression with matrix concept : we need to copy it into a matrix before using blas/lapack + template class const_qcache< A, ENABLE_IF(mpl::and_, mpl::not_ > >) > { + typedef matrix X; + X x; + public: + const_qcache(A const & x_):x(x_){} + const_qcache(const_qcache const &) = delete; + typedef X const & exposed_type; + exposed_type operator()() const {return x;} + }; + + // For any expression with vector concept : we need to copy it into a matrix before using blas/lapack + template class const_qcache< A, ENABLE_IF(mpl::and_, mpl::not_ > >) > { + typedef vector X; + X x; + public: + const_qcache(A const & x_):x(x_){} + const_qcache(const_qcache const &) = delete; + typedef X const & exposed_type; + exposed_type operator()() const {return x;} + }; + + // For any data structure for which we can NOT guarantee no copy is need to go to blas/lapack + // decision is to be taken at runtime + + // first the function to take the decision + // should be copy to call blas/lapack ? only if we have a view and if the min_stride + // of the matrix is not 1, otherwise we use the LD parameter of blas/lapack + template constexpr bool copy_is_needed (T const & A) { return false;} + + template + bool copy_is_needed (matrix_view const & A) { + auto min_stride = A.indexmap().strides()[A.memory_layout_is_fortran() ? 0 : 1]; + return min_stride !=1; + } + + // now the class + template class const_qcache< A, ENABLE_IF(may_need_copy)> { + const bool need_copy; + A keeper; + struct internal_data { + typename A::non_view_type copy_data; + A view; + internal_data(const_qcache const & P) : copy_data(P.keeper), view(copy_data) { +#ifdef TRIQS_ARRAYS_CACHE_COPY_VERBOSE + std::cerr<< " Cache : copy made "<< std::endl; + std::cerr<< " -- TRACE = --" << std::endl << triqs::utility::stack_trace() << std::endl; +#endif + } + }; + friend struct internal_data; + mutable std::unique_ptr _id; + internal_data & id() const { assert(need_copy); if (!_id) _id.reset(new internal_data(*this)); return *_id;} + + protected: + void back_update() { if (_id) keeper = _id->copy_data; } // copy data back (for derivative, but but mechanism here). + A & view() { return (need_copy ? id().view : keeper);} + A const & view() const{ return (need_copy ? id().view : keeper);} + + public : + explicit const_qcache(A const & x): need_copy (blas_lapack_tools::copy_is_needed (x)), keeper(x) {} + const_qcache(const_qcache const &) = delete; + typedef const A exposed_type; + exposed_type operator()() const { return view();} + }; + + /** + * reflexive_qcache. + * Given A, a value or a view, it presents via the () operator + * - a & to the matrix if A is a value class (matrix, vector, array, ..) + * - a view if A is a view. If the view given at construction was not contiguous, it is a view to a + * temporary regrouped value class. In that case, the data are back copied to the original at construction. + * + * reflexive_qcache is NOT copyable. It should be used in local use only. + * [Rational : in simple case, like A =matrix, it allows to keep only a &, which is quicker + * + */ + template class reflexive_qcache; + + template class reflexive_qcache )> { + A & x; + public: + reflexive_qcache(A & x_):x(x_){} + reflexive_qcache(reflexive_qcache const &) = delete; + typedef A & exposed_type; + exposed_type operator()() const {return x;} + }; + + template class reflexive_qcache )> : const_qcache { + typedef const_qcache B; + public : + explicit reflexive_qcache(A const & x) : B(x) {} + reflexive_qcache(reflexive_qcache const &) = delete; + ~reflexive_qcache() { this->back_update();} + typedef A exposed_type; + exposed_type operator()() { return B::view(); } + }; + +}}}//namespace triqs::arrays::blas_lapack +#endif + diff --git a/triqs/arrays/blas_lapack/scal.hpp b/triqs/arrays/blas_lapack/scal.hpp new file mode 100644 index 00000000..f867e184 --- /dev/null +++ b/triqs/arrays/blas_lapack/scal.hpp @@ -0,0 +1,51 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_LAPACK_SCAL_H +#define TRIQS_ARRAYS_BLAS_LAPACK_SCAL_H +#include "./tools.hpp" + +namespace triqs { namespace arrays { namespace blas { + + namespace f77 { // overload + + extern "C" { + void TRIQS_FORTRAN_MANGLING(dscal)(const int & N, const double & alpha,double * x, const int& incx); + void TRIQS_FORTRAN_MANGLING(zscal)(const int & N, const std::complex & alpha,std::complex * x, const int& incx); + } + + inline void scal (const int & M, const double & alpha, double* x, const int & incx) { TRIQS_FORTRAN_MANGLING(dscal)(M, alpha, x, incx); } + inline void scal (const int & M, const std::complex & alpha, std::complex* x, const int & incx) { TRIQS_FORTRAN_MANGLING(zscal)(M, alpha, x, incx); } + } + + /** + * Blas1 : scal + */ + template< typename VT> + typename std::enable_if< is_blas_lapack_type::value && have_same_value_type< VT>::value >::type + scal (typename VT::value_type const & alpha, VT & X) { + static_assert( is_amv_value_or_view_class::value, "blas1 bindings only take vector and vector_view"); + f77::scal(X.size(), alpha, X.data_start(), X.stride()); + } + +}}}// namespace + +#endif + diff --git a/triqs/arrays/blas_lapack/stev.hpp b/triqs/arrays/blas_lapack/stev.hpp new file mode 100644 index 00000000..62bf9fd1 --- /dev/null +++ b/triqs/arrays/blas_lapack/stev.hpp @@ -0,0 +1,61 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_LAPACK_DSTEV_H +#define TRIQS_ARRAYS_BLAS_LAPACK_DSTEV_H +#include "./tools.hpp" + +namespace triqs { namespace arrays { namespace blas { + + using namespace blas_lapack_tools; + namespace f77 { // overload + + extern "C" { + void TRIQS_FORTRAN_MANGLING(dstev)(const char *, const int &N, const double [], const double [], const double [], const int &, double [], int &); + } + + inline void stev (char J, const int & N, double* D, double* E, double* Z, int ldz, double * work, int & info) { + TRIQS_FORTRAN_MANGLING(dstev)(&J,N,D,E,Z,ldz,work,info); + } + } + + struct tridiag_worker { + arrays::vector D,E,W; + matrix Z; + size_t s; + tridiag_worker (size_t n){ s=0; resize(n);} + void resize(size_t n) { if (s + void operator()(VT const & d, VT const & e) { + if (e.size() != d.size() -1) TRIQS_RUNTIME_ERROR << " Error in tridiagonal matrix diagonalization size mismatch"; + resize(d.size()); + D(range(0,s)) = d; + E(range(0,s-1)) = e; + int info; + f77::stev ('V',d.size(),D.data_start(),E.data_start(), Z.data_start(), Z.len(0),W.data_start(), info); + if (info !=0) TRIQS_RUNTIME_ERROR << " Error in tridiagonal matrix diagonalization "<< info; + } + arrays::vector_view values() const { return D(range(0,s));} + matrix_view vectors() const { return Z(range(0,s),range(0,s));} + }; + +}}}// namespace +#endif + diff --git a/triqs/arrays/blas_lapack/swap.hpp b/triqs/arrays/blas_lapack/swap.hpp new file mode 100644 index 00000000..3e0a6d2c --- /dev/null +++ b/triqs/arrays/blas_lapack/swap.hpp @@ -0,0 +1,57 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_BLAS_LAPACK_SWAP_H +#define TRIQS_ARRAYS_BLAS_LAPACK_SWAP_H +#include "./tools.hpp" + +namespace triqs { namespace arrays { namespace blas { + + namespace f77 { // overload + + extern "C" { + void TRIQS_FORTRAN_MANGLING(dswap)(const int & N, double * x, const int& incx, double * y, const int& incy); + void TRIQS_FORTRAN_MANGLING(zswap)(const int & N, std::complex * x, const int& incx, std::complex * y, const int& incy); + } + + inline void swap (const int & N, double* x, const int & incx, double* Y, const int & incy) { + TRIQS_FORTRAN_MANGLING(dswap)(N, x, incx, Y, incy); + } + inline void swap (const int & N, std::complex* x, const int & incx, std::complex* Y, const int & incy) { + TRIQS_FORTRAN_MANGLING(zswap)(N, x, incx, Y, incy); + } + } + + /** + * Blas 1: swap + */ + template< typename VTX, typename VTY> + typename std::enable_if< is_blas_lapack_type::value && have_same_value_type< VTX, VTY>::value >::type + swap (VTX & X, VTY & Y) { + static_assert( is_amv_value_or_view_class::value, "blas1 bindings only take vector and vector_view"); + static_assert( is_amv_value_or_view_class::value, "blas1 bindings only take vector and vector_view"); + if (( X.size() != Y.size()) ) TRIQS_RUNTIME_ERROR << "Dimension mismatch in dot : X : "<. + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_IS_BLAS_LAPACK_TYPE_H +#define TRIQS_ARRAYS_IS_BLAS_LAPACK_TYPE_H +#include +#include + +namespace triqs { namespace arrays { + + // a trait to detect all types for which blas/lapack bindings is defined + // at the moment double and std::complex + // We don't need simple precision for the moment... To be added ? + template struct is_blas_lapack_type : std::false_type{}; + template<> struct is_blas_lapack_type : std::true_type{}; + template<> struct is_blas_lapack_type > : std::true_type{}; + template struct is_blas_lapack_type< const T> : is_blas_lapack_type{}; + + // true iif all T::value_type are the same + template struct have_same_value_type; + template struct have_same_value_type: std::true_type{}; + template struct have_same_value_type: + std::integral_constant::type, typename std::remove_cv::type> ::value + && have_same_value_type::value> {}; + + namespace blas_lapack_tools { + + template char get_trans(MatrixType const & A, bool transpose) { + return (A.memory_layout_is_fortran() ? (transpose ? 'T' : 'N') : (transpose ? 'N' : 'T') ); + } + + // returns the # of rows of the matrix *seen* as fortran matrix + template int get_n_rows (MatrixType const & A) { + return (A.memory_layout_is_fortran() ? A.dim0() : A.dim1()); + } + // returns the # of cols of the matrix *seen* as fortran matrix + template int get_n_cols (MatrixType const & A) { + return (A.memory_layout_is_fortran() ? A.dim1() : A.dim0()); + } + + template int get_ld (MatrixType const & A) { + return A.indexmap().strides()[A.memory_layout_is_fortran() ? 1 : 0]; + } + + } +}}// namespace + +#endif + diff --git a/triqs/arrays/cache.hpp b/triqs/arrays/cache.hpp new file mode 100644 index 00000000..5aea0738 --- /dev/null +++ b/triqs/arrays/cache.hpp @@ -0,0 +1,118 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_CACHE_H +#define TRIQS_ARRAYS_CACHE_H +#include "./array.hpp" +#include +namespace triqs { namespace arrays { + + template class const_cache; + template class cache; + + template + const_cache > + make_const_cache( D const & x, memory_layout< D::domain_type::rank> ml = memory_layout< D::domain_type::rank>('C') ) { + return const_cache > (x,ml); + } + + template + cache > + make_cache( D const & x, memory_layout< D::domain_type::rank> ml = memory_layout< D::domain_type::rank>('C') ) { + return cache > (x,ml); + } + + // ----------------- implementation ---------------------------------- + + // The type of A1, and A2 can already imply a copy. Compile time decision. + template struct need_copy_ct : mpl::true_{}; + template struct need_copy_ct)> : + mpl::not_ > {}; + //mpl::not_ >{}; + + template class const_cache { + protected: + typedef memory_layout< DataType::domain_type::rank> ml_t; + const ml_t ml; + typename view_type_if_exists_else_type::type keeper; + static const bool CT_need_copy = need_copy_ct::value; + const bool need_copy; + typedef typename CacheType::view_type exposed_view_type; + struct internal_data { + CacheType copy; + exposed_view_type view; + internal_data(const_cache const & P,ml_t ml) : copy(CacheType(P.keeper,ml)), view(copy) { +#ifdef TRIQS_ARRAYS_CACHE_COPY_VERBOSE + std::cerr<< " Cache : copy made "<< std::endl<< " -- TRACE = --" << std::endl << triqs::utility::stack_trace() << std::endl; +#endif + } + }; + friend struct internal_data; + mutable boost::shared_ptr _id; + internal_data & id() const { if (!_id) _id= boost::make_shared(*this,ml); return *_id;} + + //exposed_view_type & view2 () { if (need_copy) return id().view; else return keeper;} + //exposed_view_type const & view2 () const { if (need_copy) return id().view; else return keeper;} + + // avoid compiling the transformation keeper-> exposed_view_type when it does not make sense + exposed_view_type & view1 (mpl::false_) { if (need_copy) return id().view; else return keeper; } + exposed_view_type const & view1 (mpl::false_) const { if (need_copy) return id().view; else return keeper;} + + exposed_view_type & view1 (mpl::true_) { return id().view; } + exposed_view_type const & view1 (mpl::true_) const { return id().view; } + + exposed_view_type & view2 () { return view1(mpl::bool_());} + exposed_view_type const & view2 () const { return view1(mpl::bool_());} + + template + typename std::enable_if< ! is_amv_value_or_view_class::value, bool>::type + need_copy_dynamic ( D const & x) const { return false;} + + template + typename std::enable_if::value, bool>::type + need_copy_dynamic ( D const & x) const { return (x.indexmap().memory_indices_layout() != ml );} + + public : + const_cache (DataType const & x, ml_t ml_ = ml_t()): + ml(ml_),keeper (x), + need_copy ( CT_need_copy || need_copy_dynamic(x) || (!has_contiguous_data(x)) ) {} + void update() { if (need_copy && _id) id().view = keeper;} + exposed_view_type const & view () const { return view2();} + operator exposed_view_type const & () const { return view2();} + }; + + // Non const case : just add the back copy in the destructor + template class cache : const_cache { + static_assert( is_amv_value_or_view_class::value, "non const cache only for regular classes and views, not expressions"); + typedef const_cache B; + typedef typename B::ml_t ml_t; + public : + cache (DataType const & x, ml_t ml = ml_t() ): B(x,ml) {} + ~cache() { back_update(); } + void back_update() { if (this->need_copy) this->keeper = this->id().view;} + typename B::exposed_view_type & view () {return B::view2();} + typename B::exposed_view_type const & view () const {return B::view2();} + operator typename B::exposed_view_type & () {return B::view2();} + operator typename B::exposed_view_type const & () const {return B::view2();} + }; +}}//namespace triqs::arrays +#endif + + diff --git a/triqs/arrays/expression_template/array_algebra.hpp b/triqs/arrays/expression_template/array_algebra.hpp new file mode 100644 index 00000000..259aff91 --- /dev/null +++ b/triqs/arrays/expression_template/array_algebra.hpp @@ -0,0 +1,85 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_EXPRESSION_ARRAY_ALGEBRA_H +#define TRIQS_ARRAYS_EXPRESSION_ARRAY_ALGEBRA_H +#include "./tools.hpp" +namespace triqs { namespace arrays { + + template + struct array_expr : TRIQS_MODEL_CONCEPT(ImmutableCuboidArray) { + typedef typename keeper_type::type L_t; + typedef typename keeper_type::type R_t; + static_assert( get_rank::value==0 || get_rank::value==0 || get_rank::value == get_rank::value, "rank mismatch in array operations"); + typedef typename std::result_of(typename L_t::value_type,typename R_t::value_type)>::type value_type; + typedef typename std::remove_reference::type>::type domain_type; + + L_t l; R_t r; + template array_expr(LL && l_, RR && r_) : l(std::forward(l_)), r(std::forward(r_)) {} + + domain_type domain() const { return combine_domain()(l,r); } + + //template value_type operator[](KeyType && key) const { return operation()(l[std::forward(key)] , r[std::forward(key)]);} + template value_type operator()(Args && ... args) const { return operation()(l(std::forward(args)...) , r(std::forward(args)...));} + friend std::ostream &operator <<(std::ostream &sout, array_expr const &expr){return sout << "("<::name << " "< struct array_unary_m_expr : TRIQS_MODEL_CONCEPT(ImmutableCuboidArray) { + typedef typename keeper_type::type L_t; + typedef typename L_t::value_type value_type; + typedef typename L_t::domain_type domain_type; + + L_t l; + template array_unary_m_expr(LL && l_) : l(std::forward(l_)) {} + + domain_type domain() const { return l.domain(); } + + //template value_type operator[](KeyType&& key) const {return -l[key];} + template value_type operator()(Args && ... args) const { return -l(std::forward(args)...);} + friend std::ostream &operator <<(std::ostream &sout, array_unary_m_expr const &expr){return sout << '-'<\ + typename std::enable_if::value && TRAIT2 ::value, array_expr>::type\ + operator OP (A1 const & a1, A2 const & a2) { return array_expr(a1,a2);} + +DEFINE_OPERATOR(plus, +, ImmutableCuboidArray,ImmutableCuboidArray); +DEFINE_OPERATOR(minus, -, ImmutableCuboidArray,ImmutableCuboidArray); +DEFINE_OPERATOR(multiplies, *, ImmutableCuboidArray,ImmutableCuboidArray); +DEFINE_OPERATOR(multiplies, *, is_in_ZRC,ImmutableCuboidArray); +DEFINE_OPERATOR(multiplies, *, ImmutableCuboidArray,is_in_ZRC); +DEFINE_OPERATOR(divides, /, ImmutableCuboidArray,ImmutableCuboidArray); +DEFINE_OPERATOR(divides, /, is_in_ZRC,ImmutableCuboidArray); +DEFINE_OPERATOR(divides, /, ImmutableCuboidArray,is_in_ZRC); +#undef DEFINE_OPERATOR + + // the unary is special + template typename std::enable_if::value, array_unary_m_expr>::type + operator - (A1 const & a1) { return {a1};} + + template array + make_array( Expr const & e) { return array(e);} + +}}//namespace triqs::arrays +#endif diff --git a/triqs/arrays/expression_template/matrix_algebra.hpp b/triqs/arrays/expression_template/matrix_algebra.hpp new file mode 100644 index 00000000..b66779ea --- /dev/null +++ b/triqs/arrays/expression_template/matrix_algebra.hpp @@ -0,0 +1,117 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_EXPRESSION_MATRIX_ALGEBRA_H +#define TRIQS_ARRAYS_EXPRESSION_MATRIX_ALGEBRA_H +#include "./vector_algebra.hpp" +#include "../matrix.hpp" +#include "../linalg/matmul.hpp" +#include "../linalg/mat_vec_mul.hpp" +#include "../linalg/inverse.hpp" +namespace triqs { namespace arrays { + + template + struct matrix_expr : TRIQS_MODEL_CONCEPT(ImmutableMatrix) { + typedef typename keeper_type::type L_t; + typedef typename keeper_type::type R_t; + static_assert( get_rank::value==0 || get_rank::value==0 || get_rank::value == get_rank::value, "rank mismatch in matrix operations"); + typedef typename std::result_of(typename L_t::value_type,typename R_t::value_type)>::type value_type; + typedef typename std::remove_cv< typename std::remove_reference::type>::type>::type domain_type; + + L_t l; R_t r; + template matrix_expr(LL && l_, RR && r_) : l(std::forward(l_)), r(std::forward(r_)) {} + + domain_type domain() const { return combine_domain()(l,r); } + mini_vector shape() const { return this->domain().lengths();} + size_t dim0() const { return this->domain().lengths()[0];} + size_t dim1() const { return this->domain().lengths()[1];} + + //template value_type operator[](KeyType && key) const { return operation()(l[std::forward(key)] , r[std::forward(key)]);} + template value_type operator()(Args && ... args) const { return operation()(l(std::forward(args)...) , r(std::forward(args)...));} + friend std::ostream &operator <<(std::ostream &sout, matrix_expr const &expr){return sout << "("<::name << " "< // a special case : the unary operator ! + struct matrix_unary_m_expr : TRIQS_MODEL_CONCEPT(ImmutableMatrix) { + typedef typename keeper_type::type L_t; + typedef typename L_t::value_type value_type; + typedef typename L_t::domain_type domain_type; + L_t l; + template matrix_unary_m_expr(LL && l_) : l(std::forward(l_)) {} + + domain_type domain() const { return l.domain(); } + mini_vector shape() const { return this->domain().lengths();} + size_t dim0() const { return this->domain().lengths()[0];} + size_t dim1() const { return this->domain().lengths()[1];} + + //template value_type operator[](KeyType&& key) const {return -l[key];} + template value_type operator()(Args && ... args) const { return -l(std::forward(args)...);} + friend std::ostream &operator <<(std::ostream &sout, matrix_unary_m_expr const &expr){return sout << '-'<\ + typename std::enable_if::value && TRAIT2 ::value, matrix_expr>::type\ + operator OP (A1 const & a1, A2 const & a2) { return matrix_expr(a1,a2);} + + DEFINE_OPERATOR(plus, +, ImmutableMatrix,ImmutableMatrix); + DEFINE_OPERATOR(minus, -, ImmutableMatrix,ImmutableMatrix); + DEFINE_OPERATOR(minus, -, ImmutableMatrix,is_in_ZRC); + DEFINE_OPERATOR(minus, -, is_in_ZRC,ImmutableMatrix); + DEFINE_OPERATOR(multiplies, *, is_in_ZRC,ImmutableMatrix); + DEFINE_OPERATOR(multiplies, *, ImmutableMatrix,is_in_ZRC); + DEFINE_OPERATOR(divides, /, ImmutableMatrix,is_in_ZRC); +#undef DEFINE_OPERATOR + + // the addition/substraction of diagonal matrix is special : all scalar are diagonal matrices here... +#define DEFINE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \ + template\ + typename std::enable_if::value && TRAIT2 ::value, matrix_expr>::type\ + operator OP (A1 const & a1, A2 const & a2) { return matrix_expr(a1,a2);} + + DEFINE_OPERATOR(plus, +, ImmutableMatrix,is_in_ZRC); + DEFINE_OPERATOR(plus, +, is_in_ZRC,ImmutableMatrix); + DEFINE_OPERATOR(minus, -, ImmutableMatrix,is_in_ZRC); + DEFINE_OPERATOR(minus, -, is_in_ZRC,ImmutableMatrix); +#undef DEFINE_OPERATOR + + // the unary is special + template typename std::enable_if::value, matrix_unary_m_expr>::type + operator - (A1 const & a1) { return {a1};} + + template matrix + make_matrix( Expr const & e) { return matrix(e);} + + template // matrix * matrix + typename boost::enable_if< mpl::and_, ImmutableMatrix >, matmul_lazy >::type + operator* (M1 const & a, M2 const & b) { return matmul_lazy(a,b); } + + template // matrix * vector + typename boost::enable_if< mpl::and_, ImmutableVector >, mat_vec_mul_lazy >::type + operator* (M const & m, V const & v) { return mat_vec_mul_lazy(m,v); } + + template // anything / matrix ---> anything * inverse(matrix) + typename boost::lazy_enable_if< ImmutableMatrix, type_of_mult > >::type + operator/ (A const & a, M const & m) { return a * inverse(m);} + +}}//namespace triqs::arrays +#endif + diff --git a/triqs/arrays/expression_template/tools.hpp b/triqs/arrays/expression_template/tools.hpp new file mode 100644 index 00000000..86675b9b --- /dev/null +++ b/triqs/arrays/expression_template/tools.hpp @@ -0,0 +1,100 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_EXPRESSION_TOOLS_H +#define TRIQS_ARRAYS_EXPRESSION_TOOLS_H +#include +namespace triqs { namespace arrays { + + namespace tags { struct plus{}; struct minus{}; struct multiplies{}; struct divides{}; } + +// The basic operations put in a template.... + template struct operation; + template<> struct operation { + template auto operator()(L const & l, R const & r) const -> decltype(l+r) { return l+r;} + static const char name = '+'; + }; + template<> struct operation { + template auto operator()(L const & l, R const & r) const -> decltype(l-r) { return l-r;} + static const char name = '-'; + }; + template<> struct operation { + template auto operator()(L const & l, R const & r) const -> decltype(l*r) { return l*r;} + static const char name = '*'; + }; + template<> struct operation { + template auto operator()(L const & l, R const & r) const -> decltype(l/r) { return l/r;} + static const char name = '/'; + }; + +// The scalar ... + template struct is_in_ZRC : boost::is_arithmetic {}; + template<> struct is_in_ZRC : mpl::true_ {}; + template struct is_in_ZRC > : mpl::true_ {}; + + // Wrapping the scalar in a little struct to recognize it + // In a matrix expression, the evaluation differ (it is a scalar matrix ....) + template struct scalar_wrap; + + // First the scalar for an array expression ... + template struct scalar_wrap { + typedef S value_type; + S s; scalar_wrap(S const &s_):s(s_){} + template value_type operator[](KeyType&& key) const {return s;} + template inline value_type operator()(Args && ... args) const { return s;} + friend std::ostream &operator <<(std::ostream &sout, scalar_wrap const &expr){return sout << expr.s; } + }; + + // Second the scalar for a matrix expression ... + template struct scalar_wrap { + typedef S value_type; + S s; scalar_wrap(S const &s_):s(s_){} + template value_type operator[](KeyType&& key) const {return (key[0]==key[1] ? s : S());} + template inline value_type operator()(A1 && a1, A2 && a2) const { return (a1==a2 ? s : S());} + friend std::ostream &operator <<(std::ostream &sout, scalar_wrap const &expr){return sout << expr.s; } + }; + + // get the rank of something .... + template struct get_rank { static constexpr int value = std::remove_reference::type::domain_type::rank;}; + template struct get_rank> { static constexpr int value =0;}; + + // + template struct keeper_type : boost::mpl::if_, scalar_wrap, typename view_type_if_exists_else_type::type> {}; + + // Combine the two domains of LHS and RHS : need to specialize where there is a scalar + struct combine_domain { + template + inline auto operator() (L const & l, R const & r) const -> decltype(l.domain()) { + if (l.domain().lengths() != r.domain().lengths()) TRIQS_RUNTIME_ERROR << "Domain size mismatch : "<< l.domain().lengths()<<" vs" < auto operator() (scalar_wrap const & w, R const & r) const -> decltype(r.domain()) { return r.domain();} + template auto operator() (L const & l, scalar_wrap const & w) const -> decltype(l.domain()) { return l.domain();} + }; + + template + struct type_of_mult{ + //typedef typename boost::remove_reference::type T1; typedef typename boost::remove_reference::type T2; + //typedef BOOST_TYPEOF_TPL( (*(pseudo_default_construct())) * (*(pseudo_default_construct()))) type; + typedef decltype ( std::declval::type>() * std::declval::type>() ) type; + }; + +}}//namespace triqs::arrays +#endif diff --git a/triqs/arrays/expression_template/vector_algebra.hpp b/triqs/arrays/expression_template/vector_algebra.hpp new file mode 100644 index 00000000..e46d5d65 --- /dev/null +++ b/triqs/arrays/expression_template/vector_algebra.hpp @@ -0,0 +1,91 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_EXPRESSION_VECTOR_ALGEBRA_H +#define TRIQS_ARRAYS_EXPRESSION_VECTOR_ALGEBRA_H +#include "./tools.hpp" +#include "../matrix.hpp" +namespace triqs { namespace arrays { + + template + struct vector_expr : TRIQS_MODEL_CONCEPT(ImmutableVector) { + typedef typename keeper_type::type L_t; + typedef typename keeper_type::type R_t; + L_t l; R_t r; + template vector_expr(LL && l_, RR && r_) : l(std::forward(l_)), r(std::forward(r_)) {} + static_assert( get_rank::value==0 || get_rank::value==0 || get_rank::value == get_rank::value, "rank mismatch in array operations"); + typedef typename std::result_of(typename L_t::value_type,typename R_t::value_type)>::type value_type; + typedef typename std::remove_reference::type>::type domain_type; + + domain_type domain() const { return combine_domain()(l,r); } + mini_vector shape() const { return this->domain().lengths();} + //size_t dim0() const { return this->domain().lengths()[0];} + size_t size() const { return this->domain().lengths()[0];} + + //template value_type operator[](KeyType && key) const { return operation()(l[std::forward(key)] , r[std::forward(key)]);} + template value_type operator()(Args && ... args) const { return operation()(l(std::forward(args)...) , r(std::forward(args)...));} + friend std::ostream &operator <<(std::ostream &sout, vector_expr const &expr){return sout << "("<::name << " "< // a special case : the unary operator ! + struct vector_unary_m_expr : TRIQS_MODEL_CONCEPT(ImmutableVector) { + typedef typename keeper_type::type L_t; + L_t l; + template vector_unary_m_expr(LL && l_) : l(std::forward(l_)) {} + typedef typename L_t::value_type value_type; + typedef typename L_t::domain_type domain_type; + + domain_type domain() const { return l.domain(); } + mini_vector shape() const { return this->domain().lengths();} + //size_t dim0() const { return this->domain().lengths()[0];} + size_t size() const { return this->domain().lengths()[0];} + + //template value_type operator[](KeyType&& key) const {return -l[key];} + template value_type operator()(Args && ... args) const { return -l(std::forward(args)...);} + friend std::ostream &operator <<(std::ostream &sout, vector_unary_m_expr const &expr){return sout << '-'<\ + typename std::enable_if::value && TRAIT2 ::value, vector_expr>::type\ + operator OP (A1 const & a1, A2 const & a2) { return vector_expr(a1,a2);} +#define DELETE_OPERATOR(TAG, OP, TRAIT1, TRAIT2) \ + template\ + typename std::enable_if::value && TRAIT2 ::value, vector_expr>::type\ + operator OP (A1 const & a1, A2 const & a2) = delete; + DEFINE_OPERATOR(plus, +, ImmutableVector,ImmutableVector); + DEFINE_OPERATOR(minus, -, ImmutableVector,ImmutableVector); + DELETE_OPERATOR(multiplies, *, ImmutableVector,ImmutableVector); + DELETE_OPERATOR(divides, /, ImmutableVector,ImmutableVector); + DEFINE_OPERATOR(multiplies, *, is_in_ZRC,ImmutableVector); + DEFINE_OPERATOR(multiplies, *, ImmutableVector,is_in_ZRC); + DEFINE_OPERATOR(divides, /, ImmutableVector,is_in_ZRC); +#undef DEFINE_OPERATOR + + // the unary is special + template typename std::enable_if::value, vector_unary_m_expr>::type + operator - (A1 const & a1) { return {a1};} + + template vector + make_vector( Expr const & e) { return vector(e);} + +}}//namespace triqs::arrays +#endif diff --git a/triqs/arrays/functional/fold.hpp b/triqs/arrays/functional/fold.hpp new file mode 100644 index 00000000..be11eaa2 --- /dev/null +++ b/triqs/arrays/functional/fold.hpp @@ -0,0 +1,66 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_EXPRESSION_FOLD_H +#define TRIQS_ARRAYS_EXPRESSION_FOLD_H +#include +#include +#include +#include "../array.hpp" + +namespace triqs { namespace arrays { + + template + class fold_worker { + F f; + typedef typename boost::remove_const::type>::type result_type; + + template + struct fold_func_adaptor { + A const & b; + F f; result_type r; + fold_func_adaptor(F f_, A const & a_,typename A::value_type init ):b(a_), f(f_) { r= init;} + template void operator()(Args const & ... args) { r = f(r,b(args...)); } + }; + + public: + + fold_worker ( F const & f_):f(f_) {} + + template + result_type operator() (A const & a, typename A::value_type init = typename A::value_type() ) const { + fold_func_adaptor func(f,a,init); + //fold_func_adaptor func(f,init); + foreach(a,std::ref(func)); + //foreach(a,boost::ref(func)); + return func.r; + } + }; + + template fold_worker fold (F const & f) { return fold_worker(f);} + + template + fold_worker< boost::function > + fold (R (*f)(A1,A1)) { return fold( boost::function(f)); } + +}}//namespace triqs::arrays + +#endif + diff --git a/triqs/arrays/functional/map.hpp b/triqs/arrays/functional/map.hpp new file mode 100644 index 00000000..8fac912b --- /dev/null +++ b/triqs/arrays/functional/map.hpp @@ -0,0 +1,140 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_EXPRESSION_MAP_H +#define TRIQS_ARRAYS_EXPRESSION_MAP_H +#include "../impl/common.hpp" +#include +namespace triqs { namespace arrays { + + template class map_impl; + + /** + * Given a function f : arg_type -> result_type, map(f) is the function promoted to arrays + * map(f) : array --> array + */ + template map_impl map (F const & f) { return map_impl(f,true); } + template map_impl map2 (F const & f) { return map_impl(f,true); } + + // ----------- implementation ------------------------------------- + + // NB The bool is to make constructor not ambiguous + // clang on os X with lib++ has a pb otherwise (not clear what the pb is) + template class map_impl { + F f; + public : +// map_impl(F const & f_):f(f_) {} + map_impl(F const & f_, bool):f(f_) {} + map_impl(F && f_, bool):f(f_) {} + map_impl(map_impl const &) = default; + //map_impl(map_impl &&) = default; + + template class m_result; + + template class m_result >::type> : TRIQS_MODEL_CONCEPT(ImmutableCuboidArray) { + public: + typedef typename std::result_of::type value_type; + typedef typename A::domain_type domain_type; + A const & a; F f; + m_result(F const & f_, A const & a_):a(a_),f(f_) {} + domain_type domain() const { return a.domain(); } + template value_type operator() (Args const & ... args) const { return f(a(args...)); } + //value_type operator[] ( typename domain_type::index_value_type const & key) const { return f(a[key]); } + friend std::ostream & operator<<(std::ostream & out, m_result const & x){ return out<<"lazy matrix resulting of a mapping";} + }; + + template class m_result >::type> : TRIQS_MODEL_CONCEPT(ImmutableMatrix) { + public: + typedef typename std::result_of::type value_type; + typedef typename A::domain_type domain_type; + A const & a; F f; + m_result(F const & f_, A const & a_):a(a_),f(f_) {} + domain_type domain() const { return a.domain(); } + size_t dim0() const { return a.dim0();} + size_t dim1() const { return a.dim1();} + template value_type operator() (Args const & ... args) const { return f(a(args...)); } + //value_type operator[] ( typename domain_type::index_value_type const & key) const { return f(a[key]); } + friend std::ostream & operator<<(std::ostream & out, m_result const & x){ return out<<"lazy matrix resulting of a mapping";} + }; + + template class m_result >::type> : TRIQS_MODEL_CONCEPT(ImmutableVector) { + public: + typedef typename std::result_of::type value_type; + typedef typename A::domain_type domain_type; + A const & a; F f; + m_result(F const & f_, A const & a_):a(a_),f(f_) {} + domain_type domain() const { return a.domain(); } + size_t size() const { return a.size();} + template value_type operator() (Args const & ... args) const { return f(a(args...)); } + //value_type operator[] ( typename domain_type::index_value_type const & key) const { return f(a[key]); } + value_type operator() ( size_t i) const { return f(a(i)); } + friend std::ostream & operator<<(std::ostream & out, m_result const & x){ return out<<"lazy matrix resulting of a mapping";} + }; + + + template struct result; + template struct result { typedef m_result type;}; + + template< class A > m_result operator()(A const & a) const { + //static_assert( (ImmutableArray::value), "map : A does not model ImmutableArray"); + return m_result(f,a); + } + + friend std::ostream & operator<<(std::ostream & out, map_impl const & x){ return out<<"map("<<"F"<<")";} + }; + + // ----------- // TO DO : make this with preprocessor .... + template class map_impl { + F f; + public : + map_impl(F const & f_, bool):f(f_) {} + map_impl(F && f_, bool):f(f_) {} + map_impl(map_impl const &) = default; + //map_impl(map_impl &&) = default; + + template class m_result : TRIQS_MODEL_CONCEPT(ImmutableArray) { + static_assert( (std::is_same::value), "type mismatch"); + public: + typedef typename std::result_of::type value_type; + typedef typename A::domain_type domain_type; + A const & a; B const & b; F f; + m_result(F const & f_, A const & a_, B const & b_):a(a_),b(b_),f(f_) { + if (a.domain() != b.domain()) TRIQS_RUNTIME_ERROR<<"map2 : domain mismatch"; + } + domain_type domain() const { return a.domain(); } + template value_type operator() (Args const & ... args) const { return f(a(args...),b(args...)); } + //value_type operator[] ( typename domain_type::index_value_type const & key) const { return f(a[key],b[key]); } + friend std::ostream & operator<<(std::ostream & out, m_result const & x){ return out<<"lazy matrix resulting of a mapping";} + }; + + template struct result; + template struct result { typedef m_result type;}; + + template< class A, class B > m_result operator()(A const & a, B const & b) { + static_assert( (ImmutableArray::value), "map1 : A does not model ImmutableArray"); + static_assert( (ImmutableArray::value), "map1 : B does not model ImmutableArray"); + return m_result(f,a,b); + } + + friend std::ostream & operator<<(std::ostream & out, map_impl const & x){ return out<<"map("<<"F"<<")";} + }; +}}//namespace triqs::arrays +#endif + diff --git a/triqs/arrays/h5.hpp b/triqs/arrays/h5.hpp new file mode 100644 index 00000000..c22c5727 --- /dev/null +++ b/triqs/arrays/h5.hpp @@ -0,0 +1,24 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_H5_H +#define TRIQS_ARRAYS_H5_H +#include "./h5/simple_read_write.hpp" +#endif diff --git a/triqs/arrays/h5/array_proxy.hpp b/triqs/arrays/h5/array_proxy.hpp new file mode 100644 index 00000000..66c6e17e --- /dev/null +++ b/triqs/arrays/h5/array_proxy.hpp @@ -0,0 +1,130 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_HDF5_ARRAY_PROXY_H +#define TRIQS_ARRAYS_HDF5_ARRAY_PROXY_H +#include "./array_proxy_impl.hpp" + +namespace triqs { namespace arrays { + namespace h5 { + + /// The array proxy + template + class array_proxy : TRIQS_MODEL_CONCEPT(ImmutableCuboidArray), // WRONG ! IT does not yet implement [ ] + public sliceable_object < ValueType, + h5::index_system, + array_proxy_option, + Tag::h5_array_proxy, + ViewFactory, + indexmaps::slicer, + array_proxy > + { + public : + typedef ValueType value_type; + typedef std::pair< boost::shared_ptr ,std::string> storage_type; + static const bool T_is_complex = boost::is_complex::value; + typedef index_system< Rank, Rank_f> indexmap_type; + static const unsigned int rank = Rank; + + /// Opens a proxy on an existing array. The dataset must exists + template< class FileGroupType > + array_proxy ( FileGroupType file_group, std::string const & name) : + indexmap_ ( indexmap_type(file_group.openDataSet( name.c_str() ).getSpace(),T_is_complex) ) { + if (!h5::exists(file_group, name)) TRIQS_RUNTIME_ERROR<< " h5 : no dataset"<< name << " in file "; + storage_ = std::make_pair( boost::make_shared(file_group),name); + DataSet dataset = file_group.openDataSet( name.c_str() ); + try { if (T_is_complex) write_string_attribute(&dataset,"__complex__","1"); } + catch (...) {} // catch if the attribute already exists... + } + + /// Constructs a proxy on a new data set of the dimension of the domain D. The data must not exist. + template< class FileGroupType, class LengthType > + array_proxy ( FileGroupType file_group, std::string const & name_, LengthType L, bool overwrite = false) : + indexmap_ ( indexmap_type (L) ) + { + if (h5::exists(file_group, name_)) { + if (overwrite) file_group.unlink(name_.c_str()); + else TRIQS_RUNTIME_ERROR<< " h5 : dataset"<< name_ << " already exists in the file "; + } + storage_ = std::make_pair( boost::make_shared(file_group),name_); + DataSpace ds = indexmap_.template dataspace(); //(indexmap_type::rank_full, &indexmap_.lengths()[0], &indexmap_.strides()[0] ); + DataSet dataset = file_group.createDataSet( name_.c_str(), data_type_file(ValueType()), ds); + if (T_is_complex) write_string_attribute(&dataset,"__complex__","1"); + } + + /// Shallow copy + array_proxy(const array_proxy & X):indexmap_(X.indexmap()),storage_(X.storage_){} + + /// for slice construction + array_proxy (const indexmap_type & IM, const storage_type & ST): indexmap_(IM),storage_(ST){ } + + public: + indexmap_type const & indexmap() const {return indexmap_;} + storage_type const & storage() const {return storage_;} + storage_type & storage() {return storage_;} + const H5::CommonFG * file_group() const { return storage_.first.get();} + std::string const & name() const { return storage_.second;} + + typedef typename indexmap_type::domain_type domain_type; + domain_type const & domain() const { return indexmap_.domain();} + + typedef typename domain_type::index_value_type shape_type; + shape_type const & shape() const { return domain().lengths();} + + size_t num_elements() const { return domain().number_of_elements();} + bool is_empty() const { return this->num_elements()==0;} + + template< typename ISP>// put in the file... + void operator=(ISP const & X) { + try { + BOOST_AUTO(C, make_const_cache(X, Option::C())); + //typename result_of::cache::type C(X); + DataSet dataset = file_group()->openDataSet( name().c_str() ); + dataset.write( h5::data(C.view()), h5::data_type_mem(C.view()),h5::data_space(C.view()),indexmap().template dataspace()); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + + template // from the file to the array or the array_view... + friend void triqs_arrays_assign_delegation (LHS & lhs, array_proxy const & rhs) { + static_assert((is_amv_value_or_view_class::value), "LHS is not a value or a view class "); + h5::resize_or_check(lhs, rhs.indexmap().domain().lengths()); + try { + DataSet dataset = rhs.file_group()->openDataSet( rhs.name().c_str() ); + BOOST_AUTO(C, make_cache(lhs, Option::C() )); + //typename result_of::cache::type C(lhs); + dataset.read( h5::data(C.view()), h5::data_type_mem(C.view()), h5::data_space(C.view()), + rhs.indexmap().template dataspace() ); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + + protected: + indexmap_type indexmap_; + storage_type storage_; + + }; + }// namesapce h5 + + template < class V, int R, int Rf > + struct ViewFactory< V, R, h5::array_proxy_option, Tag::h5_array_proxy > { typedef h5::array_proxy type; }; +}} +#endif + diff --git a/triqs/arrays/h5/array_proxy_impl.hpp b/triqs/arrays/h5/array_proxy_impl.hpp new file mode 100644 index 00000000..5792c089 --- /dev/null +++ b/triqs/arrays/h5/array_proxy_impl.hpp @@ -0,0 +1,160 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_HDF5_ARRAY_PROXY_IMPL_H +#define TRIQS_ARRAYS_HDF5_ARRAY_PROXY_IMPL_H +//#define TRIQS_ARRAYS_DEBUG_H5_SLICE + +#include "../indexmaps/cuboid/domain.hpp" +#include "./group_or_file.hpp" +#include "../impl/sliceable_object.hpp" +#include "../impl/tuple_tools.hpp" +#include +#include + +namespace triqs { namespace arrays { + + namespace h5 { template struct array_proxy_option {}; } + + namespace Option { + template struct Im_Opt_2_Opt > { typedef h5::array_proxy_option type;}; + } + + namespace h5 { + + template + class index_system { + + public : + static const unsigned int rank= Rank, rank_full = Rank_full; + typedef mini_vector v_type; + typedef mini_vector v_type_full; + typedef indexmaps::cuboid::domain domain_type; + domain_type const & domain() const { return mydomain;} + + index_system (v_type_full const & total_lengths_) { + total_lens_ = total_lengths_; lens_= total_lengths_; + for (size_t i =0; i DataSpace dataspace() const { return h5::dataspace_from_LS (total_lens_, lens_,stri_,off_); } + size_t size() const { size_t _size = 1; for (size_t i =0; i total_lengths() const { return this->total_lens_;} + mini_vector lengths() const { return this->lens_;} + mini_vector strides() const { return this->stri_;} + + private: + mini_vector lens_, off_, stri_; + v_type dims; + v_type_full total_lens_; + domain_type mydomain; + }; + + namespace slicer_impl { + + template inline void _check_BC ( int N, int ind, size_t B) { } + template <> inline void _check_BC (int N, int ind, size_t B) { + bool cond = (ind >= 0) && (ind < int(B)); // fix this int ... + if (!cond) TRIQS_ARRAYS_KEY_ERROR << " index "< struct slice_calc { + + typedef mini_vector const & i_type; + typedef mini_vector & o_type; + typedef mini_vector & os_type; + + template< typename ArgsTuple> + static void invoke(i_type li, i_type si, os_type lo_c, o_type lo, o_type so, o_type offset, ArgsTuple const & args ) { + const int dP = boost::is_base_of::type, range >::type::value ; + one_step(li[N], si[N],lo[N],so[N], offset[N] ,boost::tuples::get(args)); + lo_c[P] = lo[N]; + slice_calc::invoke(li,si,lo_c,lo,so, offset, args); + } + + static void one_step(size_t li, size_t si, size_t & lo, size_t & so, size_t & offset, size_t R){ + _check_BC (N, R, li); + offset = R; lo =1; so= 1; + } + + static void one_step(size_t li, size_t si, size_t & lo, size_t & so, size_t & offset, range R){ + _check_BC (N, R.first(),li); + _check_BC (N, (R.last()==-1 ? li : R.last()) -1 ,li); + lo = ((R.last()==-1 ? li : R.last()) - R.first() + R.step()-1 )/R.step() ; // python behaviour + so = R.step(); offset = R.first() ; + } + }; + // stop the recursion + template struct slice_calc : slice_calc { + template static void invoke(T1,T2,T3,T4,T5,T6,T7 ) {} + }; + + }//namespace slicer_impl + } // h5 + + namespace indexmaps { + + template + struct slicer < h5::index_system, ArgsTuple> { + + static const unsigned int len = boost::tuples::length::value; + static_assert(len>=R, "Too few arguments in slice"); + static_assert(len<=R, "Too many arguments in slice"); + static_assert( (R==Rf), "Can not slice array_proxy twice (not implemented)"); + + static const unsigned int R2 = R - TupleTools::CountHowManyInt::value; + typedef h5::index_system< R2, Rf> return_type; + + static return_type invoke ( h5::index_system const & X, ArgsTuple args) { + mini_vector newdims; + mini_vector newoffset, newlengths, newstrides; + h5::slicer_impl::slice_calc::invoke(X.lengths(),X.strides(),newdims, newlengths,newstrides, newoffset, args); +#ifdef TRIQS_ARRAYS_DEBUG_H5_SLICE + std::cerr<<"-----------------------------------------------"< struct slicer < h5::index_system, boost::tuple<> > { typedef h5::index_system< R,Rf> return_type;}; + } + +}} +#endif + diff --git a/triqs/arrays/h5/array_stack.hpp b/triqs/arrays/h5/array_stack.hpp new file mode 100644 index 00000000..aa290fa3 --- /dev/null +++ b/triqs/arrays/h5/array_stack.hpp @@ -0,0 +1,157 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_H5_STACK_H +#define TRIQS_ARRAYS_H5_STACK_H +#include "../array.hpp" +#include +#include "./simple_read_write.hpp" + +namespace triqs { namespace arrays { + + namespace h5_stack_details { // to be replaced by ellipsis + template array_view slice0( array & A, size_t ind); +#define AUX(z,p,unused) BOOST_PP_COMMA_IF(p) range() +#define IMPL(z, NN, unused) \ + template array_view slice0( array & A, size_t ind) {\ + return A(ind,BOOST_PP_REPEAT(BOOST_PP_INC(NN),AUX,nil));} + BOOST_PP_REPEAT(ARRAY_NRANK_MAX , IMPL, nil); +#undef IMPL +#undef AUX + template T & slice0( array & A, size_t ind) { return A(ind);} + + template struct get_value_type { typedef B type; static const size_t rank = 0;}; + template struct get_value_type >::type > { + typedef typename B::value_type type;static const size_t rank = B::rank;}; + + } + + /** + * \brief Hdf5 array stack + * \tparam BaseElementType The type of the base element of the stack. Can be an array/matrix/vector or a scalar. + * If it in a scalar, the array_stack will write an hdf5 array of dimension 1 + * If it in an array/matrix/vector, the array_stack will write an hdf5 array of dimension BaseElementType::rank +1 + * + */ + template< typename BaseElementType> + class array_stack { + typedef BaseElementType base_element_type; + static_assert( (is_amv_value_class::value || is_scalar::value), "BaseElementType must be an array/matrix/vector or a simple number"); + typedef typename h5_stack_details::get_value_type::type T; + static const size_t dim = h5_stack_details::get_value_type::rank; + static const bool base_is_array = dim >0; + size_t bufsize_, step, _size; + static const bool T_is_complex = boost::is_complex::value; + static const unsigned int RANK = dim + 1 + (T_is_complex ? 1 : 0); + utility::mini_vector dims, offset, maxdims, dim_chunk, buffer_dim, zero; + H5::DataSet dataset; + array buffer; + + template + void construct_delegate ( FileGroupType g, std::string const & name, mini_vector const & a_dims, size_t bufsize) { + mini_vector dim_chunk; + bufsize_ = bufsize; step = 0; _size =0; + for (size_t i =1; i<=dim; ++i) { dims[i] = a_dims[i-1];} + if (T_is_complex) { dims[RANK-1] =2; } + maxdims = dims; buffer_dim = dims; dim_chunk = dims; + dims[0] = 0; maxdims[0] = H5S_UNLIMITED; dim_chunk[0]=1; buffer_dim[0] = bufsize_; + mini_vector s; for (size_t i =0; i<=dim; ++i) {s[i] = buffer_dim[i];} + buffer.resize(s); + H5::DataSpace mspace1( RANK, dims.ptr(), maxdims.ptr()); + H5::DSetCreatPropList cparms; cparms.setChunk( RANK, dim_chunk.ptr() ); // Modify dataset creation properties, i.e. enable chunking. + try { + dataset = g.create_dataset(name,h5::native_type_from_C(typename h5::remove_complex::type()), mspace1, cparms ); + if (boost::is_complex::value) h5::write_string_attribute(&dataset,"__complex__","1"); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + + public : + + /** + * \brief Constructor + * \param g The h5 file or group, of type FileGroupType + * \param name The name of the hdf5 array in the file/group where the stack will be stored + * \param base_element_shape The shape of the base array/matrix/vector [or mini_vector() for a scalar] + * \param bufsize The size of the bufferThe name of the hdf5 array in the file/group where the stack will be stored + * \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with stackstrace, cf doc). + */ + template + array_stack( FileGroupType g, std::string const & name, mini_vector const & base_element_shape, size_t bufsize) { + construct_delegate ( g, name, base_element_shape, bufsize); + } + + /** + * \brief Constructor : valid only if the base is a scalar + * \param g The h5 file or group, of type FileGroupType + * \param name The name of the hdf5 array in the file/group where the stack will be stored + * \param bufsize The size of the bufferThe name of the hdf5 array in the file/group where the stack will be stored + * \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with stackstrace, cf doc). + */ + template + array_stack( FileGroupType g, std::string const & name, size_t bufsize) { + static_assert( (is_scalar::value), "This constructor is only available for a scalar BaseElementType"); + construct_delegate ( g, name,mini_vector() , bufsize); + } + + /// + ~array_stack() {flush();} + + /// The type of the base of the stack (a view or a reference) + typedef typename boost::mpl::if_c< base_is_array , array_view, T &>::type slice_type; + + /** + * \return A view (for an array/matrix/vector base) or a reference (for a scalar base) to the top of the stack + * i.e. the next element to be assigned to + */ + slice_type operator() () { return h5_stack_details::slice0(buffer, step); } + + /// Advance the stack by one + void operator++() { ++step; ++_size; if (step==bufsize_) flush(); } + + /// Flush the buffer to the disk. Automatically called at destruction. + void flush() { save_buffer(); step=0;} + + /** + * \brief Add a element onto the stack and advance it by one. + * S << A is equivalent to S() = A; ++S; + */ + template void operator << ( AType const & A) { (*this)() = A; ++(*this);} + + /// Current size of the stack + size_t size() const { return _size;} + + private: + void save_buffer () { + if (step==0) return; + dims[0] += step; + buffer_dim[0] = step; + dataset.extend(dims.ptr()); + H5::DataSpace fspace1 = dataset.getSpace (), mspace = h5_impl::data_space(buffer); + fspace1.selectHyperslab( H5S_SELECT_SET, buffer_dim.ptr(), offset.ptr() ); + mspace.selectHyperslab( H5S_SELECT_SET, buffer_dim.ptr(), zero.ptr() ); + try { dataset.write( h5_impl::get_array_data_ptr(buffer), h5::data_type_memory(), mspace, fspace1 ); } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + offset [0] += step; + } + }; +}} // namespace +#endif + diff --git a/triqs/arrays/h5/common.hpp.old b/triqs/arrays/h5/common.hpp.old new file mode 100644 index 00000000..42016769 --- /dev/null +++ b/triqs/arrays/h5/common.hpp.old @@ -0,0 +1,230 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_H5_COMMON_H +#define TRIQS_ARRAYS_H5_COMMON_H + +#include +#include "hdf5_hl.h" +#include "../cache.hpp" +#include +#include + +template std::string get_triqs_hdf5_data_scheme(T const & ) { return "";} + +namespace triqs { namespace arrays { namespace h5 { + using namespace H5; + // conversion of C type to HDF5 native + inline PredType native_type_from_C(char) { return PredType::NATIVE_CHAR; } + inline PredType native_type_from_C(signed char) { return PredType::NATIVE_SCHAR; } + inline PredType native_type_from_C(unsigned char) { return PredType::NATIVE_UCHAR; } + inline PredType native_type_from_C(short) { return PredType::NATIVE_SHORT; } + inline PredType native_type_from_C(unsigned short) { return PredType::NATIVE_USHORT; } + inline PredType native_type_from_C(int) { return PredType::NATIVE_INT; } + inline PredType native_type_from_C(unsigned) { return PredType::NATIVE_UINT; } + inline PredType native_type_from_C(long) { return PredType::NATIVE_LONG; } + inline PredType native_type_from_C(unsigned long) { return PredType::NATIVE_ULONG; } + inline PredType native_type_from_C(long long) { return PredType::NATIVE_LLONG; } + inline PredType native_type_from_C(unsigned long long) { return PredType::NATIVE_ULLONG; } + inline PredType native_type_from_C(float) { return PredType::NATIVE_FLOAT; } + inline PredType native_type_from_C(double) { return PredType::NATIVE_DOUBLE; } + inline PredType native_type_from_C(long double) { return PredType::NATIVE_LDOUBLE; } + inline PredType native_type_from_C(bool) { return PredType::NATIVE_SCHAR; } + inline PredType native_type_from_C(std::string) { return PredType::C_S1; } + + // conversion of C type to HDF5 native + // NEED TO CHANGE THIS ? It is not standard... We should fix a standard or have a trait + inline PredType h5_type_from_C(char) { return PredType::NATIVE_CHAR; } + inline PredType h5_type_from_C(signed char) { return PredType::NATIVE_SCHAR; } + inline PredType h5_type_from_C(unsigned char) { return PredType::NATIVE_UCHAR; } + inline PredType h5_type_from_C(short) { return PredType::NATIVE_SHORT; } + inline PredType h5_type_from_C(unsigned short) { return PredType::NATIVE_USHORT; } + inline PredType h5_type_from_C(int) { return PredType::NATIVE_INT; } + inline PredType h5_type_from_C(unsigned) { return PredType::NATIVE_UINT; } + inline PredType h5_type_from_C(long) { return PredType::NATIVE_LONG; } + inline PredType h5_type_from_C(unsigned long) { return PredType::NATIVE_ULONG; } + inline PredType h5_type_from_C(long long) { return PredType::NATIVE_LLONG; } + inline PredType h5_type_from_C(unsigned long long) { return PredType::NATIVE_ULLONG; } + inline PredType h5_type_from_C(float) { return PredType::NATIVE_FLOAT; } + inline PredType h5_type_from_C(double) { return PredType::NATIVE_DOUBLE; } + inline PredType h5_type_from_C(long double) { return PredType::NATIVE_LDOUBLE; } + inline PredType h5_type_from_C(bool) { return PredType::NATIVE_SCHAR; } + inline PredType h5_type_from_C(std::string) { return PredType::C_S1; } + + // If it is complex return T else T + template struct remove_complex { typedef T type;}; + template struct remove_complex > { typedef T type;}; + + template + PredType data_type_mem ( ArrayType const & A) { + return native_type_from_C(typename remove_complex::type()); + } + + template + PredType data_type_mem_scalar ( S const & A) { + return native_type_from_C(typename remove_complex::type()); + } + + // the type of data to put in the file_or_group + template + PredType data_type_file ( V const & ) { return h5_type_from_C(typename remove_complex::type());} + + // the pointer on the start of data + template + TYPE_DISABLE_IF ( void *, boost::is_complex ) + data ( ArrayType const & A) { return &(A.storage()[0]);} + + template + TYPE_ENABLE_IF ( void *, boost::is_complex ) + data ( ArrayType const & A) { + typedef typename ArrayType::value_type::value_type T; + std::complex * p = &(A.storage()[0]); + return reinterpret_cast(p); + } + + // dataspace from lengths and strides. Correct for the complex. strides must be >0 + template + H5::DataSpace dataspace_from_LS ( + mini_vector const & Ltot, + mini_vector const & L, + mini_vector const & S, + mini_vector const & offset = mini_vector() ) { +#ifdef TRIQS_ARRAYS_DEBUG_H5_SLICE + std::cerr << "total lens in dataspace_from_LS"<< Ltot.to_string() << std::endl ; + std::cerr << "lens in dataspace_from_LS"<< L.to_string() << std::endl ; + std::cerr << "Strides in dataspace_from_LS "<< S.to_string() << std::endl ; + std::cerr << "offset in dataspace_from_LS"<< offset.to_string() << std::endl ; +#endif + static const unsigned int rank = R + (IsComplex ? 1 : 0); + hsize_t totdimsf[rank], dimsf [rank], stridesf[rank], offsetf[rank]; // dataset dimensions + for (size_t u=0; u + H5::DataSpace data_space ( ArrayType const & A) { + static const unsigned int R = ArrayType::rank; + mini_vector S; + mini_vector const & S1 ( A.indexmap().strides() ); + for (size_t u=0; u::value; + return dataspace_from_LS ( A.indexmap().domain().lengths(),A.indexmap().domain().lengths(), S); + } + + /******************** resize or check the size ****************************************************/ + + template ENABLE_IF(is_amv_value_class) + resize_or_check ( A & a, mini_vector const & dimsf ) { a.resize( indexmaps::cuboid::domain_t( dimsf)); } + + template ENABLE_IF(is_amv_view_class) + resize_or_check ( A const & a, mini_vector const & dimsf ) { + if (a.indexmap().domain().lengths() != dimsf) TRIQS_RUNTIME_ERROR<<"Dimension error : the view can not be resized : " + << "\n in file : "<< dimsf.to_string() + << "\n in view : "<createAttribute(name.c_str(), strdatatype, attr_dataspace); + //myatt_in.write(strdatatype, strwritebuf); + myatt_in.write(strdatatype, (void *)(value.c_str())); + } + + /****************** Read string attribute *********************************************/ + + /// Return the attribute name of obj, and "" if the attribute does not exist. + inline std::string read_string_attribute (H5::H5Object const * obj, std::string name ) { + std::string value =""; + Attribute attr; + if (H5LTfind_attribute(obj -> getId(), name.c_str() )==0) return value;// not present + // can not find how to get the size with hl. Using full interface + //herr_t err2 = H5LTget_attribute_string(gr.getId(), x.c_str(), name.c_str() , &(buf.front()) ) ; + //if (err2 < 0) TRIQS_RUNTIME_ERROR << "Reading a string attribute and got rank !=0"; + //value.append( &(buf.front()) ); + try { attr= obj->openAttribute(name.c_str());} + catch (H5::AttributeIException) { return value;} + try { + DataSpace dataspace = attr.getSpace(); + int rank = dataspace.getSimpleExtentNdims(); + if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string attribute and got rank !=0"; + size_t size = attr.getStorageSize(); + StrType strdatatype(PredType::C_S1, size); + std::vector buf(size+1, 0x00); + attr.read(strdatatype, (void *)(&buf[0])); + value.append( &(buf.front()) ); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + return value; + } + + /****************** Read/Write the special TRIQS_HDF5_data_scheme attribute *********************************************/ + + template + inline void write_triqs_hdf5_data_scheme( H5::Group g, T const & obj) { + write_string_attribute( &g, "TRIQS_HDF5_data_scheme" , get_triqs_hdf5_data_scheme(obj).c_str() ) ; + // herr_t err = H5LTset_attribute_string(F.getId(), subgroup_name.c_str(), "TRIQS_HDF5_data_scheme" , get_triqs_hdf5_data_scheme(p).c_str() ) ; + } + + inline std::string read_triqs_hdf5_data_scheme( H5::Group g) { return read_string_attribute( &g, "TRIQS_HDF5_data_scheme") ; } + + + /****************** WRITE attribute *********************************************/ + + //inline void write_triqs_data_scheme ( H5::H5Object const & grp, std::string obj_name, std::string attr_name, std::string triqs_data_scheme ) { + // herr_t err = H5LTset_attribute_string(grp.getId(),obj_name.c_str(),attr_name.c_str(), , value.c_str() ) ; + // if (err<0) TRIQS_RUNTIME_ERROR << "Error in setting attribute "<< name << " to " << value; + // } + + + +}}} +#endif diff --git a/triqs/arrays/h5/simple_read_write.hpp b/triqs/arrays/h5/simple_read_write.hpp new file mode 100644 index 00000000..88fd3c01 --- /dev/null +++ b/triqs/arrays/h5/simple_read_write.hpp @@ -0,0 +1,193 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_H5_LOWLEVEL_H +#define TRIQS_ARRAYS_H5_LOWLEVEL_H +#include +#include +#include +#include "../cache.hpp" + +namespace triqs { namespace arrays { + namespace h5_impl { + + template const void * get_array_data_cptr ( array_view const & A) { return h5::get_data_ptr(&(A.storage()[0]));} + template const void * get_array_data_cptr ( array const & A) { return h5::get_data_ptr(&(A.storage()[0]));} + //template void * get_array_data_ptr ( array_view & A) { return h5::get_data_ptr(&(A.storage()[0]));} + //template void * get_array_data_ptr ( array & A) { return h5::get_data_ptr(&(A.storage()[0]));} + + template ENABLE_IF(is_amv_value_or_view_class) * + get_array_data_ptr (A & x) { return h5::get_data_ptr(&(x.storage()[0]));} + + // the dataspace corresponding to the array. Contiguous data only... + template + H5::DataSpace data_space ( ArrayType const & A) { + static const unsigned int R = ArrayType::rank; + mini_vector S; + mini_vector const & S1 ( A.indexmap().strides() ); + for (size_t u=0; u::value; + return h5::dataspace_from_LS ( A.indexmap().domain().lengths(),A.indexmap().domain().lengths(), S); + } + + /******************** resize or check the size ****************************************************/ + + template ENABLE_IF(is_amv_value_class) + resize_or_check ( A & a, mini_vector const & dimsf ) { a.resize( indexmaps::cuboid::domain_t( dimsf)); } + + template ENABLE_IF(is_amv_view_class) + resize_or_check ( A const & a, mini_vector const & dimsf ) { + if (a.indexmap().domain().lengths() != dimsf) TRIQS_RUNTIME_ERROR<<"Dimension error : the view can not be resized : " + << "\n in file : "<< dimsf.to_string() + << "\n in view : "< + void write_array (h5::group g, std::string const & name, array_view const & A, bool C_reorder = true) { + static_assert( !std::is_base_of::value, " Not implemented");// 1d is below + if (C_reorder) { write_array(g,name, make_const_cache(A).view(),false); return; } + try { + H5::DataSet ds = g.create_dataset(name, h5::data_type_file(), data_space(A) ); + ds.write( get_array_data_cptr(A), h5::data_type_memory(), data_space(A) ); + // if complex, to be python compatible, we add the __complex__ attribute + if (boost::is_complex::value) h5::write_string_attribute(&ds,"__complex__","1"); + } + TRIQS_ARRAYS_H5_CATCH_EXCEPTION; + } + + template + void write_array (h5::group g, std::string const & name, array const & A, bool C_reorder = true) { write_array(g,name,A(),C_reorder);} + + /*********************************** READ array ****************************************************************/ + /** + * \brief Read an array or a view from an hdf5 file + * \tparam ArrayType The type of the array/matrix/vector, etc.. + * \param f The h5 file or group of type H5::H5File or H5::Group + * \param name The name of the hdf5 array in the file/group where the stack will be stored + * \param A The array to be stored + * \param C_reorder bool If true [default] the data will be stored in C order in the hdf5, hence making a temporary + * cache of the data to reorder them in memory. If false, the array is stored as it [if you know what you are doing] + * \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc). + */ + template + void read_array (h5::group g, std::string const & name, ArrayType & A, bool C_reorder = true) { + static_assert( !std::is_base_of::value, " Not implemented");// 1d is below + typedef typename ArrayType::value_type V; + try { + H5::DataSet ds = g.open_dataset(name); + H5::DataSpace dataspace = ds.getSpace(); + static const unsigned int Rank = ArrayType::rank + (boost::is_complex::value ? 1 : 0); + int rank = dataspace.getSimpleExtentNdims(); + if (rank != Rank) TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : the array has rank = " + <"; + return fs.str(); + } + + /** + * \brief Read an array or a view from an hdf5 file + * \tparam ArrayType The type of the array/matrix/vector, etc.. + * \param fg The h5 file or group of type H5::H5File or H5::Group + * \param name The name of the hdf5 array in the file/group where the stack will be stored + * \param A The array to be stored + * \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc). + */ + template + //ENABLE_IF(is_amv_value_or_view_class) + ENABLE_IFC(is_amv_value_or_view_class::value && has_scalar_or_string_value_type::value) + h5_read (h5::group fg, std::string const & name, ArrayType & A) { h5_impl::read_array(fg,name, A);} + + /** + * \brief Write an array or a view into an hdf5 file + * \tparam ArrayType The type of the array/matrix/vector, etc.. + * \param fg The h5 file or group of type H5::H5File or H5::Group + * \param name The name of the hdf5 array in the file/group where the stack will be stored + * \param A The array to be stored + * \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc). + */ + template + //ENABLE_IF(is_amv_value_or_view_class) + ENABLE_IFC(is_amv_value_or_view_class::value && has_scalar_or_string_value_type::value) + h5_write (h5::group fg, std::string const & name, ArrayType const & A) { h5_impl::write_array(fg,name, array_view(A));} + +}} +#endif + diff --git a/triqs/arrays/impl/assignment.hpp b/triqs/arrays/impl/assignment.hpp new file mode 100644 index 00000000..872e0e12 --- /dev/null +++ b/triqs/arrays/impl/assignment.hpp @@ -0,0 +1,179 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_ASSIGN2_H_ +#define TRIQS_ARRAYS_ASSIGN2_H_ +#include "iterator_adapter.hpp" +#include "../indexmaps/cuboid/foreach.hpp" +#include "../storages/memcopy.hpp" + +// two ways of doing things... optimal one depends on compiler ? To be checked... +#define TRIQS_ARRAYS_ASSIGN_ISP_WITH_FOREACH + +namespace triqs { namespace arrays { + + namespace assignment { template struct impl; } + + // puts the contents of RHS into LHS. LHS must be an indexmap_storage_pair + // it is specialized in various cases for optimisation. + template + void triqs_arrays_assign_delegation (LHS & lhs, const RHS & rhs ) { assignment::impl(lhs,rhs).invoke();} + + template + void triqs_arrays_compound_assign_delegation (LHS & lhs, const RHS & rhs, mpl::char_ ) { assignment::impl(lhs,rhs).invoke();} + +#define TRIQS_DEFINE_COMPOUND_OPERATORS(MYTYPE)\ + template MYTYPE & operator +=(RHS const & rhs) { triqs_arrays_compound_assign_delegation (*this,rhs, mpl::char_<'A'>()); return *this;}\ + template MYTYPE & operator -=(RHS const & rhs) { triqs_arrays_compound_assign_delegation (*this,rhs, mpl::char_<'S'>()); return *this;}\ + template MYTYPE & operator *=(RHS const & rhs) { triqs_arrays_compound_assign_delegation (*this,rhs, mpl::char_<'M'>()); return *this;}\ + template MYTYPE & operator /=(RHS const & rhs) { triqs_arrays_compound_assign_delegation (*this,rhs, mpl::char_<'D'>()); return *this;} + +#define TRIQS_DELETE_COMPOUND_OPERATORS(MYTYPE)\ + template MYTYPE & operator +=(RHS const & rhs) = delete;\ + template MYTYPE & operator -=(RHS const & rhs) = delete;\ + template MYTYPE & operator *=(RHS const & rhs) = delete;\ + template MYTYPE & operator /=(RHS const & rhs) = delete; + + // -------- IMPLEMENTATION ---------------------------- + + namespace assignment { + + template struct _ops_; + template struct _ops_ { static void invoke (A & a, B const & b) { a =b;} }; + template struct _ops_ { static void invoke (A & a, B const & b) { a+=b;} }; + template struct _ops_ { static void invoke (A & a, B const & b) { a-=b;} }; + template struct _ops_ { static void invoke (A & a, B const & b) { a*=b;} }; + template struct _ops_ { static void invoke (A & a, B const & b) { a/=b;} }; + + // RHS is considered to be an indexmap_storage_pair if it is one, ... except if it is the scalar type of hte LHS + // think about an Array< Array > e.g. + template struct is_isp : + std::integral_constant::value && (!is_scalar_for::value) > {}; + +#define TRIQS_REJECT_ASSIGN_TO_CONST \ + static_assert( (!std::is_const::value ), "Assignment : The value type of the LHS is const and can not be assigned to !"); +#define TRIQS_REJECT_MATRIX_COMPOUND_MUL_DIV_NON_SCALAR\ + static_assert( (!((OP=='M' || OP=='D') && MutableMatrix::value && (!is_scalar_for::value))),\ + "*= and /= operator for non scalar RHS are deleted for a type modeling MutableMatrix (e.g. matrix, matrix_view) matrix, because this is ambiguous"); + + // ----------------- standard assignment for indexmap_storage_pair -------------------------------------------------- + template + struct impl) > { + TRIQS_REJECT_ASSIGN_TO_CONST; + TRIQS_REJECT_MATRIX_COMPOUND_MUL_DIV_NON_SCALAR; + + typedef typename LHS::value_type value_type; + typedef typename LHS::indexmap_type indexmap_type; + typedef typename indexmap_type::domain_type::index_value_type index_value_type; + LHS & lhs; const RHS & rhs; + typedef typename std::remove_cv::type v_t; + impl(LHS & lhs_, const RHS & rhs_): lhs(lhs_), rhs(rhs_) {} + + template void operator()(Args const & ... args) const { + // void operator()(value_type & p, index_value_type const & key) { + _ops_::type, typename RHS::value_type, OP>::invoke(lhs(args...), rhs(args...)) ;} + + void invoke () { +#ifdef TRIQS_ARRAYS_DEBUG + if (!indexmaps::compatible_for_assignment(lhs.indexmap(), rhs.indexmap())) TRIQS_RUNTIME_ERROR<< "Size mismatch in operation "< + +namespace boost { namespace serialization { class access;}} + +#define TRIQS_ARRAYS_THROW(s) { TRIQS_RUNTIME_ERROR< typename A::view_type make_view(A const & x) { return typename A::view_type(x);} + + /// Makes a clone + template typename A::non_view_type make_clone(A const & x) { return typename A::non_view_type(x);} + + namespace arrays { + using triqs::make_clone; + + /// Is the data contiguous + template typename boost::disable_if,bool>::type has_contiguous_data(A const &) {return false;} + template typename boost::enable_if,bool>::type has_contiguous_data(A const &) {return true;} + template typename boost::enable_if, bool>::type has_contiguous_data(A const & v){return v.indexmap().is_contiguous();} + + template< typename A> + typename boost::enable_if >::type + resize_or_check_if_view ( A & a, typename A::shape_type const & sha) { + if (a.shape()!=sha) TRIQS_RUNTIME_ERROR<< "Size mismatch : view class shape = "< + typename boost::enable_if >::type + resize_or_check_if_view ( A & a, typename A::shape_type const & sha) { if (a.shape()!=sha) a.resize(sha); } + }}//namespace triqs::arrays +#endif + diff --git a/triqs/arrays/impl/exceptions.hpp b/triqs/arrays/impl/exceptions.hpp new file mode 100644 index 00000000..0f6afbe6 --- /dev/null +++ b/triqs/arrays/impl/exceptions.hpp @@ -0,0 +1,48 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ + +#ifndef TRIQS_ARRAYS_EXCEPTIONS_H +#define TRIQS_ARRAYS_EXCEPTIONS_H + +#include +#include +#include +#include + +namespace triqs { namespace arrays { + + class key_error : public std::exception { + std::string acc; + public: + key_error() throw() :std::exception() {} + virtual ~key_error() throw() {} + template key_error & operator <<( T const & x) { std::stringstream f; f<. + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_FLAGS_H +#define TRIQS_ARRAYS_FLAGS_H +#include "../indexmaps/permutation.hpp" +namespace triqs { namespace arrays { + + typedef unsigned long long ull_t; + + // Flags is a 64 bit unsigned int. + // 0 is the default option. + // Meaning of the bits : + // 0 -> Boundcheck + // 1,2 -> Predefined order : + // 0 : None, 1 : C, 2 : Fortran + // 3,4 -> Init + // 0 : Noinit, 1 : NanInit, 2 : DefaultInit + + constexpr ull_t BoundCheck = 1ull << 0; + constexpr ull_t TraversalOrderC = 1ull << 1; + constexpr ull_t TraversalOrderFortran = 1ull << 2; + constexpr ull_t NanInit = 1ull << 3; + constexpr ull_t DefaultInit = 1ull << 4; + +#define BOUND_CHECK triqs::arrays::BoundCheck +#define TRAVERSAL_ORDER_C triqs::arrays::TraversalOrderC +#define TRAVERSAL_ORDER_FORTRAN triqs::arrays::TraversalOrderFortran +#define DEFAULT_INIT triqs::arrays::DefaultInit + + // NB : flags MUST be insensitive to slicing ... + // i.e. when I slice, the flags does not change. + + namespace flags { + +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + + constexpr ull_t get(ull_t f, ull_t a) { return ((f & (1ull<> a);} + constexpr ull_t get2(ull_t f, ull_t a) { return (f & (((1ull<> a) );} + +#ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK + constexpr bool bound_check (ull_t f) { return true;} +#else + constexpr bool bound_check (ull_t f) { return get (f, 0)!=0;} +#endif + + constexpr bool traversal_order_c (ull_t f) { return get (f,1ull)!=0ull;} + constexpr bool traversal_order_fortran (ull_t f) { return get (f,2ull)!=0ull;} + + template< ull_t F> struct bound_check_trait { static constexpr bool value = bound_check(F); }; + + constexpr ull_t init_mode (ull_t f) { return get2 (f,3);} + constexpr bool check_init_mode (ull_t f) { return get2 (f,3)!=3ull;} + + template struct init_tag1; + template<> struct init_tag1<0> { typedef Tag::no_init type;}; + template<> struct init_tag1<1> { typedef Tag::nan_inf_init type;}; + template<> struct init_tag1<2> { typedef Tag::default_init type;}; + + // for the init_tag, we pass the *whole* option flag. + template struct init_tag : init_tag1 < init_mode(F)> {}; + + template struct assert_make_sense { + static constexpr bool bc = bound_check(F);; + static constexpr bool is_c = traversal_order_c(F); + static constexpr bool is_f = traversal_order_fortran(F); + static constexpr bool inm = check_init_mode(F); + static_assert ( (!( is_c && is_f)), "You asked C and Fortran traversal order at the same time..."); + static_assert ( (!( (is_c || is_f) && To )), "You asked C or Fortran traversal order and gave a traversal order ..."); + static_assert ( (inm), "You asked nan and default init at the same time..."); + }; + +#else + +#define TRIQS_FLAGS_GET(f,a) ((f & (1ull<> a) +#define TRIQS_FLAGS_GET2(f,a) (f & (((1ull<> a)) + +#ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK + template< ull_t F> struct bound_check_trait { static constexpr bool value = true;}; +#else + template< ull_t F> struct bound_check_trait { static constexpr bool value = TRIQS_FLAGS_GET (F, 0)!=0; }; +#endif + + template< ull_t F> struct traversal_order_c { static constexpr bool value = TRIQS_FLAGS_GET(F,1) !=0; }; + template< ull_t F> struct traversal_order_fortran { static constexpr bool value = TRIQS_FLAGS_GET(F,2) !=0; }; + + template< ull_t F> struct init_mode_tr { static constexpr int value = TRIQS_FLAGS_GET(F,3); }; + + template struct init_tag1; + template<> struct init_tag1<0> { typedef Tag::no_init type;}; + template<> struct init_tag1<1> { typedef Tag::nan_inf_init type;}; + template<> struct init_tag1<2> { typedef Tag::default_init type;}; + template struct init_tag : init_tag1 < init_mode_tr::value > {}; + + template struct assert_make_sense { };// no check on icc +#undef TRIQS_FLAGS_GET +#undef TRIQS_FLAGS_GET2 +#endif + + } +}}//namespace triqs::arrays +#endif diff --git a/triqs/arrays/impl/indexmap_storage_pair.hpp b/triqs/arrays/impl/indexmap_storage_pair.hpp new file mode 100644 index 00000000..f1158f3d --- /dev/null +++ b/triqs/arrays/impl/indexmap_storage_pair.hpp @@ -0,0 +1,272 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAY_IMPL_INDEX_STORAGE_PAIR_H +#define TRIQS_ARRAY_IMPL_INDEX_STORAGE_PAIR_H +#include "./common.hpp" +#include "./flags.hpp" +#include "../storages/shared_block.hpp" +#include "./assignment.hpp" +#include "../indexmaps/cuboid/foreach.hpp" +#include "triqs/utility/exceptions.hpp" +#include "triqs/utility/typeid_name.hpp" +#include "triqs/utility/view_tools.hpp" +#include +#include +#include +#ifdef TRIQS_WITH_PYTHON_SUPPORT +#include "../python/numpy_extractor.hpp" +#include "../python/array_view_to_python.hpp" +#endif + +namespace triqs { namespace arrays { + + template class iterator_adapter; + + template < class V, int R, ull_t OptionFlags, ull_t TraversalOrder, class ViewTag > struct ViewFactory; + + template + class indexmap_storage_pair : Tag::indexmap_storage_pair, TRIQS_MODEL_CONCEPT(MutableArray) { + + public : + typedef typename StorageType::value_type value_type; + static_assert(std::is_constructible::value, "array/array_view and const operate only on values"); + //static_assert(!std::is_const::value, "no const type"); + typedef StorageType storage_type; + typedef IndexMapType indexmap_type; + static constexpr unsigned int rank = IndexMapType::domain_type::rank; + protected: + + indexmap_type indexmap_; + storage_type storage_; + + // ------------------------------- constructors -------------------------------------------- + + indexmap_storage_pair() {} + + indexmap_storage_pair (const indexmap_type & IM, const storage_type & ST): + indexmap_(IM),storage_(ST){ +#ifdef TRIQS_ARRAYS_CHECK_IM_STORAGE_COMPAT + if (ST.size() != IM.domain().number_of_elements()) + TRIQS_RUNTIME_ERROR<<"index_storage_pair construction : storage and indices are not compatible"; +#endif + } + + indexmap_storage_pair (indexmap_type && IM, storage_type && ST): + indexmap_(std::move(IM)),storage_(std::move(ST)){ +#ifdef TRIQS_ARRAYS_CHECK_IM_STORAGE_COMPAT + if (ST.size() != IM.domain().number_of_elements()) + TRIQS_RUNTIME_ERROR<<"index_storage_pair construction : storage and indices are not compatible"; +#endif + } + + + /// The storage is allocated from the size of IM. + indexmap_storage_pair (const indexmap_type & IM): indexmap_(IM),storage_(){ + this->storage_ = StorageType(this->indexmap_.domain().number_of_elements(), typename flags::init_tag::type() ); + } + + public: + /// Shallow copy + indexmap_storage_pair(const indexmap_storage_pair & X):indexmap_(X.indexmap()),storage_(X.storage_){} + indexmap_storage_pair(indexmap_storage_pair && X):indexmap_(std::move(X.indexmap())),storage_(std::move(X.storage_)){} + protected: + +#ifdef TRIQS_WITH_PYTHON_SUPPORT + indexmap_storage_pair (PyObject * X, bool allow_copy, const char * name ) { + //std::cout << " Enter IPS ref count = "<< X->ob_refcnt << std::endl; + try { + numpy_interface::numpy_extractor E(X, allow_copy); + this->indexmap_ = E.indexmap(); this->storage_ = E.storage(); + } + catch(numpy_interface::copy_exception s){// intercept only this one... + TRIQS_RUNTIME_ERROR<< " construction of a "<< name <<" from a numpy " + <<"\n T = "<< triqs::utility::typeid_name(value_type()) + // lead to a nasty link pb ??? + // linker search for IndexMapType::domain_type::rank in triqs.so + // and can not resolve it ??? + //<<"\n rank = "<< IndexMapType::domain_type::rank//this->rank + <<"\n OptionFlags = "<< OptionFlags + <<"\nfrom the python object \n"<< numpy_interface::object_to_string(X) + <<"\nThe error was :\n "<::type type; + }; + + template // non const version + typename boost::lazy_enable_if_c< + (!clef::is_any_lazy::value) && (indexmaps::slicer::r_type::domain_type::rank!=0) + , result_of_call_as_view + >::type // enable_if + operator()(Args const & ... args) { + return typename result_of_call_as_view::type ( indexmaps::slicer::invoke(indexmap_,args...), storage()); } + + template // const version + typename boost::lazy_enable_if_c< + (!clef::is_any_lazy::value) && (indexmaps::slicer::r_type::domain_type::rank!=0) + , result_of_call_as_view + >::type // enable_if + operator()(Args const & ... args) const { + return typename result_of_call_as_view::type ( indexmaps::slicer::invoke(indexmap_,args...), storage()); } + + typedef typename ViewFactory::type view_type; + + // Interaction with the CLEF library : calling with any clef expression as argument build a new clef expression + // NB : this is ok because indexmap_storage_pair has a shallow copy constructor ... + // so A(i_) if A is an array will NOT copy the data.... + template< typename... Args> + typename clef::result_of::make_expr_call::type + operator()( Args&&... args ) const { + static_assert(sizeof...(Args) <= indexmap_type::rank, "Incorrect number of variable in call");// not perfect : ellipsis ... + return make_expr_call(*this,args...); + //return make_expr_call( view_type(*this),args...); + } + + template friend void triqs_clef_auto_assign (indexmap_storage_pair & x, Fnt f) { assign_foreach(x,f);} + + /// Equivalent to make_view + typename ViewFactory::type,domain_type::rank, OptionFlags, TraversalOrder, ViewTag >::type + operator()() const { return *this; } + typename ViewFactory::type + operator()() { return *this; } + + // ------------------------------- Iterators -------------------------------------------- + typedef iterator_adapter const_iterator; + typedef iterator_adapter iterator; + const_iterator begin() const {return const_iterator(indexmap(),storage(),false);} + const_iterator end() const {return const_iterator(indexmap(),storage(),true);} + iterator begin() {return iterator(indexmap(),storage(),false);} + iterator end() {return iterator(indexmap(),storage(),true);} + + protected: + + // ------------------------------- resize -------------------------------------------- + // + void resize (domain_type const & d) { + this->indexmap_ = IndexMapType(d);// build a new one with the lengths of IND + // optimisation. Construct a storage only if the new index is not compatible (size mismatch). + if (this->storage_.size() != this->indexmap_.domain().number_of_elements()) + this->storage_ = StorageType(this->indexmap_.domain().number_of_elements(), typename flags::init_tag::type() ); + } + + template + void resize_and_clone_data( Xtype const & X) { indexmap_ = X.indexmap(); storage_ = X.storage().clone(); } + + // BOOST Serialization + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int version) { + ar & boost::serialization::make_nvp("storage",this->storage_); + ar & boost::serialization::make_nvp("indexmap",this->indexmap_); + } + + // pretty print of the array + friend std::ostream & operator << (std::ostream & out, const indexmap_storage_pair & A) { + if (A.storage().size()==0) out<<"empty "; + else indexmaps::pretty_print(out,A); + return out; + } + };// end class + +}}//namespace triqs::arrays +#endif + diff --git a/triqs/arrays/impl/iterator_adapter.hpp b/triqs/arrays/impl/iterator_adapter.hpp new file mode 100644 index 00000000..13f2dc13 --- /dev/null +++ b/triqs/arrays/impl/iterator_adapter.hpp @@ -0,0 +1,69 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ + +#ifndef TRIQS_ARRAYS_ARRAY_ITERATOR_H +#define TRIQS_ARRAYS_ARRAY_ITERATOR_H +#include "./make_const.hpp" +#include + +namespace triqs { namespace arrays { + /** + * Iterator on a couple (IndexMap, StorageType). + * It transforms the mini-iterator on the IndexMap into a STL-compliant iterator. + * Template parameters are : + * - Const : true -> const_iterator, false -> non const version. + * - IndexMapIterator : an IndexMapIterator + * - StorageType : the storage. + */ + + template + class iterator_adapter : + public boost::iterator_facade< + iterator_adapter, + typename details::make_const_type::type, + boost::forward_traversal_tag > + { + public: + typedef typename details::make_const_type::type value_type; + typedef IndexMapIterator indexmap_iterator_type; + + iterator_adapter(): storage_(), it() {} + iterator_adapter(const typename IndexMapIterator::indexmap_type & Ind, const StorageType & ST, bool atEnd=false): + storage_(ST), it(Ind,atEnd) {} + + operator bool() const { return bool(it);} + + typename IndexMapIterator::indexmap_type::domain_type::index_value_type const & indices() const {return it.indices();} + IndexMapIterator const & indexmap_iterator() const { return it;} + + private: + friend class boost::iterator_core_access; + void increment() { ++it; } + value_type & dereference() const { return storage_[*it];} + bool equal(iterator_adapter const & other) const { return (other.it == it);} + + StorageType storage_; + IndexMapIterator it; + }; + +}}//namespace triqs::arrays +#endif diff --git a/triqs/arrays/impl/make_const.hpp b/triqs/arrays/impl/make_const.hpp new file mode 100644 index 00000000..3529dedd --- /dev/null +++ b/triqs/arrays/impl/make_const.hpp @@ -0,0 +1,39 @@ + +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ + +#ifndef TRIQS_ARRAYS_MAKE_CONST_H +#define TRIQS_ARRAYS_MAKE_CONST_H +#include +#include + +namespace triqs { namespace arrays { + + namespace details { + /* + * make_const_type : make the type constant. + * For a storage, it transforms it into a storage + */ + template struct make_const_type : boost::mpl::if_c::type, T> {}; + } +}}//namespace triqs::arrays +#endif + diff --git a/triqs/arrays/impl/tags.hpp b/triqs/arrays/impl/tags.hpp new file mode 100644 index 00000000..9fcce82b --- /dev/null +++ b/triqs/arrays/impl/tags.hpp @@ -0,0 +1,34 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_IMPL_TAGS_H +#define TRIQS_ARRAYS_IMPL_TAGS_H +#include + +namespace triqs { namespace arrays { + namespace Tag { + struct indexmap_storage_pair{}; + struct no_init {}; struct nan_inf_init {}; struct default_init {}; + struct h5_array_proxy {}; + } + +}}//namespace triqs::arrays +#endif + diff --git a/triqs/arrays/impl/traits.hpp b/triqs/arrays/impl/traits.hpp new file mode 100644 index 00000000..09197a32 --- /dev/null +++ b/triqs/arrays/impl/traits.hpp @@ -0,0 +1,85 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_IMPL_TRAITS_H +#define TRIQS_ARRAYS_IMPL_TRAITS_H +#include +#include +#include +#include +#include + +namespace triqs { namespace arrays { + namespace mpl=boost::mpl; + + // The ImmutableArray concept + TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT(ImmutableArray); + TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R(MutableArray,(ImmutableArray)); + + /*template struct BCC_ImmutableArray { + BOOST_CONCEPT_USAGE(BCC_ImmutableArray) + { + typename X::mc_weight_type r = i.Try(); // this is e.g. for a QMC move + r = i.Accept(); + i.Reject(); + } + private: X i; + }; +*/ + + // The ImmutableCuboidArray concept + TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R(ImmutableCuboidArray,(ImmutableArray)); + TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R(MutableCuboidArray,(ImmutableCuboidArray)(MutableArray)); + + // The ImmutableMatrix concept + TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R(ImmutableMatrix,(ImmutableArray)); + TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R(MutableMatrix,(ImmutableMatrix)(MutableArray)); + + // The ImmutableVector concept + TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R(ImmutableVector,(ImmutableArray)); + TRIQS_DEFINE_CONCEPT_AND_ASSOCIATED_TRAIT_R(MutableVector,(ImmutableVector)(MutableArray)); + + namespace Tag { struct array{}; struct array_view {}; } + template struct is_array : std::is_base_of {}; + template struct is_array_view : std::is_base_of {}; + template struct is_array_or_view : boost::mpl::or_< is_array, is_array_view > {}; + + namespace Tag { struct vector{}; struct vector_view {};} + template struct is_vector : std::is_base_of {}; + template struct is_vector_view : std::is_base_of {}; + template struct is_vector_or_view : boost::mpl::or_< is_vector, is_vector_view > {}; + + namespace Tag { struct matrix_view {}; struct matrix {}; } + template struct is_matrix : std::is_base_of {}; + template struct is_matrix_view : std::is_base_of {}; + template struct is_matrix_or_view : boost::mpl::or_< is_matrix, is_matrix_view > {}; + + template struct is_amv_value_class : boost::mpl::or_< is_array, is_matrix, is_vector > {}; + template struct is_amv_view_class : boost::mpl::or_< is_array_view, is_matrix_view, is_vector_view > {}; + template struct is_amv_value_or_view_class : boost::mpl::or_< is_amv_value_class, is_amv_view_class > {}; + + template struct is_scalar : boost::mpl::or_ , boost::is_complex > {}; + + template struct is_scalar_for : + boost::mpl::if_ , is_scalar,boost::is_same >::type {}; + +}}//namespace triqs::arrays +#endif + diff --git a/triqs/arrays/indexmaps/common.hpp b/triqs/arrays/indexmaps/common.hpp new file mode 100644 index 00000000..f31621f8 --- /dev/null +++ b/triqs/arrays/indexmaps/common.hpp @@ -0,0 +1,89 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_INDEXMAP_COMMON_H +#define TRIQS_ARRAYS_INDEXMAP_COMMON_H +#include "../impl/common.hpp" +#include +//#include "../impl/tuple_tools.hpp" +#include +#include + +namespace boost { namespace serialization { class access;}} +namespace triqs { namespace arrays { namespace Tag {struct indexmap{}; }}} + +namespace triqs { namespace arrays { + using utility::mini_vector; + + // make_shape + // generalize with preproc or variadic template +//#define IMPL(z, NN, unused) \ +// template mini_vector make_shape(BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), T I_)) \ +// { return mini_vector(BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(NN), I_));} +// BOOST_PP_REPEAT(ARRAY_NRANK_MAX , IMPL, nil) +//#undef IMPL + template + mini_vector make_shape(size_t x0, T... args) { return mini_vector (x0,args...);} + + namespace indexmaps { + + // to be specialized for all IndexMap types. + template struct slicer; + + /// Returns whether the 2 indexMaps are compatible with A op B (op : = , +, etc...) + template< typename IndexMap1, typename IndexMap2> + bool compatible_for_binary_ops (const IndexMap1 &, const IndexMap2 &); + + // The generator of indices for an index domain. + template class indices_generator; + + /** + * Is a raw copy possible between 2 arrays with these indexMaps ? + * They have to have the same ordering, and be contiguous typically. + */ + template< typename IndexMap1, typename IndexMap2> + bool raw_copy_possible (const IndexMap1 &, const IndexMap2 &); + + /** + * Metafunction. + * Given an IndexMapIterator and an IndexMap, + * ::type should be the iterator of IndexMap which traverses + * the indices in the same order as IndexMapIterator. + * Example : + * - IndexMapIterator is a parallelepipedon_iterator < SomeParallelepipedon, So + meIterationOrder> + * - IndexMap is AnotherParallelepipedon (e.g. with a different memory storage) + . + * - type is then parallelepipedon_iterator < AnotherParallelepipedon, SomeIter + ationOrder> + * Application example : + * A = B with A, B in different order in memory. + * One takes the optimized iterator on A, this defines the order of indices + traversal, + * and use indexmap_iterator_adapter to deduce the iterator on B that traver + se the indices in the same way. + */ + //template + // struct indexmap_iterator_adapter; + + }}}//namespace triqs::arrays +#endif + + diff --git a/triqs/arrays/indexmaps/cuboid/domain.hpp b/triqs/arrays/indexmaps/cuboid/domain.hpp new file mode 100644 index 00000000..02d5102e --- /dev/null +++ b/triqs/arrays/indexmaps/cuboid/domain.hpp @@ -0,0 +1,197 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011-2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_DOMAIN_H +#define TRIQS_ARRAYS_INDEXMAP_CUBOID_DOMAIN_H +#include "../common.hpp" +#include "../range.hpp" +#include "./mem_layout.hpp" +#include +#include "../../impl/exceptions.hpp" +#include +#include +#include +#include +#include +#include + +namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid { + using namespace triqs::arrays::permutations; + + /// Standard hyper_rectangular domain for arrays + template + class domain_t { + typedef mini_vector n_uple; + n_uple lengths_; + friend class boost::serialization::access; + template void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::make_nvp("dimensions",lengths_);} + public : + //static const unsigned int rank = Rank; + static constexpr unsigned int rank = Rank; + typedef n_uple index_value_type; + + domain_t ():lengths_(){} + domain_t (n_uple const & lengths):lengths_(lengths) {} + domain_t (n_uple && lengths):lengths_(std::move(lengths)) {} + domain_t (mini_vector const & lengths):lengths_(lengths) {} + domain_t (std::vector const & l):lengths_() { + if (!(l.size()==rank)) TRIQS_RUNTIME_ERROR << "cuboid domain_t construction : vector size incorrect : got "<lengths_ == X.lengths_;} + bool operator!=(domain_t const & X) const { return !(this->lengths_ == X.lengths_);} + n_uple const & lengths() const { return lengths_;} + + /** Generates the value of the indices of a cuboid_domain. */ + static constexpr ull_t iteration_order_default = permutations::identity(Rank); + template + class gal_generator { + typedef index_value_type indices_type; + const domain_t * dom; + indices_type indices_tuple; + bool atend; + public: + gal_generator (const domain_t & P, bool atEnd=false): dom(&P), atend(atEnd) {} + bool operator==(const gal_generator & IT2) const { assert((IT2.dom == dom)); return ((IT2.atend==atend) );} + bool operator!=(const gal_generator & IT2) const { return (!operator==(IT2));} + indices_type const & operator *() const { return indices_tuple;} + operator bool () const { return !atend;} + gal_generator & operator++(){ assert(!atend); atend = advance_impl(std::integral_constant()); return *this;} + private: + template bool advance_impl(std::integral_constant) { + constexpr int p = permutations::apply(IterationOrder, r); + if (indices_tuple[p] < dom->lengths()[p]-1) { ++(indices_tuple[p]); return false;} + indices_tuple[p] = 0; + return advance_impl(std::integral_constant()); + } + bool advance_impl(std::integral_constant) { return true;} + }; + + typedef gal_generator<> generator; + + generator begin() const { return generator(*this,false);} + generator end() const { return generator(*this,true);} + /* End of generator */ + + // Check that key in in the domain + template void assert_key_in_domain(KeyType const & key) const { + std::stringstream fs; + bool res = key_check_impl(std::integral_constant(), key,this->lengths_,fs); + if (!res) TRIQS_ARRAYS_KEY_ERROR << " key out of domain \n" < + bool key_check_impl (std::integral_constant, KeyType const & key, n_uple const & L, std::stringstream & fs ) const { + //bool cond = ( ( size_t(key[r]) < L[r])); + bool cond = ( ( size_t(std::get(key)) < L[r])); + //if (!cond) fs << "key ["<(), key,L,fs) && cond; + } + template bool key_check_impl (std::integral_constant, KeyType const &, n_uple const &, std::stringstream &) const { return true;} + + // Check that key in in the domain : variadic form. No need for speed optimisation here, it is just for debug + template void assert_key_in_domain_v (Args const & ... args) const { assert_key_in_domain( std::make_tuple(args...));} + + friend std::ostream & operator<<(std::ostream & out, domain_t const & x){return out<<"Cuboid of rank "< struct foreach_impl; + /// Call the function F for each element of the domain, traversed in the TraversalOrder + template + void foreach(domain_t const & d, FntType F) { foreach_impl::invoke (d,F); } + + // ------------------------- implementation of foreach ----------------------------------------------------- + + typedef std::ptrdiff_t foreach_int_type; + // better to be signed here : 1) on some machine/compiler, it is a lot faster ! + // When used with clef auto assign, e.g. A(i_,j_) = i -2*j, one needs signed arithmetics + // The clef adapters would convert, but this requires a conversion at each call.... + //typedef size_t foreach_int_type; + +#define AUX0(z,P,NNN) constexpr int p##P = mem_layout::memory_rank_to_index(TraversalOrder,NNN-P); +#define AUX1(z,P,unused) for (t[p##P]=0; t[p##P]< l[p##P]; ++t[p##P]) +//#define AUX1(z,P,unused) for (foreach_int_type x##P=0; x##P< dom.lengths()[p##P]; ++x##P) +#define AUX3(z,p,unused) BOOST_PP_COMMA_IF(p) t[p] +#define IMPL(z, RR, unused) \ + template struct foreach_impl {\ + static void invoke ( domain_t const & dom, FntType F) { \ + BOOST_PP_REPEAT(RR,AUX0,BOOST_PP_DEC(RR))\ + mini_vector t;\ + const mini_vector l(dom.lengths());\ + BOOST_PP_REPEAT(RR,AUX1,nil){\ + F(BOOST_PP_REPEAT(RR,AUX3,nil));\ + } }}; + BOOST_PP_REPEAT_FROM_TO(1,ARRAY_NRANK_MAX , IMPL, nil); +#undef IMPL +#undef AUX0 +#undef AUX1 +#undef AUX3 +} +/// ------------ Pretty Printing : specializing the default behaviour for d=1,2 ------------------------- +namespace PrettyPrint_details { + template + struct print_impl { + std::ostream & out; A const & a; + print_impl( std::ostream & out_, A const & a_) : out(out_), a(a_){} + template void operator()(A0 const & a0, Args const & ... args) const { out << a(a0,args...)<< " ";} + void print() const { out<<"["; + indexmaps::cuboid::foreach (a.domain(), std::cref(*this)); //foreach(a, std::cref(*this)); + out<<"]"; } + }; + + template + struct print_impl <1,A> { + std::ostream & out; A const & a; + print_impl( std::ostream & out_, A const & a_) : out(out_), a(a_){} + void print() const { + auto d = a.indexmap().domain(); + out<<"["; for (size_t i=0; i< d.lengths()[0]; ++i) out<<(i>0 ? ",": "")< + struct print_impl <2,A> { + std::ostream & out; A const & a; + print_impl( std::ostream & out_, A const & a_) : out(out_), a(a_){} + void print() const { + auto d = a.indexmap().domain(); + out<<"\n["; + for (size_t i=0; i< d.lengths()[0]; ++i) { + out<<(i==0 ? "[" : " ["); + for (size_t j=0; j< d.lengths()[1]; ++j) out<<(j>0 ? ",": "")< +void pretty_print (std::ostream & out, A const & a ) { PrettyPrint_details::print_impl(out,a).print();} + +}}} +#endif diff --git a/triqs/arrays/indexmaps/cuboid/foreach.hpp b/triqs/arrays/indexmaps/cuboid/foreach.hpp new file mode 100644 index 00000000..2c46d5be --- /dev/null +++ b/triqs/arrays/indexmaps/cuboid/foreach.hpp @@ -0,0 +1,47 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_FOREACH_H +#define TRIQS_ARRAYS_INDEXMAP_CUBOID_FOREACH_H +#include "./map.hpp" + +namespace triqs { namespace arrays { + + template struct get_traversal_order : indexmaps::mem_layout::fortran_order_tr{}; + //template struct get_traversal_order : indexmaps::mem_layout::c_order_tr{}; + template struct get_traversal_order : std::integral_constant{}; + + template + typename std::enable_if::value >::type + foreach (T const & x, Function const & F) { indexmaps::cuboid::foreach::value> (x.domain(), F); } + + template + struct assign_foreach_adapter { + T& x; Function const & f; + assign_foreach_adapter( T& x_, Function const & ff): x(x_), f(ff){} + template void operator()(Args const & ... args) const { x(args...) = f(args...);} + }; + + template + typename std::enable_if::value >::type + assign_foreach (T & x, Function const & F) { indexmaps::cuboid::foreach::value> (x.domain(),assign_foreach_adapter(x,F)); } + +}}//namespace +#endif diff --git a/triqs/arrays/indexmaps/cuboid/group_indices.hpp b/triqs/arrays/indexmaps/cuboid/group_indices.hpp new file mode 100644 index 00000000..8132ba0f --- /dev/null +++ b/triqs/arrays/indexmaps/cuboid/group_indices.hpp @@ -0,0 +1,111 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2013 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_GROUP_INDICES_H +#define TRIQS_ARRAYS_INDEXMAP_CUBOID_GROUP_INDICES_H +#include +namespace triqs { namespace arrays { + + // a variadic push_back into a vector. + template void vector_push_back_v(V & v){} + template void vector_push_back_v(V & v, T0 && t0, T && ... t){ v.push_back(std::forward(t0)); vector_push_back_v(v,t...);} + + // a list of compile time int... + template struct m_index{}; + template struct m_index {static constexpr int head = I0; }; + template std::vector m_index_to_vector( m_index) { std::vector v; vector_push_back_v(v,Is...); return v;} + + // a trait to get the min, max of a m_index + template struct get_min_max; + template struct get_min_max> { + typedef get_min_max> r; + static constexpr int min = (I0 < r::min ? I0 : r::min); static constexpr int max = (I0 > r::max ? I0 : r::max); + }; + template struct get_min_max> { static constexpr int min = I0; static constexpr int max = I0; }; + + // given a m_index of indices, a metafunction to map to their position into memory + template struct index_group_to_mem_pos_list; + template struct index_group_to_mem_pos_list> { +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + typedef m_index < indexmaps::mem_layout::index_to_memory_rank(ML,Is)...> type; +#else + typedef m_index < indexmaps::mem_layout::index_to_memory_rank_tr::value ... > type; +#endif + static_assert( get_min_max::max - get_min_max::min + 1 == sizeof...(Is), "Indices not contiguous in memory"); + }; + +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + // count the number of Is strictly smaller than C + constexpr int count_pos(int C){ return 0;} + template constexpr int count_pos(int C, int i, T... t){ return (i struct count_pos_list { typedef m_index< count_pos(Is, Is...)...> type; }; +#else + template struct count_pos; + template struct count_pos> : std::integral_constant>::value + (I0 {}; + template struct count_pos> : std::integral_constant{}; + template struct count_pos_list { typedef m_index tmp; typedef m_index< count_pos::value...> type; }; +#endif + + // a simple foreach + template void for_each (Callee & C, T0 const & t0, T const & ... t ) { C(t0); for_each(C, t...);} + template void for_each (Callee & C){} + + // make a permutation out of a m_index + template struct to_permu; + template struct to_permu> { static constexpr ull_t value = permutations::permutation(Is...);}; + + // the main class + template struct group_indices_impl { + static constexpr int new_dim = sizeof...(MIndex); + typedef typename count_pos_list< index_group_to_mem_pos_list::type::head ...>::type new_memory_pos; + + static constexpr ull_t traversal_layout = to_permu::value; + typedef array_view type; + + static type invoke(A const & a) { + if (a.indexmap().memory_indices_layout_ull() != a.indexmap().traversal_order) + TRIQS_RUNTIME_ERROR << "Grouping indices is only possible for arrays when the memory_layout is the same as the traversal order \n" + << "But here your memory_layout is "<< a.indexmap().memory_indices_layout() << " while the traversal order is "<< a.indexmap().traversal_order_indices_layout(); + std::vector< std::vector > Indices; + vector_push_back_v(Indices, m_index_to_vector(MIndex())...); + mini_vector l; + mini_vector s; + for (size_t u=0; u + typename group_indices_impl::type group_indices(A const & a, MIndex... ) { return group_indices_impl::invoke(a);} +}}//namespace triqs::arrays +#endif diff --git a/triqs/arrays/indexmaps/cuboid/map.hpp b/triqs/arrays/indexmaps/cuboid/map.hpp new file mode 100644 index 00000000..c4e055e0 --- /dev/null +++ b/triqs/arrays/indexmaps/cuboid/map.hpp @@ -0,0 +1,216 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_MAP_H +#define TRIQS_ARRAYS_INDEXMAP_CUBOID_MAP_H +#include "./domain.hpp" +#include "./mem_layout.hpp" +#include "../../impl/flags.hpp" +#include +#include + +namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid { + + template< bool BC, class D, class K> struct _chk; + template< class D, class K> struct _chk { static void invoke (D const & d, K const & k) {d.assert_key_in_domain(k);} }; + template< class D, class K> struct _chk { static void invoke (D const & d, K const & k) {} }; + + template< bool BC, class D, class ... K> struct _chk_v; + template< class D, class ... K> struct _chk_v { static void invoke (D const & d, K const & ... k) {d.assert_key_in_domain_v(k...);} }; + template< class D, class ... K> struct _chk_v { static void invoke (D const & d, K const & ... k) {} }; + + template ull_t memory_layout_from_strides(mini_vector const & strides) { + int c[Rank]; for (size_t i=0; i strides[j]) c[i]++; else c[j]++; + // we computed the map : index -> memory_rank, which is the inverse map, cf mem_layout + return permutations::inverse(permutations::permutation_from_array(c, Rank)); + } + + /** Standard hyper_rectangular arrays, implementing the IndexMap concept. + */ + template + class map { + public : + static constexpr bool CheckBounds = flags::bound_check_trait::value; + static constexpr ull_t traversal_order_in_template = TraversalOrder; + static constexpr ull_t traversal_order = indexmaps::mem_layout::get_traversal_order::value; + typedef void has_traversal_order_tag; + static const unsigned int rank = Rank; + typedef mini_vector lengths_type; + typedef mini_vector strides_type; + typedef domain_t domain_type; + domain_type const & domain() const { return mydomain;} + + // basic construction + map (memory_layout const & ml = memory_layout(traversal_order)):mydomain(), start_shift_(0), memory_order_(ml) {} + map(domain_type const & C): mydomain(C), start_shift_(0), memory_order_(traversal_order) {compute_stride_compact();} + map(domain_type const & C, memory_layout ml): mydomain(C), start_shift_(0), memory_order_(ml) {compute_stride_compact();} + + /// Construction from the length, the stride, start_shift + map(lengths_type const & Lengths, strides_type const & strides, std::ptrdiff_t start_shift ): + mydomain(Lengths), strides_(strides), start_shift_(start_shift), + memory_order_ (memory_layout_from_strides(strides_)) {} + + /// Construction from the length, the stride, start_shift + map(lengths_type && Lengths, strides_type && strides, std::ptrdiff_t start_shift ): + mydomain(std::move(Lengths)), strides_(std::move(strides)), start_shift_(start_shift), + memory_order_ (memory_layout_from_strides(strides_)) {} + + /// Construction from another map with the same order (used in grouping indices) + template map (map const & C): + mydomain(C.domain()), strides_(C.strides()), start_shift_(C.start_shift()), memory_order_ (C.memory_indices_layout()) {} + + // value semantics + map (map const & C) = default; + map (map && C) { *this = std::move(C);} + friend void swap(map & a, map & b) { + swap(a.mydomain, b.mydomain); std::swap(a.start_shift_,b.start_shift_); +#ifdef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + std::swap(a.memory_order_.value, b.memory_order_.value);// why is there a link pb on icc ? temporary fix... +#else + std::swap(a.memory_order_, b.memory_order_); +#endif + swap(a.strides_, b.strides_); + } + map & operator = (map const & m) = default; + map & operator = (map && m) { swap(*this,m); return *this;} + + /// Returns the shift in position of the element key. + template + size_t operator[] (KeyType const & key ) const { + _chk::invoke (this->domain(),key); + return start_shift_ + dot_product(key,this->strides()); + } + + friend std::ostream & operator << (std::ostream & out, const map & P) { + return out <<" ordering = {"< size_t operator()(Args const & ... args) const { + _chk_v::invoke (this->domain(),args...); + return start_shift_ + _call_impl<0>(args...); + } + private : + template + size_t _call_impl( Arg0 const & arg0, Args const & ... args) const { return arg0* strides_[N] + _call_impl(args...); } + template size_t _call_impl() const { return 0;} + public: + + /// + bool is_contiguous() const { + const size_t last_index = mem_layout::memory_rank_to_index(memory_order_.value, rank-1); + return (strides()[last_index] * this->lengths()[last_index] == mydomain.number_of_elements()); + } + + size_t start_shift() const { return start_shift_;} + lengths_type const & lengths() const { return mydomain.lengths();} + strides_type const & strides() const { return this->strides_;} + + memory_layout const & memory_indices_layout() const { return memory_order_;} + memory_layout traversal_order_indices_layout() const { return memory_layout(traversal_order);} + ull_t memory_indices_layout_ull() const { return memory_order_.value;} + bool memory_layout_is_c() const { return memory_indices_layout().value == mem_layout::c_order(Rank);} + bool memory_layout_is_fortran() const { return memory_indices_layout().value == mem_layout::fortran_order(Rank);} + + private : + domain_type mydomain; + strides_type strides_; + std::ptrdiff_t start_shift_; + memory_layout memory_order_; + + // BOOST Serialization + friend class boost::serialization::access; + template void serialize(Archive & ar, const unsigned int version) { + ar & boost::serialization::make_nvp("domain",mydomain); + ar & boost::serialization::make_nvp("strides",strides_); + ar & boost::serialization::make_nvp("start_shift",start_shift_); + } + // for construction + void compute_stride_compact() { + size_t str = 1; + csc_impl(memory_order_.value, str, std::integral_constant()); + assert(this->domain().number_of_elements()==str); + } + template + void csc_impl(ull_t order, size_t & str, std::integral_constant) { + size_t u = mem_layout::memory_rank_to_index(order, rank-v); + this->strides_[u] = str; + str *= this->lengths() [u]; + csc_impl(order, str, std::integral_constant()); + } + void csc_impl(ull_t order,size_t & str, std::integral_constant) {} + + public: + + /** + * Iterator on a cuboid_map, modeling the IndexMapIterator concept. + * Iteration order is the order in which to iterate on the indices. + * It is given by a permutation, with the same convention as IndexOrder. + */ + class iterator : public boost::iterator_facade< iterator, const std::ptrdiff_t, boost::forward_traversal_tag > { + public: + typedef map indexmap_type; + typedef typename domain_type::index_value_type indices_type; + typedef const std::ptrdiff_t return_type; + iterator (): im(NULL), pos(0),atend(true) {} + iterator (const map & P, bool atEnd=false, ull_t iteration_order=0): + im(&P), pos(im->start_shift()),atend(atEnd) {} + indices_type const & indices() const { return indices_tuple; } + operator bool() const { return !atend;} + private: + friend class boost::iterator_core_access; + void increment(){ inc_ind_impl (std::integral_constant()); } + template inline void inc_ind_impl(std::integral_constant) { + constexpr size_t p = mem_layout::memory_rank_to_index(traversal_order, rank-v); +#ifdef TRIQS_ARRAYS_ENFORCE_BOUNDCHECK + if (atend) TRIQS_RUNTIME_ERROR << "Iterator in cuboid can not be pushed after end !"; +#endif + if (indices_tuple[p] < im->lengths()[p]-1) { ++(indices_tuple[p]); pos += im->strides()[p]; return; } + indices_tuple[p] = 0; + pos -= (im->lengths()[p]-1) * im->strides()[p]; + inc_ind_impl (std::integral_constant()); + } + inline void inc_ind_impl(std::integral_constant) { atend = true;} + bool equal(iterator const & other) const {return ((other.im==im)&&(other.atend==atend)&&(other.pos==pos));} + return_type & dereference() const { assert (!atend); return pos; } + map const * im; + indices_type indices_tuple; + std::ptrdiff_t pos; + bool atend; + }; + + }; //------------- end class --------------------- +}//namespace cuboid + +template +bool compatible_for_assignment (const cuboid::map & X1, const cuboid::map & X2) { return X1.lengths() == X2.lengths();} + +template + bool raw_copy_possible (const cuboid::map & X1,const cuboid::map & X2) { + return ( (X1.memory_indices_layout() == X2.memory_indices_layout()) + && X1.is_contiguous() && X2.is_contiguous() + && (X1.domain().number_of_elements()==X2.domain().number_of_elements())); + } +}}}//namespace triqs::arrays::indexmaps +#endif diff --git a/triqs/arrays/indexmaps/cuboid/mem_layout.hpp b/triqs/arrays/indexmaps/cuboid/mem_layout.hpp new file mode 100644 index 00000000..bdbbe62e --- /dev/null +++ b/triqs/arrays/indexmaps/cuboid/mem_layout.hpp @@ -0,0 +1,130 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_INDEXMAP_MEMORY_LAYOUT_H +#define TRIQS_ARRAYS_INDEXMAP_MEMORY_LAYOUT_H +#include "../permutation.hpp" +#include "../../impl/flags.hpp" + +namespace triqs { namespace arrays { + + namespace indexmaps { namespace mem_layout { + /* The storage order is given by a permutation P stored in a ull_t (unsigned long long) as in permutations::.. + * P[0] : the fastest index, + * P[RANK-1] : the slowest index + * Example : + * 012 : Fortran, the first index is the fastest + * 210: C the last index is the fastest + * 120 : storage (i,j,k) is : index j is fastest, then k, then i + * + * index_to_memory_rank : i ---> r : to the index (0,1, ... etc), associates the rank in memory + * e.g. r=0 : fastest index, r = RANK-1 : the slowest + * memory_rank_to_index : the inverse mapping : r---> i : + * 0-> the fastest index, etc.. + * + * All these computations can be done *at compile time* (constexpr) + */ + +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + + constexpr int memory_rank_to_index(ull_t p, int r) { return permutations::apply(p, r);} + constexpr int index_to_memory_rank(ull_t p, int r) { return permutations::apply(permutations::inverse(p), r);} + + constexpr bool is_fortran (ull_t p){ return p == permutations::identity(permutations::size(p));} + constexpr bool is_c (ull_t p){ return p == permutations::ridentity(permutations::size(p));} + + constexpr ull_t fortran_order (int n){ return permutations::identity(n);} + constexpr ull_t c_order (int n){ return permutations::ridentity(n);} + + template struct fortran_order_tr { static constexpr ull_t value = permutations::identity(n);}; + template struct c_order_tr { static constexpr ull_t value = permutations::ridentity(n);}; + + // From the flag in the template definition to the real traversal_order + // 0 -> C order + // 1 -> Fortran Order + // Any other number interpreted as a permutation ? + + constexpr ull_t _get_traversal_order (int rank, ull_t fl, ull_t to) { return (flags::traversal_order_c(fl) ? c_order(rank) : + (flags::traversal_order_fortran(fl) ? fortran_order(rank) : (to==0 ? c_order(rank) : to )));} + + template< int rank, ull_t fl, ull_t to> struct get_traversal_order { static constexpr ull_t value = _get_traversal_order (rank,fl,to); }; +#else + + constexpr int memory_rank_to_index(ull_t p, int r) { return permutations::apply(p, r);} + constexpr int index_to_memory_rank(ull_t p, int r) { return permutations::apply(permutations::inverse(p), r);} + + template struct index_to_memory_rank_tr { static constexpr ull_t value = permutations::apply(permutations::inverse(p), r);}; + + constexpr bool is_fortran (ull_t p){ return p == permutations::identity(permutations::size(p));} + constexpr bool is_c (ull_t p){ return p == permutations::ridentity(permutations::size(p));} + + constexpr ull_t fortran_order (int n){ return permutations::identity(n);} + constexpr ull_t c_order (int n){ return permutations::ridentity(n);} + + template struct fortran_order_tr { static constexpr ull_t value = permutations::identity(n);}; + template struct c_order_tr { static constexpr ull_t value = permutations::ridentity(n);}; + + template< int rank, ull_t fl, ull_t to> struct get_traversal_order { + static constexpr ull_t value = (flags::traversal_order_c::value ? c_order_tr::value : + (flags::traversal_order_fortran::value ? fortran_order_tr::value : (to==0 ? c_order_tr::value : to ))); + }; +#endif + }} + + + + struct memory_layout_fortran {}; + struct memory_layout_c {}; + +#define FORTRAN_LAYOUT (triqs::arrays::memory_layout_fortran()) +#define C_LAYOUT (triqs::arrays::memory_layout_fortran()) + + // stores the layout == order of the indices in memory + // wrapped into a little type to make constructor unambigous. + template + struct memory_layout { + ull_t value; + explicit memory_layout (ull_t v) : value(v) {assert((permutations::size(v)==Rank));} + explicit memory_layout (char ml='C') { + assert( (ml=='C') || (ml == 'F')); + value = (ml=='F' ? indexmaps::mem_layout::fortran_order(Rank) : indexmaps::mem_layout::c_order(Rank)); + } + memory_layout (memory_layout_fortran) { value = indexmaps::mem_layout::fortran_order(Rank); } + memory_layout (memory_layout_c) { value = indexmaps::mem_layout::c_order(Rank); } + template + explicit memory_layout(int i0, int i1, INT ... in) : value (permutations::permutation(i0,i1,in...)){ + static_assert( sizeof...(in)==Rank-2, "Error"); + } + memory_layout (const memory_layout & C) = default; + memory_layout (memory_layout && C) { *this = std::move(C);} + friend void swap( memory_layout & a, memory_layout & b){ std::swap(a.value,b.value);} + memory_layout & operator =( memory_layout const &) = default; + memory_layout & operator =( memory_layout && x) { swap(*this,x); return *this;} + + bool operator ==( memory_layout const & ml) const { return value == ml.value;} + bool operator !=( memory_layout const & ml) const { return value != ml.value;} + + friend std::ostream & operator <<( std::ostream & out, memory_layout const & s) { permutations::print(out,s.value); return out;} + }; + + //template void swap( memory_layout & a, memory_layout & b) { std::swap(a.value,b.value);} + +}}//namespace triqs::arrays +#endif diff --git a/triqs/arrays/indexmaps/cuboid/slice.hpp b/triqs/arrays/indexmaps/cuboid/slice.hpp new file mode 100644 index 00000000..2173f93e --- /dev/null +++ b/triqs/arrays/indexmaps/cuboid/slice.hpp @@ -0,0 +1,115 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2011 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_SLICE_H +#define TRIQS_ARRAYS_INDEXMAP_CUBOID_SLICE_H +#include +#include "./slice_traversal_order.hpp" +namespace triqs { namespace arrays { namespace indexmaps { + namespace cuboid_details { +#define LISILOSO l_type const * li, s_type const * si, l_type * lo, s_type * so + typedef size_t l_type; + typedef std::ptrdiff_t s_type; + + template inline void _check_BC ( int N, int ind, size_t B, int ind_min =0) { } + template <> inline void _check_BC (int N, int ind, size_t B, int ind_min) { + if (!((ind >= ind_min) && (ind < int(B)))) TRIQS_ARRAYS_KEY_ERROR << " index "< + static void one_step(LISILOSO, std::ptrdiff_t& offset, size_t R){ + _check_BC (N, R, li[N]); + offset += R*si[N]; + } + + template + static void one_step(LISILOSO, std::ptrdiff_t& offset, range R){ + _check_BC (N, R.first(),li[N]); + lo[P] = ((R.last()==-1 ? li[N] : R.last()) - R.first() + R.step()-1 )/R.step(); // python behaviour + _check_BC (N, R.first() + (lo[P]!=0 ? (lo[P]-1) : 0)*R.step() ,li[N], -1); + so[P] = si[N] * R.step(); + offset += R.first() * si[N]; + } + + template + static typename std::enable_if<((EllipsisLength==1) || (!std::is_base_of::type::value)), void>::type + invoke(LISILOSO, s_type & offset, Arg0 const & arg0, Args const & ... args ) { + constexpr bool dP = (std::is_base_of::type::value ? 1 : 0); // Arg0 is range or ellipsis + one_step(li,si,lo,so,offset, arg0); + invoke(li,si,lo,so, offset, args...); + } + + template + static typename std::enable_if<((EllipsisLength==0) && std::is_base_of::type::value), void>::type + invoke(LISILOSO, s_type & offset, Arg0 const & arg0, Args const & ... args ) { + invoke(li,si,lo,so, offset, args...); + } + + template + static typename std::enable_if<((EllipsisLength>1) && std::is_base_of::type::value), void>::type + invoke(LISILOSO, s_type & offset, Arg0 const & arg0, Args const & ... args ) { + constexpr bool dP = (std::is_base_of::type::value ? 1 : 0); // Arg0 is range or ellipsis + one_step(li,si,lo,so,offset, arg0); + invoke(li,si,lo,so, offset, arg0, args...); + } + + template static void invoke(LISILOSO, s_type & offset ) {} + }; +#undef LISILOSO + }//namespace cuboid_details + + // special case of no argument : + template struct slicer < cuboid::map > { typedef cuboid::map < R, Opt,To > r_type; }; + + // general case + template struct slicer < cuboid::map, Args...> { + + static const unsigned int len = sizeof...(Args); + static constexpr bool has_ellipsis = (count_type_occurrence::value>0); + static_assert((count_type_occurrence::value < 2), "Only one ellipsis is permitted"); + static_assert((len>=R || has_ellipsis), "Too few arguments in slice"); + static_assert((len<=R+(has_ellipsis ?1:0)), "Too many arguments in slice"); // + one to allow an empty ellipsis + + typedef cuboid::map im_t; + static constexpr int Rf = R - count_type_occurrence_not::value; + static constexpr ull_t To_i = im_t::traversal_order; + + // compute a new traversal order, only if there is no ellipsis + // the computation with ellipsis is not yet implemented... + static constexpr ull_t Tof = (has_ellipsis ? 0 : cuboid::slicing_TO_order::sliced_memory_order::value); + typedef cuboid::map < Rf , Opt, Tof> r_type; + +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + static_assert(( (has_ellipsis) || (permutations::size(Tof) == Rf)), "Mismatch between Rank and the TraversalOrder"); +#endif + + static r_type invoke (im_t const & X, Args ... args) { + typename r_type::lengths_type newlengths; + typename r_type::strides_type newstrides; + std::ptrdiff_t newstart= X.start_shift(); + constexpr int EllipsisLength = R -len+1; + cuboid_details::slice_calc::invoke<0,0,flags::bound_check_trait::value,EllipsisLength>(&X.lengths()[0],&X.strides()[0],&newlengths[0],&newstrides[0],newstart, args...); + return r_type(std::move(newlengths),std::move(newstrides),newstart);// use move construction ? + }; + }; +}}}//namespaces triqs::arrays::indexmaps +#endif diff --git a/triqs/arrays/indexmaps/cuboid/slice_traversal_order.hpp b/triqs/arrays/indexmaps/cuboid/slice_traversal_order.hpp new file mode 100644 index 00000000..bae721af --- /dev/null +++ b/triqs/arrays/indexmaps/cuboid/slice_traversal_order.hpp @@ -0,0 +1,75 @@ +/******************************************************************************* + * + * TRIQS: a Toolbox for Research in Interacting Quantum Systems + * + * Copyright (C) 2012 by 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 . + * + ******************************************************************************/ +#ifndef TRIQS_ARRAYS_INDEXMAP_STORAGE_ORDER_H +#define TRIQS_ARRAYS_INDEXMAP_STORAGE_ORDER_H +#include "./mem_layout.hpp" +namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid { namespace slicing_TO_order { + +#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS + template struct _impl{ + static constexpr int n_range_ellipsis=0; + static constexpr ull_t mask(ull_t mo, int P, int c) { return 0;} + static constexpr ull_t smo (ull_t mo, ull_t ma, int P, int c) { return 0;} + }; + template struct _impl< A0,SliceArgs...> { + typedef _impl next_t; + static constexpr bool is_range = std::is_base_of::value; // range and ellipsis (derived from range) + static constexpr int n_range_ellipsis= next_t::n_range_ellipsis + is_range; + static constexpr ull_t mask(ull_t mo, int P=0, int c=0) { return ((is_range ? P+1 : 0) << (4*c)) + next_t::mask(mo,P + is_range,c+1);} + static constexpr ull_t r2 (ull_t mo, ull_t ma, int c) { return (ma >> (4*(permutations::apply(mo,c)))) & 0xF; } + static constexpr ull_t aux (ull_t mo,ull_t ma,ull_t r,int P,int c) { return (r!=0? ( (r-1) << (4*P)) : 0) + next_t::smo(mo,ma,P+(r!=0), c+1); } + static constexpr ull_t smo (ull_t mo, ull_t ma, int P=0, int c=0) { return aux(mo,ma,r2(mo,ma,c),P,c); } + }; + template + constexpr ull_t sliced_memory_order1(ull_t mo) { return _impl::n_range_ellipsis + 0x10*_impl::smo(mo, _impl::mask(mo));} + template + constexpr ull_t sliced_memory_order2(ull_t mo) { return (mem_layout::is_c (mo) ? c_order(_impl::n_range_ellipsis) : + ( mem_layout::is_fortran(mo) ? fortran_order(_impl::n_range_ellipsis) : sliced_memory_order1(mo) )); + } + template struct sliced_memory_order { static constexpr ull_t value = sliced_memory_order1(mo); }; +#else + template struct mask { + static constexpr ull_t value = 0; + static constexpr int n_range_ellipsis= 0; + }; + template struct mask { + static constexpr bool is_range = std::is_base_of::value; + typedef mask

0q#Bh!A)M7?Agd*K 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