Skip to content

Commit c290253

Browse files
mandliketch
andauthored
Add Testing Matrix (#748)
* Add initial testing matrix * Fix bugs in testing script * Add macos to testing * Cleanup some source that was failing via pyflake * Tweak flake8 call * Limit build options and python versions to see if the testing can pass again * Try using current numpy * Verbose pytest output. * Add test summary action * Restrict coverage uploading to one config * Fix errant . * Correct some github action syntax bugs * Correct missing path info * Fix bad path/naming again * Fix another path problem * Try confusing pathing fix * Fix linting path * One more try at getting pathing right * This is on me, clearly I cannot deal with paths * Turn off fast fail * Adjust archive source file path * Uniquely identify test results * Fix missing variable declarations in archiving step * Do not capture output in pytest * Update the expected dimension of limiters array. For sharpclaw, this is sometimes num_eqn and sometimes num_waves depending on options. * Make sure limiters is a list. * Fix stupid bug I just introduced. * Avoid explicitly indexing into empty aux array. * Remove debugging print statements. * Add a space to re-trigger tests on Github. * Expand grid for 3D acoustics test. * Test if WENO limiting passes for 3D acoustics. --------- Co-authored-by: David Ketcheson <dketch@gmail.com>
1 parent 2caf7ec commit c290253

8 files changed

Lines changed: 142 additions & 49 deletions

File tree

.github/workflows/testing.yml

Lines changed: 105 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Test PyClaw
1+
name: Test PyClaw
22

33
on:
44
push:
@@ -15,20 +15,53 @@ env:
1515
CLAW: ${{ github.workspace }}
1616

1717
jobs:
18-
build:
19-
runs-on: ubuntu-latest
18+
tests:
19+
name: >
20+
${{ matrix.os }} - py ${{ matrix.python-version }} - ${{ matrix.toolchain.compiler }} ${{ matrix.build }}
21+
runs-on: ${{ matrix.os }}
22+
strategy:
23+
fail-fast: false # Probably want to turn this off for a large matrix
24+
matrix:
25+
os: [ubuntu-latest, macos-latest]
26+
python-version: ["3.12"]
27+
build: [debug, opt]
28+
toolchain:
29+
- {compiler: gcc, version: 14}
30+
- {compiler: gcc, version: 15}
31+
# - {compiler: intel, version: '2025.0'}
32+
# - {compiler: intel-classic, version: '2021.10'}
33+
# - {compiler: nvidia-hpc, version: '25.1'} # does not build python
34+
# - {compiler: lfortran, version: '0.45.0'} # lfortran not yet supported
35+
# - {compiler: flang, version: '20.1.0'} # flang not yet supported
36+
# include:
37+
# - os: ubuntu-latest
38+
# python-version: 3.10
39+
# build: opt
40+
# toolchain: {compiler: gcc, version: 14}
41+
exclude:
42+
- os: ubuntu-latest
43+
toolchain: {compiler: gcc, version: 15}
44+
- os: macos-latest
45+
toolchain: {compiler: gcc, version: 14}
46+
2047
steps:
21-
- name: Set up Python 3.10
48+
- name: Set up Python ${{ matrix.python-version }}
2249
uses: actions/setup-python@v5
2350
with:
24-
python-version: "3.10"
25-
- name: Install dependencies
26-
run: |
27-
sudo apt-get update
28-
sudo apt-get install gfortran
51+
python-version: ${{ matrix.python-version }}
52+
53+
- name: Set up compilers
54+
uses: fortran-lang/setup-fortran@v1
55+
id: setup-fortran
56+
with:
57+
compiler: ${{ matrix.toolchain.compiler }}
58+
version: ${{ matrix.toolchain.version }}
2959

60+
- name: Install python dependencies
61+
run: |
3062
python -m pip install --upgrade pip
31-
pip install 'numpy<2.0'
63+
# pip install 'numpy<2.0'
64+
pip install numpy
3265
pip install matplotlib #Some imports require matplotlib
3366
pip install scipy #To not skip tests
3467
pip install flake8 meson-python ninja pytest coveralls
@@ -44,21 +77,77 @@ jobs:
4477
uses: actions/checkout@v4.1.5
4578
with:
4679
path: pyclaw
47-
80+
4881
- name: Install clawpack
4982
run: |
50-
cd ${CLAW}
83+
if [ "${{ matrix.toolchain.compiler }}" = "gcc" ]; then
84+
if [ "${{ matrix.build }}" = "debug" ]; then
85+
export FFLAGS="-O0 -g -fcheck=all -fbacktrace -fbounds-check -ffpe-trap=invalid,zero,overflow -finit-real=nan -finit-integer=nan -Wall -Wunderflow -Wextra -Wconversion -Wuninitialized -Warray-bounds -Wshadow -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-unused-label -Wno-unused-but-set-variable"
86+
export CFLAGS=""
87+
elif [ "${{ matrix.build }}" = "opt" ]; then
88+
# export FFLAGS="-O1 -funroll-loops -finline-functions -ftree-vectorize -fstack-protector-strong -flto -march=native"
89+
export FFLAGS=""
90+
export CFLAGS=""
91+
else
92+
echo "Unknown build type: ${{ matrix.build }}"
93+
exit 1
94+
fi
95+
elif [ "${{ matrix.toolchain.compiler }}" = "intel" ] || [ "${{ matrix.toolchain.compiler }}" = "intel-classic" ]; then
96+
if [ "${{ matrix.build }}" = "debug" ]; then
97+
export FFLAGS=""
98+
export CFLAGS=""
99+
elif [ "${{ matrix.build }}" = "opt" ]; then
100+
export FFLAGS=""
101+
export CFLAGS=""
102+
else
103+
echo "Unknown build type: ${{ matrix.build }}"
104+
exit 1
105+
fi
106+
else
107+
echo "Unknown compiler: ${{ matrix.toolchain.compiler }}"
108+
exit 1
109+
fi
110+
echo "Using `$FC --version`"
111+
echo "FFLAGS: $FFLAGS"
112+
echo "CFLAGS: $CFLAGS"
113+
cd ${{ env.CLAW }}
51114
pip install --no-build-isolation --editable .
52115
116+
- name: Lint with flake8
117+
if: ${{ matrix.build == 'debug' }}
118+
run: |
119+
cd ${{ env.CLAW }}/pyclaw
120+
# stop the build if there are Python syntax errors or undefined names
121+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude "development","src/pyclaw/fileio/netcdf.py"
122+
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
123+
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
124+
53125
- name: Test with pytest
54126
run: |
55-
cd ${CLAW}/pyclaw
56-
coverage run --source=src -m pytest --ignore=development -k "not test_shallow_sphere"
127+
cd ${{ env.CLAW }}/pyclaw
128+
coverage run --source=src -m pytest -vv -s --showlocals --ignore=development -k "not test_shallow_sphere" --junitxml=test-report.xml
57129
58-
- name: Upload to Coveralls
130+
- name: Process test results
131+
uses: test-summary/action@v2.4
132+
if: always()
133+
with:
134+
paths: ${{ env.CLAW }}/pyclaw/test-report.xml
135+
output: ${{ env.CLAW }}/pyclaw/test-summary.md
136+
show: "all"
137+
138+
- name: Upload test results
139+
# if: failure()
59140
if: always()
141+
uses: actions/upload-artifact@v4
142+
with:
143+
name: ${{ matrix.os }}-py${{ matrix.python-version }}-${{ matrix.toolchain.compiler }}-${{ matrix.build }}
144+
path: ${{ env.CLAW }}/pyclaw/test-summary.md
145+
if-no-files-found: ignore
146+
147+
- name: Upload to Coveralls
148+
if: ${{ matrix.os == 'ubuntu-latest' && matrix.toolchain.compiler == 'gcc' && matrix.build == 'opt' && matrix.python-version == '3.12' }}
60149
run: |
61-
cd ${CLAW}/pyclaw
150+
cd ${{ env.CLAW }}/pyclaw
62151
ls -l .coverage
63152
coveralls
64153
env:

cleanup_examples.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,32 @@
44
Cleans up by deleting object files, executable, and _output directory.
55
"""
66

7-
import os,sys,glob
7+
import os
8+
import sys
89
import shutil
910

1011
if __name__ == "__main__":
1112

1213
examples_dir = os.path.abspath('./examples')
13-
print "Will remove all _output, _plots, and build directories from ",examples_dir
14-
ans = raw_input("Ok? ")
14+
print(f"Will remove all _output, _plots, and build directories from {examples_dir}")
15+
ans = input("Ok? ")
1516
if ans.lower() not in ['y','yes']:
16-
print "Aborting."
17+
print("Aborting.")
1718
sys.exit()
1819

1920
os.chdir(examples_dir)
2021
exdirlist = []
2122
for (dirpath, subdirs, files) in os.walk('.'):
2223
currentdir = os.path.abspath(os.getcwd())
2324
os.chdir(os.path.abspath(dirpath))
24-
25-
print 'In directory ',dirpath
26-
25+
26+
print(f'In directory {dirpath}')
27+
2728
if os.path.isdir('_output'):
2829
shutil.rmtree('./_output')
2930
if os.path.isdir('_plots'):
3031
shutil.rmtree('./_plots')
3132
if os.path.isdir('build'):
3233
shutil.rmtree('./build')
33-
34-
os.chdir(currentdir)
3534

35+
os.chdir(currentdir)

examples/acoustics_3d_variable/acoustics_3d_interface.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def setup(use_petsc=False,outdir='./_output',solver_type='classic',
6464
if solver_type=='classic':
6565
solver.dimensional_split=True
6666
else:
67-
solver.lim_type = 1
67+
solver.lim_type = 2
6868

6969
solver.limiters = [4]
7070

examples/acoustics_3d_variable/test_3d_acoustics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
def check_error(**kwargs):
88

9-
claw = acoustics_3d_interface.setup(problem='homogeneous',mx=128,my=4,mz=4,disable_output=True,**kwargs)
9+
claw = acoustics_3d_interface.setup(problem='homogeneous',mx=128,my=8,mz=8,disable_output=True,**kwargs)
1010
claw.run()
1111

1212
test_pressure = claw.frames[-1].q[0,:,:,:]

examples/compare_solvers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,20 +160,20 @@ def compare_2D(nx=(250,250)):
160160
import sys
161161

162162
vis = True
163-
163+
164164
if vis:
165165
compare_solvers.outdir='./_output'
166166
else:
167167
compare_solvers.outdir = None
168-
168+
169169
if len(sys.argv) > 1:
170170
nx_1D = int(sys.argv[1])
171171
else:
172172
nx_1D = 500
173173

174174
if len(sys.argv) > 2:
175175
# '(2,2)' -> (2,2)
176-
nx_2D = tuple(int(i) for i in argv.split(','))
176+
nx_2D = tuple(int(i) for i in sys.argv.split(','))
177177
else:
178178
nx_2D = 100,100
179179

fvmbook/chap22/inclusion/inclusion.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Variable-coefficient elasticity example.
55
"""
66
import numpy as np
7-
from six.moves import range
7+
88
t0wall = 0.025
99
tperiod = 0.05
1010

@@ -13,20 +13,20 @@ def moving_wall_bc(state,dim,t,qbc,auxbc,num_ghost):
1313
if t<t0wall:
1414
s = np.sin(np.pi*t/tperiod)
1515
else:
16-
s = 0.
16+
s = 0.0
1717

1818
for i in range(num_ghost):
1919
# First reflect-extrapolate
2020
qbc[:,i,:] = qbc[:,2*num_ghost-i-1,:]
2121
# Now set velocity
2222
qbc[3,i,:] = 2.0*s - qbc[3,i,:]
2323
qbc[4,i,:] = - qbc[4,i,:]
24-
24+
2525

2626
#def no_stress_bc(state,dim,t,qbc,num_ghost):
2727
# """No-stress boundary condition: sigma_{12} = sigma_{11} = 0"""
2828
# if state.grid.on_lower_boundary[idim]:
29-
# jghost =
29+
# jghost =
3030
# # First extrapolate
3131
# tmp = qbc[:,:,self.num_ghost]
3232
# tmp = np.tile(tmp,(1,1,num_ghost))
@@ -35,8 +35,8 @@ def moving_wall_bc(state,dim,t,qbc,auxbc,num_ghost):
3535
# # Then negate the sig12 and sig11 components
3636

3737
def integrate_displacement(solver,state):
38-
aux[5,:,:] = aux[5,:,:] + dt*q[3,:,:]
39-
aux[6,:,:] = aux[6,:,:] + dt*q[4,:,:]
38+
state.aux[5,:,:] = state.aux[5,:,:] + solver.dt * state.q[3,:,:]
39+
state.aux[6,:,:] = state.aux[6,:,:] + solver.dt * state.q[4,:,:]
4040

4141

4242
def inclusion():
@@ -116,19 +116,19 @@ def inclusion():
116116
#--------------------------
117117
def setplot(plotdata):
118118
#--------------------------
119-
120-
"""
119+
120+
"""
121121
Specify what is to be plotted at each frame.
122122
Input: plotdata, an instance of visclaw.data.ClawPlotData.
123123
Output: a modified version of plotdata.
124-
125-
"""
124+
125+
"""
126126

127127

128128
from clawpack.visclaw import colormaps
129129

130130
plotdata.clearfigures() # clear any old figures,axes,items data
131-
131+
132132

133133
# Figure for pressure
134134
# -------------------
@@ -148,11 +148,11 @@ def setplot(plotdata):
148148
plotitem.pcolor_cmap = colormaps.yellow_red_blue
149149
plotitem.add_colorbar = True
150150
plotitem.show = True # show on plot?
151-
151+
152152

153153
# Figure for x-velocity plot
154154
# -----------------------
155-
155+
156156
plotfigure = plotdata.new_plotfigure(name='x-Velocity', figno=1)
157157

158158
# Set up for axes in this figure:
@@ -166,7 +166,7 @@ def setplot(plotdata):
166166
plotitem.pcolor_cmap = colormaps.yellow_red_blue
167167
plotitem.add_colorbar = True
168168
plotitem.show = True # show on plot?
169-
169+
170170
# Parameters used only when creating html and/or latex hardcopy
171171
# e.g., via visclaw.frametools.printframes:
172172

@@ -190,4 +190,3 @@ def setplot(plotdata):
190190

191191
from clawpack.pyclaw import plot
192192
plot.interactive_plot()
193-

src/pyclaw/classic/flux3.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ subroutine flux3(ixyz,maxm,num_eqn,num_waves,num_ghost,mx, &
199199

200200
! aux2(1-num_ghost,1,2) is the start of a 1d array now used by rpn3
201201
call rpn3(ixyz,maxm,num_eqn,num_waves,num_aux,num_ghost,mx,q1d,q1d, &
202-
aux2(1,1-num_ghost,2),aux2(1,1-num_ghost,2),wave,s,amdq,apdq)
202+
aux2(:,1-num_ghost,2),aux2(:,1-num_ghost,2),wave,s,amdq,apdq)
203203

204204
! Set qadd for the donor-cell upwind method (Godunov)
205205
forall (m = 1:num_eqn, i = 1:mx+1)

src/pyclaw/sharpclaw/solver.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -519,9 +519,14 @@ def check_3rd_ord_cond(self,state,step_index,dtFE):
519519
def _set_mthlim(self):
520520
self._mthlim = self.limiters
521521
if not isinstance(self.limiters,list): self._mthlim=[self._mthlim]
522-
if len(self._mthlim)==1: self._mthlim = self._mthlim * self.num_waves
523-
if len(self._mthlim)!=self.num_waves:
524-
raise Exception('Length of solver.limiters is not equal to 1 or to solver.num_waves')
522+
if self.char_decomp == 0: # entry-wise limiting
523+
if len(self._mthlim)==1: self._mthlim = self._mthlim * self.num_eqn
524+
if len(self._mthlim)!=self.num_eqn:
525+
raise Exception('Length of solver.limiters is not equal to 1 or to solver.num_eqn')
526+
else: # Wave-wise limiting
527+
if len(self._mthlim)==1: self._mthlim = self._mthlim * self.num_waves
528+
if len(self._mthlim)!=self.num_waves:
529+
raise Exception('Length of solver.limiters is not equal to 1 or to solver.num_waves')
525530

526531

527532
def dq(self,state):

0 commit comments

Comments
 (0)