Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix LaplacePetsc3dAmg #2237

Merged
merged 12 commits into from
Feb 17, 2021
Merged

Fix LaplacePetsc3dAmg #2237

merged 12 commits into from
Feb 17, 2021

Conversation

johnomotani
Copy link
Contributor

The bug in test-laplace-petsc3d that @ZedThree found (#2225) was hiding a couple of other bugs in ZInterpolationandZHermiteSpline` that made the matrix for 3d Laplace_perp inversion incorrect with non-trivial parallel derivatives. These bugs should be fixed by this PR.

I've also added some extra checks (when CHECK > 2) for finiteness of matrix elements and interpolation weights, and bounds of indices passed to getWeightsForYApproximation(), which helped to find the bugs.

Fixes #2225.

These are occasionally needed, and it only adds initialisation cost to
calculate them.
The method actually creates the intersection.

Fixes #2236.
getUnion() was misleadingly named, and actually gave the intersection.
Region::operator+=(Region) updates a Region to be the union of two
Regions, which is almost what was wanted, although we have to call
mask_region.unique() afterwards too to ensure there are no repeated
entries and the entries are sorted.
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

include/bout/petsc_interface.hxx Outdated Show resolved Hide resolved
include/bout/petsc_interface.hxx Outdated Show resolved Hide resolved
include/bout/petsc_interface.hxx Outdated Show resolved Hide resolved
include/bout/petsc_interface.hxx Show resolved Hide resolved
include/bout/petsc_interface.hxx Show resolved Hide resolved
include/bout/petsc_interface.hxx Outdated Show resolved Hide resolved
include/bout/petsc_interface.hxx Outdated Show resolved Hide resolved
include/bout/petsc_interface.hxx Outdated Show resolved Hide resolved
include/bout/petsc_interface.hxx Show resolved Hide resolved
include/bout/petsc_interface.hxx Show resolved Hide resolved
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

include/bout/petsc_interface.hxx Show resolved Hide resolved
include/bout/petsc_interface.hxx Show resolved Hide resolved
@johnomotani
Copy link
Contributor Author

Only the Fedora tests are failing, but they're only failing on the test that this PR is supposed to fix. It says a PETSc matrix element argument was out of range, but I've tested with PETSC-3.14.4 (same version as Fedora) and an identical ./configure --with-petsc --enable-shared (except I passed a path for petsc) and the test passes. @ZedThree @dschwoerer should I worry about the failure?

@ZedThree
Copy link
Member

It is a bit concerning, and I'd prefer to fix it if at all possible. I'll see if I can reproduce it locally.

@dschwoerer
Copy link
Contributor

dschwoerer commented Feb 17, 2021

I can reproduce it using the fedora packages.

petsc is compiled with (mpich)

./configure --build=x86_64-redhat-linux-gnu --host=x86_64-redhat-linux-gnu --program-prefix= --disable-dependency-tracking --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include --libdir=/usr/lib64 --libexecdir=/usr/libexec --localstatedir=/var --sharedstatedir=/var/lib --mandir=/usr/share/man --infodir=/usr/share/info '--FC_LINKER_FLAGS=-Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld  -lgfortran -lfmpich -lmpichf90' '--LIBS= -lmpich -lfmpich -lmpichf90' 'CFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O3 -fPIC' 'CXXFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O3 -fPIC' 'FFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/usr/lib64/gfortran/modules -O3 -fPIC' 'LDFLAGS=-Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld  -fPIC' 'COPTFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' 'CXXOPTFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' 'FOPTFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/usr/lib64/gfortran/modules' 'FCFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/usr/lib64/gfortran/modules -O3 -fPIC' '--CC_LINKER_FLAGS=-Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld ' --with-default-arch=0 --with-make=1 --with-cmake-exec=/usr/bin/cmake3 --with-ctest-exec=/usr/bin/ctest3 --with-single-library=1 --with-precision=double --with-petsc-arch=x86_64 --with-clanguage=C --with-shared-libraries=1 --with-fortran-interfaces=1 --with-windows-graphics=0 --with-cc=/usr/lib64/mpich/bin/mpicc --with-cxx=/usr/lib64/mpich/bin/mpicxx --with-fc=/usr/lib64/mpich/bin/mpif90 --with-shared-ld=ld --with-pic=1 --with-clib-autodetect=0 --with-fortranlib-autodetect=0 --with-mkl_sparse=0 --with-mkl_sparse_optimize=0 --with-mkl_cpardiso=0 --with-mkl_pardiso=0 --DATAFILESPATH=share/petsc/datafiles --with-python=1 --with-python-exec=/usr/bin/python3 --download-petsc4py=1 --with-cxxlib-autodetect=0 --with-threadsafety=0 --with-log=1 --with-debugging=0 '--with-mpiexec=/usr/lib64/mpich/bin/mpiexec -n 6 --mca btl_base_warn_component_unused 0' --with-scalapack=1 '--with-scalapack-lib=-L/usr/lib64/mpich/lib -lscalapack' --with-scalapck-include= --with-mpi=1 --with-cgns=1 --with-cgns-include= --with-cgns-lib=-lcgns --with-hdf5=1 --with-hdf5-include= '--with-hdf5-lib=-L/usr/lib64/mpich/lib -lhdf5 -lhdf5_hl' --with-ptscotch=1 --with-ptscotch-include= '--with-ptscotch-lib=-L/usr/lib64/mpich/lib -lptscotch -lscotch -lptscotcherr -lscotcherr' --with-mumps=1 --with-superlu_dist=1 --with-superlu_dist-include=/usr/include/mpich-x86_64/superlu_dist --with-superlu_dist-lib=-lsuperlu_dist --with-x=1 --with-openmp=0 --with-hwloc=0 --with-ssl=0 --with-hypre=1 --with-hypre-include=/usr/include/mpich-x86_64/hypre '--with-hypre-lib=-L/usr/lib64/mpich/lib -lHYPRE' --with-pthread=1 --with-valgrind=1 --with-metis=1 --with-64-bit-indices=0 --with-blaslapack=1 --with-blaslapack-lib=-lflexiblas --with-blaslapack-include=/usr/include/flexiblas

openmpi:

./configure --build=x86_64-redhat-linux-gnu --host=x86_64-redhat-linux-gnu --program-prefix= --disable-dependency-tracking --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include --libdir=/usr/lib64 --libexecdir=/usr/libexec --localstatedir=/var --sharedstatedir=/var/lib --mandir=/usr/share/man --infodir=/usr/share/info '--FC_LINKER_FLAGS=-Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld  -lgfortran -lmpi_mpifh' '--LIBS= -lmpi -lmpi_mpifh' 'CFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O3 -fPIC' 'CXXFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O3 -fPIC' 'FFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/usr/lib64/gfortran/modules -O3 -fPIC' 'LDFLAGS=-Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld  -fPIC' 'COPTFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' 'CXXOPTFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' 'FOPTFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/usr/lib64/gfortran/modules' 'FCFLAGS=-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1  -m64  -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -I/usr/lib64/gfortran/modules -O3 -fPIC' '--CC_LINKER_FLAGS=-Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld ' --with-default-arch=0 --with-make=1 --with-cmake-exec=/usr/bin/cmake3 --with-ctest-exec=/usr/bin/ctest3 --with-single-library=1 --with-precision=double --with-petsc-arch=x86_64 --with-clanguage=C --with-shared-libraries=1 --with-fortran-interfaces=1 --with-windows-graphics=0 --with-cc=/usr/lib64/openmpi/bin/mpicc --with-cxx=/usr/lib64/openmpi/bin/mpicxx --with-fc=/usr/lib64/openmpi/bin/mpif90 --with-shared-ld=ld --with-pic=1 --with-clib-autodetect=0 --with-fortranlib-autodetect=0 --with-mkl_sparse=0 --with-mkl_sparse_optimize=0 --with-mkl_cpardiso=0 --with-mkl_pardiso=0 --DATAFILESPATH=share/petsc/datafiles --with-python=1 --with-python-exec=/usr/bin/python3 --download-petsc4py=1 --with-cxxlib-autodetect=0 --with-threadsafety=0 --with-log=1 --with-debugging=0 '--with-mpiexec=/usr/lib64/openmpi/bin/mpiexec -n 6 --mca btl_base_warn_component_unused 0' --with-scalapack=1 '--with-scalapack-lib=-L/usr/lib64/openmpi/lib -lscalapack' --with-scalapck-include= --with-mpi=1 --with-cgns=1 --with-cgns-include= --with-cgns-lib=-lcgns --with-hdf5=1 --with-hdf5-include= '--with-hdf5-lib=-L/usr/lib64/openmpi/lib -lhdf5 -lhdf5_hl' --with-ptscotch=1 --with-ptscotch-include= '--with-ptscotch-lib=-L/usr/lib64/openmpi/lib -lptscotch -lscotch -lptscotcherr -lscotcherr' --with-mumps=1 --with-superlu_dist=1 --with-superlu_dist-include=/usr/include/openmpi-x86_64/superlu_dist --with-superlu_dist-lib=-lsuperlu_dist --with-x=1 --with-openmp=0 --with-hwloc=0 --with-ssl=0 --with-hypre=1 --with-hypre-include=/usr/include/openmpi-x86_64/hypre '--with-hypre-lib=-L/usr/lib64/openmpi/lib -lHYPRE' --with-pthread=1 --with-valgrind=1 --with-metis=1 --with-64-bit-indices=0 --with-blaslapack=1 --with-blaslapack-lib=-lflexiblas --with-blaslapack-include=/usr/include/flexiblas

@ZedThree
Copy link
Member

I finally managed to reproduce it by compiling with optimisations, the debug build doesn't fail. Unfortunately, this means the debugger is not much help, as lots of stuff has been inlined and otherwise rearranged. Here's the (abridged) output with some extra debugging stuff put in:

[0]PETSC ERROR: --------------------- Error Message --------------------------------------------------------------
[0]PETSC ERROR: Argument out of range
[0]PETSC ERROR: New nonzero at (2016,2) caused a malloc
Use MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE) to turn off this check
<snip>
[0]PETSC ERROR: #1 MatSetValues_MPIAIJ() line 606 in /builddir/build/BUILD/petsc-3.14.4/buildopenmpi_dir/src/mat/impls/aij/mpi/mpiaij.c
[0]PETSC ERROR: #2 MatSetValues() line 1395 in /builddir/build/BUILD/petsc-3.14.4/buildopenmpi_dir/src/mat/interface/matrix.c
terminate called after throwing an instance of 'BoutException'
  what():  ====== Exception path ======
