From e8ee7af12fada360ec4a1704fc0c2a4a9c1e85c3 Mon Sep 17 00:00:00 2001 From: David Ketcheson Date: Mon, 30 Oct 2023 13:49:50 +0300 Subject: [PATCH 1/2] Update meson build to include fortran extensions for examples. Also fix a bug in which the SharpClaw fortran extensions were not properly compiled. --- examples/acoustics_2d_mapped/__init__.py | 0 examples/euler_1d/shocksine.py | 26 +-- examples/euler_1d/woodward_colella_blast.py | 38 +--- examples/shallow_sphere/Rossby_wave.py | 20 +- src/pyclaw/meson.build | 201 +++++++++++++++++++- 5 files changed, 212 insertions(+), 73 deletions(-) create mode 100644 examples/acoustics_2d_mapped/__init__.py diff --git a/examples/acoustics_2d_mapped/__init__.py b/examples/acoustics_2d_mapped/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/examples/euler_1d/shocksine.py b/examples/euler_1d/shocksine.py index b4d69eb17..97e271c61 100755 --- a/examples/euler_1d/shocksine.py +++ b/examples/euler_1d/shocksine.py @@ -59,26 +59,12 @@ def setup(use_petsc=False,iplot=False,htmlplot=False,outdir='./_output',solver_t solver.cfl_desired = 0.6 solver.cfl_max = 0.7 if use_char_decomp: - try: - from . import sharpclaw1 # Import custom Fortran code - solver.fmod = sharpclaw1 - solver.tfluct_solver = tfluct_solver # Use total fluctuation solver for efficiency - if solver.tfluct_solver: - try: - from . import euler_tfluct - solver.tfluct = euler_tfluct - except ImportError: - import logging - logger = logging.getLogger() - logger.error('Unable to load tfluct solver, did you run make?') - print('Unable to load tfluct solver, did you run make?') - raise - except ImportError: - import logging - logger = logging.getLogger() - logger.error('Unable to load sharpclaw1 solver, did you run make?') - print('Unable to load sharpclaw1 solver, did you run make?') - pass + from pyclaw.sharpclaw import euler_sharpclaw1 # Import custom Fortran code + solver.fmod = euler_sharpclaw1 + solver.tfluct_solver = tfluct_solver # Use total fluctuation solver for efficiency + if solver.tfluct_solver: + from pyclaw.sharpclaw import euler_tfluct + solver.tfluct = euler_tfluct solver.lim_type = 2 # WENO reconstruction solver.char_decomp = 2 # characteristic-wise reconstruction else: diff --git a/examples/euler_1d/woodward_colella_blast.py b/examples/euler_1d/woodward_colella_blast.py index 553ce3656..e6b8b238b 100755 --- a/examples/euler_1d/woodward_colella_blast.py +++ b/examples/euler_1d/woodward_colella_blast.py @@ -27,26 +27,6 @@ from clawpack import riemann from clawpack.riemann.euler_with_efix_1D_constants import * -# Compile Fortran code if not already compiled -try: - from clawpack.pyclaw.examples.euler_1d import sharpclaw1 -except ImportError: - import os - from clawpack.pyclaw.util import inplace_build - this_dir = os.path.dirname(__file__) - if this_dir == '': - this_dir = os.path.abspath('.') - inplace_build(this_dir) - try: - # Now try to import again - from clawpack.pyclaw.examples.euler_1d import sharpclaw1 - except ImportError: - import logging - logger = logging.getLogger() - logger.warn('unable to compile Fortran modules; some SharpClaw options will not be available for this example') - print('unable to compile Fortran modules; some SharpClaw options will not be available for this example') - raise - gamma = 1.4 # Ratio of specific heats def setup(use_petsc=False,outdir='./_output',solver_type='sharpclaw',kernel_language='Fortran',tfluct_solver=True): @@ -68,22 +48,12 @@ def setup(use_petsc=False,outdir='./_output',solver_type='sharpclaw',kernel_lang solver.cfl_desired = 0.6 solver.tfluct_solver = tfluct_solver if solver.tfluct_solver: - try: - from clawpack.pyclaw.examples.euler_1d import euler_tfluct - solver.tfluct = euler_tfluct - except ImportError: - import logging - logger = logging.getLogger() - logger.error('Unable to load tfluct solver, did you run make?') - print('Unable to load tfluct solver, did you run make?') - raise + from clawpack.pyclaw.examples.euler_1d import euler_tfluct + solver.tfluct = euler_tfluct solver.lim_type = 1 solver.char_decomp = 2 - try: - from clawpack.pyclaw.examples.euler_1d import sharpclaw1 - solver.fmod = sharpclaw1 - except ImportError: - pass + from clawpack.pyclaw.sharpclaw import euler_sharpclaw1 + solver.fmod = euler_sharpclaw1 elif solver_type=='classic': solver = pyclaw.ClawSolver1D(rs) solver.limiters = 4 diff --git a/examples/shallow_sphere/Rossby_wave.py b/examples/shallow_sphere/Rossby_wave.py index 7310d0019..1c86bf20f 100755 --- a/examples/shallow_sphere/Rossby_wave.py +++ b/examples/shallow_sphere/Rossby_wave.py @@ -27,24 +27,8 @@ from clawpack.pyclaw.util import inplace_build from six.moves import range -try: - from clawpack.pyclaw.examples.shallow_sphere import problem - from clawpack.pyclaw.examples.shallow_sphere import classic2 - -except ImportError: - this_dir = os.path.dirname(__file__) - if this_dir == '': - this_dir = os.path.abspath('.') - inplace_build(this_dir) - - try: - # Now try to import again - from clawpack.pyclaw.examples.shallow_sphere import problem - from clawpack.pyclaw.examples.shallow_sphere import classic2 - except ImportError: - print("***\nUnable to import problem module or automatically build, try running (in the directory of this file):\n python setup.py build_ext -i\n***", file=sys.stderr) - raise - +from clawpack.pyclaw.examples.shallow_sphere import sw_sphere_problem +from clawpack.pyclaw.classic import classic2_sw_sphere as classic2 # Nondimensionalized radius of the earth Rsphere = 1.0 diff --git a/src/pyclaw/meson.build b/src/pyclaw/meson.build index 6cc522b94..3203ed4bd 100644 --- a/src/pyclaw/meson.build +++ b/src/pyclaw/meson.build @@ -57,6 +57,169 @@ foreach subpkg, subsrcs: python_sources ) endforeach +examples = { + '' : [ + '__init__.py' + ], + 'acoustics_1d_homogeneous' : [ + '__init__.py', + 'acoustics_1d.py', + 'test_acoustics.py', + ], + 'acoustics_2d_homogeneous' : [ + '__init__.py', + 'acoustics_2d.py', + 'test_2d_acoustics.py', + ], + 'acoustics_2d_mapped' : [ + '__init__.py', + 'acoustics_2d_inclusions.py', + 'test_acoustics_2d_mapped.py', + ], + 'acoustics_2d_variable' : [ + '__init__.py', + 'acoustics_2d_interface.py', + 'test_acoustics_2d_variable.py', + 'test_acoustics_2d_variable_io.py', + ], + 'acoustics_3d_variable' : [ + '__init__.py', + 'acoustics_3d_interface.py', + 'test_3d_acoustics.py', + ], + 'advection_1d' : [ + '__init__.py', + 'advection_1d.py', + 'advection_1d_nonunif.py', + 'test_advection.py', + 'test_advection_nonunif.py', + ], + 'advection_1d_variable' : [ + '__init__.py', + 'variable_coefficient_advection.py', + ], + 'advection_2d' : [ + '__init__.py', + 'advection_2d.py', + ], + 'advection_2d_annulus' : [ + '__init__.py', + 'advection_annulus.py', + 'mapc2p.py', + ], + 'advection_reaction_2d' : [ + '__init__.py', + 'advection_reaction.py', + 'test_advection_reaction.py', + ], + 'burgers_1d' : [ + '__init__.py', + 'burgers_1d.py', + ], + 'cubic_1d' : [ + '__init__.py', + 'cubic.py', + 'test_cubic.py', + ], + 'euler_1d' : [ + '__init__.py', + 'shocksine.py', + 'shocktube.py', + 'test_shocksine.py', + 'test_shocktube.py', + 'test_woodward_colella_blast.py', + 'woodward_colella_blast.py', + ], + 'euler_2d' : [ + '__init__.py', + 'euler_2d.py', + 'quadrants.py', + 'shock_bubble_interaction.py', + 'shock_forward_step.py', + 'test_euler2d_shockbubble.py', + 'test_quadrants.py', + ], + 'euler_3d' : [ + 'Sedov.py', + '__init__.py', + 'shock_bubble.py', + 'shocktube.py', + 'test_sedov_and_hdf.py', + ], + 'euler_gravity_3d' : [ + 'plotCreateVisitXDMF.py', + 'rising_hot_sphere.py', + 'rising_hot_sphere_spherical.py', + 'test_rising_hot_sphere.py', + 'visitHDF5XDMF.py', + ], + 'iso_c_advection' : [ + '__init__.py', + 'iso_c_advection.py', + 'iso_c_solver.py', + ], + 'kpp' : [ + '__init__.py', + 'kpp.py', + ], + 'mhd_1d' : [ + '__init__.py', + 'shocktube.py', + 'test_shocktube.py', + ], + 'peano_shallow_2d' : [ + 'setplot.py', + 'shallow2D.py', + 'test_identical_grids.py', + 'test_peano_solver.py', + ], + 'psystem_2d' : [ + '__init__.py', + 'psystem_2d.py', + 'test_2d_psystem.py', + ], + 'shallow_1d' : [ + '__init__.py', + 'dam_break.py', + 'sill.py', + 'test_dambreak.py', + 'test_sill.py', + ], + 'shallow_2d' : [ + '__init__.py', + 'radial_dam_break.py', + 'sill.py', + 'test_dambreak.py', + 'test_sill.py', + ], + 'shallow_sphere' : [ + '__init__.py', + 'setplot.py', + 'test_shallow_sphere.py', + 'Rossby_wave.py', + ], + 'stegoton_1d' : [ + '__init__.py', + 'stegoton.py', + 'test_stego.py', + ], + 'traffic' : [ + '__init__.py', + 'traffic.py', + ], +} + +foreach ex, exsrcs: examples + sources = [] + foreach src: exsrcs + sources += '../../examples' / ex / src + endforeach + py.install_sources( + sources, + subdir: pkg_dir / 'examples' / ex + ) +endforeach + py.install_sources( 'log.config', subdir: pkg_dir @@ -67,14 +230,20 @@ fortran_extensions = { 'classic1': ['limiter.f90','philim.f90','step1.f90'], 'classic2': ['limiter.f90','philim.f90','flux2.f90','step2ds.f90','step2.f90'], 'classic3': ['limiter.f90','philim.f90','flux3.f90','step3ds.f90','step3.f90'], + 'classic2_sw_sphere': ['limiter.f90','philim.f90','flux2.f90','step2ds.f90','../../../examples/shallow_sphere/step2qcor.f90','../../../examples/shallow_sphere/qcor.f90'], }, 'sharpclaw': { 'sharpclaw1': ['ClawParams.f90','weno.f90','reconstruct.f90','evec.f90','workspace.f90','flux1.f90'], 'sharpclaw2': ['ClawParams.f90','weno.f90','reconstruct.f90','evec.f90','workspace.f90','flux2.f90','flux1.f90'], 'sharpclaw3': ['ClawParams.f90','weno.f90','reconstruct.f90','evec.f90','workspace.f90','flux3.f90','flux1.f90'], + # 1D Euler with characteristic decomposition for SharpClaw limiting + 'euler_sharpclaw1': ['ClawParams.f90','weno.f90','reconstruct.f90','../../../examples/euler_1d/evec.f90','workspace.f90','flux1.f90'], + 'euler_tfluct1': ['../../../examples/euler_1d/euler_tfluct.f90'], }, } +numpy_nodepr_api = '-DNPY_NO_DEPRECATED_API=NPY_1_9_API_VERSION' + foreach subpkg, module: fortran_extensions srcdir = join_paths(subpkg.split('.')) foreach ext_name, sources : module @@ -82,14 +251,20 @@ foreach subpkg, module: fortran_extensions foreach src: sources ext_srcs += srcdir / src endforeach + f2py_extra = [] + #if subpkg == 'sharpclaw' + if 'ClawParams.f90' in sources + f2py_extra += ext_name + '-f2pywrappers2.f90' + endif f2py_srcs = custom_target( command: [f2py, ext_name], input: ext_srcs, - output: [ext_name + 'module.c', ext_name + '-f2pywrappers.f'], + output: [ext_name + 'module.c', ext_name + '-f2pywrappers.f', f2py_extra], ) py.extension_module( ext_name, [ext_srcs, f2py_srcs], incdir_f2py / 'fortranobject.c', + c_args: [numpy_nodepr_api], include_directories: inc_np, dependencies : py_dep, subdir: 'clawpack/pyclaw/' + srcdir, @@ -106,3 +281,27 @@ py.extension_module( subdir: 'clawpack/pyclaw/limiters/weno', install : true ) + +# Special extensions for examples + +ext_name = 'sw_sphere_problem' +ext_srcs = [ + '../../examples/shallow_sphere/mapc2p.f90', + '../../examples/shallow_sphere/setaux.f90', + '../../examples/shallow_sphere/qinit.f90', + '../../examples/shallow_sphere/src2.f90', +] +f2py_srcs = custom_target( + command: [f2py, ext_name], + input: ext_srcs, + output: [ext_name + 'module.c', ext_name + '-f2pywrappers.f'], +) + +py.extension_module( + ext_name, [ext_srcs, f2py_srcs], + incdir_f2py / 'fortranobject.c', + include_directories: inc_np, + dependencies : py_dep, + subdir: 'clawpack/pyclaw/examples/shallow_sphere', + install : true +) From d7094efff53c926740a0503b45a83206de2d6c34 Mon Sep 17 00:00:00 2001 From: David Ketcheson Date: Tue, 31 Oct 2023 11:46:44 +0300 Subject: [PATCH 2/2] Use CLAW env variable to set path for editable installs. The old approach doesn't work with meson, but this does. --- src/pyclaw/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pyclaw/__init__.py b/src/pyclaw/__init__.py index 448cf36a4..6c9a62ea9 100644 --- a/src/pyclaw/__init__.py +++ b/src/pyclaw/__init__.py @@ -5,8 +5,11 @@ import logging, logging.config +CLAW_dir = os.environ.get('CLAW') +if CLAW_dir == None: + raise Exception('You must set the CLAW environment to use an editable install.') # To get pyclaw.examples -_path = os.path.dirname(os.path.dirname(__path__[0])) +_path = os.path.dirname(os.path.join(CLAW_dir, 'clawpack')) if os.path.isdir(_path): __path__.append(_path) del _path