diff --git a/README.rst b/README.rst index 662c1b5626d234a621bbd17b98dc82aa2718d861..abb838902203b2ba491cb33fbd2bf780c4214b1d 100644 --- a/README.rst +++ b/README.rst @@ -18,3 +18,7 @@ Comments * particles: initialization of multistep solvers is done with lower order methods, so don't be surprised if direct convergence tests fail. +* I am using this code mainly with Python 3.4, but Python 2.7 + compatibility should be kept since mayavi (well, vtk actually) only + works on Python 2. + diff --git a/bfps/__init__.py b/bfps/__init__.py index 08532a02b43e6a74b5ae94c643f15c6b7a075a21..248b5a75570bdafb1dad2c57e571b6981abbd13e 100644 --- a/bfps/__init__.py +++ b/bfps/__init__.py @@ -38,10 +38,10 @@ try: if not here.startswith(os.path.join(dist_loc, 'bfps')): # not installed, but there is another version that *is* header_dir = os.path.join(os.path.dirname(here), 'cpp') - lib_dir = os.path.join(os.path.dirname(here), os.pardir) + lib_dir = os.path.dirname(here) raise DistributionNotFound header_dir = os.path.join(os.path.join(dist_loc, 'bfps'), 'cpp') - lib_dir = _dist.location + lib_dir = os.path.join(dist_loc, 'bfps') __version__ = _dist.version except DistributionNotFound: __version__ = '' @@ -49,7 +49,7 @@ except DistributionNotFound: install_info = pickle.load( open(os.path.join(os.path.dirname(here), 'install_info.pickle'), - 'r')) + 'rb')) from .code import code from .fluid_converter import fluid_converter diff --git a/bfps/base.py b/bfps/base.py index 528db8260fc561890481feaba56a116a29902abb..1301fe65d465066134755c1e10d6b72d707c3236 100644 --- a/bfps/base.py +++ b/bfps/base.py @@ -25,6 +25,7 @@ import os +import sys import numpy as np import h5py import bfps @@ -48,8 +49,7 @@ class base(object): self.simname = simname return None def cdef_pars(self): - key = self.parameters.keys() - key.sort() + key = sorted(list(self.parameters.keys())) src_txt = '' for i in range(len(key)): if type(self.parameters[key[i]]) == int: @@ -60,21 +60,18 @@ class base(object): src_txt += 'double ' + key[i] + ';\n' return src_txt def cread_pars(self): - key = self.parameters.keys() - key.sort() + key = sorted(list(self.parameters.keys())) src_txt = ('int read_parameters(hid_t data_file_id)\n{\n' + 'hid_t dset, memtype, space;\n' + 'hsize_t dims[1];\n' - + 'char *string_data;\n' - + 'std::string tempstr;\n') + + 'char *string_data;\n') for i in range(len(key)): src_txt += 'dset = H5Dopen(data_file_id, "parameters/{0}", H5P_DEFAULT);\n'.format(key[i]) if type(self.parameters[key[i]]) == int: src_txt += 'H5Dread(dset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &{0});\n'.format(key[i]) elif type(self.parameters[key[i]]) == str: src_txt += ('space = H5Dget_space(dset);\n' + - 'memtype = H5Tcopy(H5T_C_S1);\n' + - 'H5Tset_size(memtype, H5T_VARIABLE);\n' + + 'memtype = H5Dget_type(dset);\n' + 'H5Sget_simple_extent_dims(space, dims, NULL);\n' + 'string_data = (char*)malloc(dims[0]*sizeof(char));\n' + 'H5Dread(dset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, &string_data);\n' + @@ -88,8 +85,7 @@ class base(object): src_txt += 'return 0;\n}\n' # finishing read_parameters return src_txt def cprint_pars(self): - key = self.parameters.keys() - key.sort() + key = sorted(list(self.parameters.keys())) src_txt = '' for i in range(len(key)): if type(self.parameters[key[i]]) == int: @@ -104,7 +100,14 @@ class base(object): os.makedirs(self.work_dir) ofile = h5py.File(os.path.join(self.work_dir, self.simname + '.h5'), 'w-') for k in self.parameters.keys(): - ofile['parameters/' + k] = self.parameters[k] + if (type(self.parameters[k]) == str) and (sys.version[0] == 3): + ofile.create_dataset('parameters/' + k, + (1,), + dtype = 'S10') + #ofile['parameters/' + k] = self.parameters[k].encode('ascii', 'ignore') + #print (ofile['parameters/' + k]) + else: + ofile['parameters/' + k] = self.parameters[k] ofile['iteration'] = int(iter0) for k in bfps.install_info.keys(): ofile['install_info/' + k] = str(bfps.install_info[k]) diff --git a/bfps/code.py b/bfps/code.py index 478ef8ad9b61c6f3e1d76bdb2c650f9060787103..e8baced47d29812354974f3b8f44cda896b5ff67 100644 --- a/bfps/code.py +++ b/bfps/code.py @@ -24,10 +24,11 @@ -import h5py -import subprocess import os +import sys import shutil +import subprocess +import h5py from datetime import datetime import math import bfps @@ -139,7 +140,8 @@ class code(base): raise IOError('header not there:\n' + '{0}\n'.format(os.path.join(bfps.header_dir, 'base.hpp')) + '{0}\n'.format(bfps.dist_loc)) - libraries = ['bfps'] + bfps.install_info['libraries'] + libraries = ['bfps'] + libraries += bfps.install_info['libraries'] command_strings = ['g++'] command_strings += [self.name + '.cpp', '-o', self.name] diff --git a/bfps/cpp/fftw_tools.cpp b/bfps/cpp/fftw_tools.cpp index c9e685268c1fda92881798670933ca0c455f6420..f6eacbf1dfe2dfe31e603e9239c42d4639327d3d 100644 --- a/bfps/cpp/fftw_tools.cpp +++ b/bfps/cpp/fftw_tools.cpp @@ -28,9 +28,7 @@ #include "base.hpp" #include "fftw_tools.hpp" -//#ifdef NDEBUG -//#undef NDEBUG -//#endif//NDEBUG +#define NDEBUG template <class rnumber> int clip_zero_padding( diff --git a/bfps/cpp/field_descriptor.cpp b/bfps/cpp/field_descriptor.cpp index 87f25a169accb92d185cbda8dbed4753846cba14..b5025835903a37ea5384cb4102c716f527aabfe5 100644 --- a/bfps/cpp/field_descriptor.cpp +++ b/bfps/cpp/field_descriptor.cpp @@ -22,10 +22,9 @@ * * **********************************************************************/ -// code is generally compiled via setuptools, therefore NDEBUG is present -//#ifdef NDEBUG -//#undef NDEBUG -//#endif//NDEBUG + + +#define NDEBUG #include <stdlib.h> #include <algorithm> diff --git a/bfps/cpp/fluid_solver.cpp b/bfps/cpp/fluid_solver.cpp index 04b4aa5a1c88ee40bc70b0ad62b88f6d35935280..880d4f695fc513ddd6d4d931bf08ff83e2a5f5d6 100644 --- a/bfps/cpp/fluid_solver.cpp +++ b/bfps/cpp/fluid_solver.cpp @@ -22,10 +22,9 @@ * * **********************************************************************/ -// code is generally compiled via setuptools, therefore NDEBUG is present -//#ifdef NDEBUG -//#undef NDEBUG -//#endif//NDEBUG + + +#define NDEBUG #include <cassert> #include <cmath> diff --git a/bfps/cpp/fluid_solver_base.cpp b/bfps/cpp/fluid_solver_base.cpp index d570f80f98d3be1a990c56592b192fc97478e21a..7f191f88da6cee5bfbd23b423e5b956dd2a3906a 100644 --- a/bfps/cpp/fluid_solver_base.cpp +++ b/bfps/cpp/fluid_solver_base.cpp @@ -22,10 +22,9 @@ * * **********************************************************************/ -// code is generally compiled via setuptools, therefore NDEBUG is present -//#ifdef NDEBUG -//#undef NDEBUG -//#endif//NDEBUG + + +#define NDEBUG #include <cassert> #include <cmath> diff --git a/bfps/cpp/slab_field_particles.cpp b/bfps/cpp/slab_field_particles.cpp index 3988659a0caba5eb46fd2070b178f68a5694a343..15fa363f6d277d34c6081fd545c4578e1f735929 100644 --- a/bfps/cpp/slab_field_particles.cpp +++ b/bfps/cpp/slab_field_particles.cpp @@ -22,10 +22,9 @@ * * **********************************************************************/ -// code is generally compiled via setuptools, therefore NDEBUG is present -//#ifdef NDEBUG -//#undef NDEBUG -//#endif//NDEBUG + + +#define NDEBUG #include <cmath> diff --git a/bfps/cpp/tracers.cpp b/bfps/cpp/tracers.cpp index 5e0e106ea658741fdf1b1bb209e100b22474504c..3d9fbfb6a1e357d70452466b6cc901659444539d 100644 --- a/bfps/cpp/tracers.cpp +++ b/bfps/cpp/tracers.cpp @@ -22,10 +22,9 @@ * * **********************************************************************/ -// code is generally compiled via setuptools, therefore NDEBUG is present -//#ifdef NDEBUG -//#undef NDEBUG -//#endif//NDEBUG + + +#define NDEBUG #include <cmath> diff --git a/bfps/fluid_converter.py b/bfps/fluid_converter.py index b448d8db870303bc7b8822277711b7db198a527a..04f113c4ed44d99fb020d4a782bb7d28ae09adbb 100644 --- a/bfps/fluid_converter.py +++ b/bfps/fluid_converter.py @@ -37,12 +37,14 @@ class fluid_converter(bfps.fluid_base.fluid_particle_base): name = 'fluid_converter', work_dir = './', simname = 'test', - fluid_precision = 'single'): + fluid_precision = 'single', + use_fftw_wisdom = True): super(fluid_converter, self).__init__( name = name, work_dir = work_dir, simname = simname, - dtype = fluid_precision) + dtype = fluid_precision, + use_fftw_wisdom = use_fftw_wisdom) self.parameters['write_rvelocity'] = 1 self.parameters['write_rvorticity'] = 1 self.parameters['fluid_name'] = 'test' diff --git a/bfps/fluid_resize.py b/bfps/fluid_resize.py index c022627931c29534c24f26934504712def959e90..5c4e6c5ed001c9ca698d19824677c335a6a0ff53 100644 --- a/bfps/fluid_resize.py +++ b/bfps/fluid_resize.py @@ -35,12 +35,14 @@ class fluid_resize(bfps.fluid_base.fluid_particle_base): name = 'fluid_resize', work_dir = './', simname = 'test', - dtype = np.float32): + dtype = np.float32, + use_fftw_wisdom = False): super(fluid_resize, self).__init__( name = name, work_dir = work_dir, simname = simname, - dtype = dtype) + dtype = dtype, + use_fftw_wisdom = use_fftw_wisdom) self.parameters['src_simname'] = 'test' self.parameters['dst_iter'] = 0 self.parameters['dst_nx'] = 32 diff --git a/done.txt b/done.txt new file mode 100644 index 0000000000000000000000000000000000000000..11abcd19add0332fa2b7a91b4dc24fde68c17b57 --- /dev/null +++ b/done.txt @@ -0,0 +1 @@ +x 2015-12-04 make code py3 compatible @python3 diff --git a/setup.py b/setup.py index ae97c93421499a46f260781ed8a1b0722ec2b42a..5ef07d2904e9fd111aba3f105bc87f27f53a9f3a 100644 --- a/setup.py +++ b/setup.py @@ -31,6 +31,7 @@ import pickle AUTHOR = 'Cristian C Lalescu' AUTHOR_EMAIL = 'Cristian.Lalescu@ds.mpg.de' +import os import datetime import subprocess from subprocess import CalledProcessError @@ -61,8 +62,8 @@ src_file_list = ['field_descriptor', header_list = ['cpp/base.hpp'] + ['cpp/' + fname + '.hpp' for fname in src_file_list] -# not sure we need the MANIFEST.in file, but I might as well #with open('MANIFEST.in', 'w') as manifest_in_file: +# manifest_in_file.write('include libbfps.a\n') # for fname in ['bfps/cpp/' + fname + '.cpp' for fname in src_file_list] + header_list: # manifest_in_file.write('include {0}\n'.format(fname)) @@ -83,22 +84,45 @@ pickle.dump( open('bfps/install_info.pickle', 'wb'), protocol = 2) -from setuptools import setup, Extension - -libbfps = Extension( - 'libbfps', - sources = ['bfps/cpp/' + fname + '.cpp' for fname in src_file_list], - include_dirs = include_dirs, - libraries = libraries, - extra_compile_args = extra_compile_args, - library_dirs = library_dirs) +from distutils.command.build import build as DistutilsBuild + +class CustomBuild(DistutilsBuild): + def run(self): + # compile bfps library + if not os.path.isdir('obj'): + os.makedirs('obj') + for fname in src_file_list: + ifile = 'bfps/cpp/' + fname + '.cpp' + ofile = 'obj/' + fname + '.o' + if not os.path.exists(ofile): + need_to_compile = True + else: + need_to_compile = (datetime.datetime.fromtimestamp(os.path.getctime(ofile)) < + datetime.datetime.fromtimestamp(os.path.getctime(ifile))) + if need_to_compile: + command_strings = ['g++', '-c'] + command_strings += ['bfps/cpp/' + fname + '.cpp'] + command_strings += ['-o', 'obj/' + fname + '.o'] + command_strings += extra_compile_args + command_strings += ['-I' + idir for idir in include_dirs] + command_strings.append('-Ibfps/cpp/') + print(' '.join(command_strings)) + subprocess.call(command_strings) + command_strings = ['ar', 'rvs', 'bfps/libbfps.a'] + command_strings += ['obj/' + fname + '.o' for fname in src_file_list] + print(' '.join(command_strings)) + subprocess.call(command_strings) + DistutilsBuild.run(self) + +from setuptools import setup setup( name = 'bfps', packages = ['bfps'], install_requires = ['numpy>=1.8', 'h5py>=2.2.1'], - ext_modules = [libbfps], + cmdclass={'build': CustomBuild}, package_data = {'bfps': header_list + ['../machine_settings.py', + 'libbfps.a', 'install_info.pickle']}, ######################################################################## # useless stuff folows diff --git a/tests/test_convergence.py b/tests/test_convergence.py index 0b27504d10c275c79fabb4aa5df8fb715758a1b9..636dea9bc9487241b62166d35ac7367272e513b3 100755 --- a/tests/test_convergence.py +++ b/tests/test_convergence.py @@ -71,7 +71,9 @@ def convergence_test( code_class = code_class, tracer_state_file = h5py.File(os.path.join(c0.work_dir, c0.simname + '.h5'), 'r')) # get real space fields - converter = bfps.fluid_converter(fluid_precision = opt.precision) + converter = bfps.fluid_converter( + fluid_precision = opt.precision, + use_fftw_wisdom = False) converter.write_src() converter.set_host_info({'type' : 'pc'}) for c in [c0, c1, c2]: diff --git a/tests/test_plain.py b/tests/test_plain.py index 596eb0e9323c81e4d0c8c504b093aa2b1c95b0f9..a4f032ccf535057e4a89ef0cac7080d4673beff2 100755 --- a/tests/test_plain.py +++ b/tests/test_plain.py @@ -46,12 +46,12 @@ def plain(opt): assert(opt.niter_todo % 3 == 0) opt.work_dir = wd + '/N{0:0>3x}_2'.format(opt.n) opt.njobs *= 2 - opt.niter_todo /= 2 + opt.niter_todo = opt.niter_todo//2 c1 = launch(opt, dt = c0.parameters['dt']) c1.compute_statistics() opt.work_dir = wd + '/N{0:0>3x}_3'.format(opt.n) - opt.njobs = 3*opt.njobs/2 - opt.niter_todo = 2*opt.niter_todo/3 + opt.njobs = 3*opt.njobs//2 + opt.niter_todo = 2*opt.niter_todo//3 c2 = launch(opt, dt = c0.parameters['dt']) c2.compute_statistics() # plot energy and enstrophy diff --git a/todo.txt b/todo.txt index 41973e4e1db5181dcde4bed763ea8e3d54288075..c25b79d183a098e3384e324612b4255696157c12 100644 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,5 @@ (B) use less memory @optimization (C) code overview @documentation -(C) make code py3 compatible @python3 (C) test involving hydrodynamic similarity @tests (C) use HDF5 io for fields @HDF5 +I/O (D) test anisotropic grids @tests diff --git a/tox_convergence.ini b/tox_convergence.ini index 447e32fe9a7ffa2fc7adbcd9e07ca464785b8700..39a368ff0d1954cb841cbaab41e5a8d98bb68031 100644 --- a/tox_convergence.ini +++ b/tox_convergence.ini @@ -1,6 +1,7 @@ [tox] -envlist = py27 +envlist = py34 [testenv] +deps = matplotlib whitelist_externals = echo cp diff --git a/tox_io.ini b/tox_io.ini index 994d35525286ef31df4a896a341f796287c3ba2e..de8c2fc5d0bb5fa7498527ecb4b96b32ca000c69 100644 --- a/tox_io.ini +++ b/tox_io.ini @@ -1,6 +1,7 @@ [tox] -envlist = py27 +envlist = py27, py34 [testenv] +deps = matplotlib whitelist_externals = echo cp diff --git a/tox_plain.ini b/tox_plain.ini index 1af8e3cd72aeb99524d339dbf9cd13ca306d1f2a..ad816b8378eab61dcfcc679f9704bffa09e6cb78 100644 --- a/tox_plain.ini +++ b/tox_plain.ini @@ -1,6 +1,7 @@ [tox] -envlist = py27 +envlist = py34 [testenv] +deps = matplotlib whitelist_externals = echo cp