<snip>
[bt] #6 ./test-laplace3d() [0x40e91f]
main at /home/test/tmp/tests/integrated/test-laplace-petsc3d/test-laplace3d.cxx:117
[bt] #5 <snip> invert/laplace/impls/petsc3damg/petsc3damg.cxx:184
[bt] #4 <snip> LaplacePetsc3dAmg::updateMatrix3D() at /home/test/tmp/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx:351
[bt] #3 <snip> PetscMatrix<Field3D>::Element::operator=(double) at include/bout/petsc_interface.hxx:625
[bt] #2 <snip> PetscMatrix<Field3D>::Element::setValues(double, InsertMode) at include/bout/petsc_interface.hxx:657 
[bt] #1 <snip> include/bout/../boutexception.hxx:28
====== Back trace ======
 -> PetscMatrix setting values at (2016, 0) on line 647 of '../../../../../include/bout/petsc_interface.hxx'
 -> PetscMatrix<T>::Element& PetscMatrix<T>::Element::operator=(BoutReal) [with T = Field3D; BoutReal = double] on line 625 of '../../../../../include/bout/petsc_interface.hxx'
 -> virtual Field3D LaplacePetsc3dAmg::solve(const Field3D&, const Field3D&) on line 181 of 'petsc3damg.cxx'

