Skip to content

Commit

Permalink
Fix #963: PETSc 3.20.0 broke the world (#982)
Browse files Browse the repository at this point in the history
Fixes #963
(Actually, PETSC 3.19.0 broke the world.)

This PR:
- Assembles before `multTranspose` to prevent newly added exception
- Renames `bandwidth` to `nonZerosPerRow` and removes `sizeHint`

  The two were confusingly redundant:
  - PySparse takes `sizeHint`, the number of non-zeros in the matrix.
  - PyTrilinos takes `NumEntriesPerRow`.
  - petsc4py didn't used to be clear what it took, but is now
    documented as number of non-zeros per row (of the local portion
    of the matrix, but we'll ignore that part).
  - scipy doesn't preallocate.
  - Linear algebra
    [defines bandwidth](https://en.wikipedia.org/wiki/Band_matrix#Bandwidth)
    as "number $k$ such that $a_{i,j}=0$ if $|i-j| > k$", which is
    roughly half the number of non-zeros per row (and only applies
    to a band-diagonal matrix).
    Better to be explicit about what we really mean.

  Now all take same parameter and PySparse adjusts as needed.

  `sizeHint` was introduced in @a15d696 (in 2006!) to
  "allow smaller preallocations", but it was never used that way.
  Now, `nonZerosPerRow` can take an array_like to specify row-by-row
  preallocations, which are directly supported by PyTrilinos and petsc4py,
  and can be simulated for PySparse.

  Added `exactNonZeros`, which may have performance benefits for
  PyTrilinos and petsc4py. Currently unused.
- Uses `Term`'s knowledge of own stencil to preallocate more effectively.
  Still doesn't do a good job with vector equations, but that's a deeper change
  (the resolution of which might help #920).
- Fixes(?) conda/mamba installs
- Fixes(?) race condition
  • Loading branch information
guyer committed Dec 4, 2023
1 parent 7f3fc9a commit 7befdbc
Show file tree
Hide file tree
Showing 14 changed files with 463 additions and 228 deletions.
2 changes: 1 addition & 1 deletion .azure/pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ stages:
condition: startsWith(variables.image, 'windows')
- bash: |
mamba create --quiet --name wheelEnvironment --channel conda-forge python=3.10 mamba
conda create --quiet --name wheelEnvironment --channel conda-forge python=3.10
source activate wheelEnvironment
mkdir tmp
cd tmp
Expand Down
17 changes: 2 additions & 15 deletions .azure/templates/install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,11 @@ steps:
- bash: |
conda config --set always_yes yes --set changeps1 no
conda config --remove channels defaults
if [[ ${{ parameters.python_version }} == "2.7" ]]; then
# mamba doesn't work in Py2.7
conda create --quiet --name myEnvironment --channel conda-forge python=${{ parameters.python_version }}
else
# mamba needs to be installed in the Py3k environment for some reason
conda create --yes --quiet --name myEnvironment --channel conda-forge python=${{ parameters.python_version }} mamba
fi
conda config --set solver libmamba
displayName: Create Anaconda environment
- bash: |
if [[ ${{ parameters.python_version }} == "2.7" ]]; then
# mamba doesn't work in Py2.7
conda install --quiet --name myEnvironment --channel conda-forge python=${{ parameters.python_version }} ${{ parameters.conda_packages }}
else
# do mamba installs from environment on Py3k
source activate myEnvironment
mamba install --quiet --channel conda-forge python=${{ parameters.python_version }} ${{ parameters.conda_packages }}
fi
conda create --yes --quiet --name myEnvironment --channel conda-forge python=${{ parameters.python_version }} ${{ parameters.conda_packages }}
displayName: Install Anaconda packages
- bash: |
Expand Down
3 changes: 3 additions & 0 deletions .en-custom.txt
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ pre-assembled
pre-built
pre-installed
Pre-Installed
preallocated
preallocation
preallocating
preconditioner
preconditioners
Pusztai
Expand Down
4 changes: 2 additions & 2 deletions fipy/boundaryConditions/boundaryCondition.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ def _buildMatrix(self, SparseMatrix, Ncells, MaxFaces, coeff):
Ncells : int
Size of matrices
MaxFaces : int
Maximum number of faces per cell (determines bandwidth of
:math:`\mathsf{L}`)
Maximum number of faces per cell (determines number of
non-zeros per row of :math:`\mathsf{L}`)
coeff : list
Contribution due to this face
"""
Expand Down
6 changes: 3 additions & 3 deletions fipy/boundaryConditions/fixedValue.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ def _buildMatrix(self, SparseMatrix, Ncells, MaxFaces, coeff):
Ncells : int
Size of matrices
MaxFaces : int
Maximum number of faces per cell (determines bandwidth of
:math:`\mathsf{L}`)
Maximum number of faces per cell (determines number of
non-zeros per row of :math:`\mathsf{L}`)
coeff : list
Contribution to adjacent cell diagonal and
:math:`\mathsf{b}` vector by this exterior face
"""
faces = self.faces.value

LL = SparseMatrix(mesh=self.faces.mesh, sizeHint=len(self.faces), bandwidth=1)
LL = SparseMatrix(mesh=self.faces.mesh, nonZerosPerRow=1)
LL.addAt(coeff['cell 1 diag'][faces], self.adjacentCellIDs, self.adjacentCellIDs)

## The following has been commented out because
Expand Down
37 changes: 31 additions & 6 deletions fipy/matrices/offsetSparseMatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,41 @@ class OffsetSparseMatrixClass(SparseMatrix):
equationIndex = 0
varIndex = 0

def __init__(self, mesh, bandwidth=0, sizeHint=None,
numberOfVariables=numberOfVariables, numberOfEquations=numberOfEquations):
SparseMatrix.__init__(self, mesh=mesh, bandwidth=bandwidth, sizeHint=sizeHint,
numberOfVariables=numberOfVariables, numberOfEquations=numberOfEquations)
def __init__(self, mesh, nonZerosPerRow=1, exactNonZeros=False,
numberOfVariables=numberOfVariables,
numberOfEquations=numberOfEquations):
if hasattr(nonZerosPerRow, "__iter__"):
# nonZerosPerRow is an iterable for each row.
# need to pad rows for other equations with zeros.
# can't compare to collections.abc.Iterable because PySparse.
before = self.equationIndex
after = numberOfEquations - self.equationIndex - 1
N = len(nonZerosPerRow)
nonZerosPerRow = numerix.concatenate([[0] * N * before,
nonZerosPerRow,
[0] * N * after])
else:
nonZerosPerRow //= numberOfEquations
SparseMatrix.__init__(self,
mesh=mesh,
nonZerosPerRow=nonZerosPerRow,
exactNonZeros=exactNonZeros,
numberOfVariables=numberOfVariables,
numberOfEquations=numberOfEquations)

def put(self, vector, id1, id2):
SparseMatrix.put(self, vector, id1 + self.mesh.numberOfCells * self.equationIndex, id2 + self.mesh.numberOfCells * self.varIndex)
N = self.mesh.numberOfCells
SparseMatrix.put(self,
vector=vector,
id1=id1 + N * self.equationIndex,
id2=id2 + N * self.varIndex)

def addAt(self, vector, id1, id2):
SparseMatrix.addAt(self, vector, id1 + self.mesh.numberOfCells * self.equationIndex, id2 + self.mesh.numberOfCells * self.varIndex)
N = self.mesh.numberOfCells
SparseMatrix.addAt(self,
vector=vector,
id1=id1 + N * self.equationIndex,
id2=id2 + N * self.varIndex)

def addAtDiagonal(self, vector):
if type(vector) in [type(1), type(1.)]:
Expand Down
Loading

0 comments on commit 7befdbc

Please sign in to comment.