Source code for pyfvtool.pdesolver

import numpy as np

from scipy.sparse import csr_array
from scipy.sparse.linalg import spsolve
from scipy.sparse.linalg import use_solver
use_solver(useUmfpack=False) 
# For reproducibility, do not automatically use any installed `scikits.umfpack`
# solver. Always use the built-in SuperLU by default. In PyFVTool, the
# `scikits.umfpack.spsolve` solver (if installed) should be supplied via
# the `externalsolver` keyword argument of `solvePDE`, as is the case for
# the `pypardiso.spsolve` solver (and any other external solvers).

from .mesh import MeshStructure
from .cell import CellVariable
from .utilities import TrackedArray



[docs] def solvePDE(phi: CellVariable, eqnterms: list, externalsolver = None) -> CellVariable: """ Solve a PDE using the finite volume method This solver routine constructs the matrix equation from the FVM-discretized terms. These terms are provided by the user as a list each term being the output of a prior call to the appropriate xxxTerm() function. The terms provided by the user should not include any terms related to the boundary conditions, as these are handled automatically by solvePDE. The CellVariable is updated with the solution values, and a reference to this one and the same variable is returned. If the 'old' input CellVariable is to be conserved, it should be copied beforehand to a separate instance. Parameters ---------- phi : CellVariable Solution variable subject to the boundary conditions represented by bcterm. eqnterms : list List of matrix equation terms generated by the xxxTerm functions. The elements of the list can either be a tuple (M, RHS), a simple csr_array matrix (M) or a 1D np.ndarray (RHS). These will be added up to create both the M and RHS of the matrix equation to be solved. externalsolver : function, optional If specified, use an external sparse solver via a function call having the same interface as the default solver `scipy.sparse.linalg.spsolve`. If not specified, this default built-in SuperLU solver will be used. Raises ------ TypeError If any of the provided terms is not conform to expectations. Returns ------- CellVariable The updated CellVariable. """ if externalsolver is None: solver = spsolve else: solver = externalsolver if phi.BCs.modified or phi.value.modified: phi.apply_BCs() # Construct BCs Term # Mbc, RHSbc = boundaryConditionsTerm(phi.BCs) # Retrieve pre-constructed BCs Term Mbc, RHSbc = phi._BCsTerm # Initialize overall cumulative matrix and right-hand side for # matrix equation M = Mbc.copy() # need to copy, so that original 'bcterm' is protected RHS = RHSbc.copy() # need to copy, so that original 'bcterm' is protected # Cumulate all equation terms for term in eqnterms: if isinstance(term, tuple): Mterm, RHSterm = term if (Mterm.ndim != 2) or (RHSterm.ndim != 1): raise TypeError('Unknown term') M += Mterm RHS += RHSterm elif term.ndim == 1: RHS += term elif term.ndim == 2: M += term else: raise TypeError('Unknown term') # Solve! phi_new_values = solver(M, RHS) # Update phi phi._value = TrackedArray(np.reshape(phi_new_values, phi.domain.dims+2)) phi.apply_BCs() return phi
[docs] def solveMatrixPDE(m: MeshStructure, M:csr_array, RHS: np.ndarray, externalsolver = None) -> CellVariable: """ Solve the PDE discretized according to the finite volume method This 'expert-level' solver routine uses the M matrix and RHS right-hand side vector directly. These matrices should be constructed beforehand by combining the different M matrices and RHS vectors generated using the xxxTerm routines, including those related to the boundary conditions. Returns a new CellVariable without changing the input ('old') CellVariable. Application of boundary condition terms and updating the related ghost cells should be handled entirely by the (expert-level) user. Parameters ---------- m: MeshStructure Mesh structure M: csr_array Matrix of the linear system RHS: np.ndarray Right hand side of the linear system externalsolver: function (optional) If provided, use an external sparse solver via a function call having the same interface as the default built-in SuperLU solver scipy.sparse.linalg.spsolve. Returns ------- phi: CellVariable Solution of the PDE (newly created CellVariable instance) """ if externalsolver is None: solver = spsolve else: solver = externalsolver phi = solver(M, RHS) return CellVariable(m, np.reshape(phi, m.dims+2)) # BCs handled by user
[docs] def solveExplicitPDE(phi_old: CellVariable, dt: float, RHS: np.ndarray) -> CellVariable: """ Solve the PDE using an explicit finite volume method. Parameters ---------- phi_old: CellVariable Solution of the previous time step dt: float Time step RHS: np.ndarray Right hand side of the linear system Returns ------- phi: CellVariable Solution of the PDE """ if phi_old.BCs.modified or phi_old.value.modified: phi_old.apply_BCs() x = phi_old._value + dt*RHS.reshape(phi_old._value.shape) phi = CellVariable(phi_old.domain, 0.0, phi_old.BCs, BCsTerm_precalc = False) phi._value = TrackedArray(x) phi.apply_BCs() return phi