The code that's causing the problem is:

    const int yup = (l.y() == localmesh->yend && upperY.intersects(l.x())) ? -1 : 0,
              ydown = (l.y() == localmesh->ystart && lowerY.intersects(l.x())) ? -1 : 0;
    operator3D.yup(yup)(l, l.yp()) = 0.0;
    operator3D.ydown(ydown)(l, l.ym()) = 0.0;
    operator3D.yup(yup)(l, l.xp().yp()) = 0.0;
    operator3D.ydown(ydown)(l, l.xp().ym()) = 0.0;
    operator3D.yup(yup)(l, l.xm().yp()) = 0.0;    // <---- this line
    operator3D.ydown(ydown)(l, l.xm().ym()) = 0.0;
    operator3D.yup(yup)(l, l.yp().zp()) = 0.0;
    operator3D.yup(yup)(l, l.yp().zm()) = 0.0;
    operator3D.ydown(ydown)(l, l.ym().zp()) = 0.0;
    operator3D.ydown(ydown)(l, l.ym().zm()) = 0.0;
  }
  operator3D.partialAssemble();

which is a bit confusing, because we clearly haven't assembled the matrix yet, so I don't know why it would complain about mallocs. We do call MatMPIAIJSetPreallocation when creating the PetscMatrix, so maybe that's getting the information wrong?

I'm going to try using ASAN/valgrind, see either of them get anywhere

@johnomotani
Copy link
Contributor Author

That's bizzare - the preallocation and matrix elements that we set must be the same as in builds that are not raising errors?!? I'd not thought of the debugging mode in PETSc, everything I've tested has been with optimized PETSc builds. @ZedThree what configure command did you use exactly to reproduce the error?

@ZedThree
Copy link
Member

This is my PETSc configure command:

./configure --prefix=/home/peter/Tools/petsc/installed/3.14.4 \
  --with-shared-libraries=1 --with-make-np=12 --with-clean=1 \
  --with-fortran-bindings=0 --download-hypre=yes \
  --download-superlu_dist=yes --with-debugging=1 \
  --with-threadsafety=0 --with-log=1 --with-mpi=1 --with-openmp=0

and BOUT++:

cmake . -B build_petsc3144 \
  -DBOUT_USE_PETSC=on -DPETSC_DIR=/home/peter/Tools/petsc/installed/3.14.4 \
  -DCMAKE_BUILD_TYPE=RelWithDebInfo -G Ninja \
  -DPython_EXECUTABLE=$(which python3) \
&& cmake --build build_petsc3144/ --target test-laplace-petsc3d

This diff:

diff --git a/include/bout/petsc_interface.hxx b/include/bout/petsc_interface.hxx
index 1d1f3dfdf..a44fe5ea1 100644
--- a/include/bout/petsc_interface.hxx
+++ b/include/bout/petsc_interface.hxx
@@ -617,16 +617,19 @@ public:
       }
     }
     Element& operator=(const Element& other) {
+      AUTO_TRACE();
       ASSERT3(finite(static_cast<BoutReal>(other)));
       return *this = static_cast<BoutReal>(other);
     }
     Element& operator=(BoutReal val) {
+      AUTO_TRACE();
       ASSERT3(finite(val));
       value = val;
       setValues(val, INSERT_VALUES);
       return *this;
     }
     Element& operator+=(BoutReal val) {
+      AUTO_TRACE();
       ASSERT3(finite(val));
       auto columnPosition = std::find(positions.begin(), positions.end(), petscCol);
       if (columnPosition != positions.end()) {
@@ -641,10 +644,12 @@ public:
 
   private:
     void setValues(BoutReal val, InsertMode mode) {
+      TRACE("PetscMatrix setting values at ({}, {})", petscRow, petscCol);
       ASSERT3(positions.size() > 0);
       std::vector<PetscScalar> values;
       std::transform(weights.begin(), weights.end(), std::back_inserter(values),
                      [&val](BoutReal weight) -> PetscScalar { return weight * val; });
+
       int status;
       BOUT_OMP(critical)
       status = MatSetValues(*petscMatrix, 1, &petscRow, positions.size(),
@@ -724,7 +729,7 @@ public:
     BOUT_OMP(critical)
     status = MatGetValues(*get(), 1, &global1, 1, &global2, &value);
     if (status != 0) {
-      throw BoutException("Error when setting elements of a PETSc matrix.");
+      throw BoutException("Error when getting elements of a PETSc matrix.");
     }
     return value;
   }
diff --git a/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx b/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx
index fdb65599a..a8a60387d 100644
--- a/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx
+++ b/src/invert/laplace/impls/petsc3damg/petsc3damg.cxx
@@ -178,6 +178,7 @@ LaplacePetsc3dAmg::~LaplacePetsc3dAmg() {
 
 
 Field3D LaplacePetsc3dAmg::solve(const Field3D &b_in, const Field3D &x0) {
+  AUTO_TRACE();
   // If necessary, update the values in the matrix operator and initialise
   // the Krylov solver
   if (updateRequired) updateMatrix3D();

and using export BOUT_SHOW_BACKTRACE=1 to get a backtrace out of the test

valgrind had a ton of output, but all leaks, rather than invalid read/writes.

@ZedThree
Copy link
Member

AddressSanitizer to the rescue! Fix incoming

Stencil was storing a lambda which captured some state by reference,
which went out of scope before the lambda was called. Fix is to
capture by value. `RangeIterator` is not particularly expensive to
copy, so this should not affect performance.

Possible issue with linked `RangeIterator`s?
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

@ZedThree
Copy link
Member

Fix was basically a single character:

modified   src/invert/laplace/impls/petsc3damg/petsc3damg.cxx
@@ -511,7 +511,7 @@ OperatorStencil<Ind3D> LaplacePetsc3dAmg::getStencil(Mesh* localmesh,
   // If there is a lower y-boundary then create a part of the stencil
   // for cells immediately adjacent to it.
   if (lowerYBound.max() - lowerYBound.min() > 0) {
-    stencil.add([index = localmesh->ystart, &lowerYBound](Ind3D ind) -> bool {
+    stencil.add([index = localmesh->ystart, lowerYBound](Ind3D ind) -> bool {
 		  return index == ind.y() && lowerYBound.intersects(ind.x()); },
       lowerEdgeStencilVector);
   }
@@ -519,7 +519,7 @@ OperatorStencil<Ind3D> LaplacePetsc3dAmg::getStencil(Mesh* localmesh,
   // If there is an upper y-boundary then create a part of the stencil
   // for cells immediately adjacent to it.
   if (upperYBound.max() - upperYBound.min() > 0) {
-    stencil.add([index = localmesh->yend, &upperYBound](Ind3D ind) -> bool {
+    stencil.add([index = localmesh->yend, upperYBound](Ind3D ind) -> bool {
 		  return index == ind.y() && upperYBound.intersects(ind.x()); },
       upperEdgeStencilVector);
   }

Basically the stencil test function was capturing the RangeIterator by reference -- but the function took them by value, so this turned out to be taking a reference to a local variable, which of course went out of scope by the time the lambda was called in calculating the number of off-diagonals. Which explains why PETSc was complaining -- I suspect we preallocated zero off-diagonals.

I'm not sure why this worked in all the other builds!

@johnomotani
Copy link
Contributor Author

Thanks @ZedThree! Fix looks good to me.

@ZedThree
Copy link
Member

test-drift-instability-staggered timing out in the debug build again -- unrelated to this PR, so I'll merge. Needs sorting out though, so that is a task for the rest of the week

@ZedThree ZedThree merged commit 86c00cc into next Feb 17, 2021
@ZedThree ZedThree deleted the fix-petsc3damg-test branch February 17, 2021 17:30
ZedThree added a commit that referenced this pull request Mar 2, 2021
…terp transform"

This (partially) reverts commit 0c04105, now that a proper fix is in (#2237)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants