public abstract class DirectSolverBase extends java.lang.Object implements DirectSolver
DirectSolver implementations which are implemented
natively and which accept their matrices in compressed row storage (CRS)
format with 1-based indices. It supplies the solver state machine, the
buffers used to extract CRS data from Matrix objects, and the
analyze, factor and solve methods which are common to such solvers,
leaving subclasses to supply the native calls themselves through a small
number of hook methods:
createSolverHandle() and releaseSolverHandle(long), which
create and destroy the native solver instance;
setMatrixNative(double[], int[], int[], int, int, int), factorMatrixNative(double[]) and
solveNative(double[], double[], int), which implement the three solution phases;
errorMessage(int) and getSolverName(), which are used to
describe failures.
Solver specific settings (reorder methods, pivot perturbation, etc.), and the static methods which load the native libraries and determine solver availability, are left entirely to the subclasses. Note in particular that the fields which record whether a native library has been loaded must be declared in the subclass, since static fields are not polymorphic and sharing them here would cause one solver's availability to be reported for another.
DirectSolver.IterativeMethod| Modifier and Type | Field and Description |
|---|---|
static int |
DEFAULT_GMRES_RESTART
Default restart length for GMRES iterative solves.
|
ANALYZED, DEFAULT_ITERATIVE_MAX_SOLVES, DEFAULT_ITERATIVE_TOLERANCE, FACTORED, UNSET| Constructor and Description |
|---|
DirectSolverBase() |
| Modifier and Type | Method and Description |
|---|---|
void |
analyze(double[] vals,
int[] colIdxs,
int[] rowOffs,
int size,
int type)
Performs prefactor analysis on a matrix whose structure and values are
supplied in compressed row storage (CRS) format, using 1-based
indices, as described in the documentation for
Matrix.setCRSValues. |
void |
analyze(Matrix M,
int size,
int type)
Performs prefactor analysis on a specified matrix.
|
void |
analyzeAndFactor(Matrix M)
Factors a matrix.
|
void |
dispose()
Releases all internal resources allocated by this solver.
|
void |
factor()
Factors a previously analyzed matrix.
|
void |
factor(double[] vals)
Factors a previously analyzed matrix, using the numeric values supplied
by
vals. |
void |
finalize() |
static int |
getDefaultNumThreads()
Returns the default number of threads which solvers are assigned when
they are created.
|
java.lang.String |
getErrorMessage()
|
int |
getGmresRestart()
Queries the GMRES restart length.
|
int |
getIterativeMaxSolves()
Queries the maximum number of preconditioner solves allowed for
DirectSolver.iterativeSolve(double[], double[], double[]). |
DirectSolver.IterativeMethod |
getIterativeMethod()
Queries the method used by
DirectSolver.iterativeSolve(double[], double[], double[]). |
double |
getIterativeTolerance()
Queries the tolerance for
DirectSolver.iterativeSolve(double[], double[], double[]). |
double |
getLastIterativeResidual()
Returns the relative residual
||b - M x||/||b|| obtained by the
most recent call to DirectSolver.iterativeSolve(double[], double[], double[]), or -1 if this is not
available. |
int |
getLastIterativeSolves()
Returns the number of preconditioner solves performed by the most recent
call to
DirectSolver.iterativeSolve(double[], double[], double[]), or -1 if this is not available. |
int |
getNumThreads()
Returns the number of threads that this solver is using.
|
int |
getPhysicalCoreCount()
Returns the number of physical CPU cores on this machine, as opposed
to logical/hyperthreaded processors -- queried natively (see
getPhysicalCoreCountNative()) since Java has no portable way to tell
the two apart, and hyperthreads provide little to no benefit for
compute-bound work like sparse factorization (see maxThreadsNnz(int, int)). |
int |
getState()
|
static boolean |
getUseCriticalArrayAccess()
Queries whether native solvers use JNI critical array access for their
iterative solves.
|
double |
residual(int[] rowOffs,
int[] colIdxs,
double[] vals,
int size,
double[] x,
double[] b,
boolean symmetric)
Computes the norm of the residual
M x - b, where the values of
M are given in compressed row storage (CRS) format. |
static void |
setDefaultNumThreads(int num)
Sets the default number of threads which solvers are assigned when they
are created.
|
void |
setGmresRestart(int restart)
Sets the restart length used when the iterative method is GMRES.
|
void |
setIterativeMaxSolves(int max)
Sets the maximum number of preconditioner solves allowed for
DirectSolver.iterativeSolve(double[], double[], double[]), beyond which it fails. |
void |
setIterativeMethod(DirectSolver.IterativeMethod method)
Sets the method used by
DirectSolver.iterativeSolve(double[], double[], double[]). |
void |
setIterativeTolerance(double tol)
Sets the tolerance for
DirectSolver.iterativeSolve(double[], double[], double[]): the iteration succeeds
when the relative residual ||b - M x||/||b|| is at most
tol. |
void |
setNumThreads(int num)
Sets the number of threads that this solver should use.
|
static void |
setUseCriticalArrayAccess(boolean enable)
Sets whether native solvers use JNI critical array access
(
GetPrimitiveArrayCritical) to transfer array data for the
iterative (GMRES or CGS) solves performed by their native wrappers. |
void |
solve(double[] x,
double[] b)
Solves the system
|
void |
solve(double[] X,
double[] B,
int nrhs)
Solves the system
|
void |
solve(VectorNd x,
VectorNd b)
Solves the system
|
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitgetMaxRefinementSteps, getNumNegEigenvalues, getNumNonZerosInFactors, getNumPerturbedPivots, getNumPosEigenvalues, hasIterativeSolves, hasMultipleRhsSolves, iterativeSolve, iterativeSolve, residual, setMaxRefinementStepspublic static final int DEFAULT_GMRES_RESTART
public int getState()
getState in interface DirectSolverpublic java.lang.String getErrorMessage()
analyze() or factor(), or
null if the method succeeded.getErrorMessage in interface DirectSolverpublic static void setDefaultNumThreads(int num)
num to a value <= 0 will reset the number of threads
to the default used by OpenMP, which is typically the value stored in the
environment variable OMP_NUM_THREADS.
Note: this setting is shared by all solvers derived from
DirectSolverBase, since the thread pools which they use
(OpenMP and the threaded BLAS) are properties of the process rather than
of an individual solver.
num - default number of threads to usegetDefaultNumThreads()public static int getDefaultNumThreads()
setDefaultNumThreads(int)public void setNumThreads(int num)
num to a value <= 0 will
reset the number of threads to myNominalNumThreads, i.e.,
whatever this solver would have been assigned when created: the thread
pool's own natural default, overridden by getDefaultNumThreads()
if positive, and capped by getPhysicalCoreCount().
Note: the thread count is a property of the process rather than of an individual solver, so changing it here affects all solvers running in the same process. It should also not be changed in between the analyze, factor and solve phases.
A positive value here is also recorded as the highest priority input
to automatic thread throttling (see maxThreadsNnz(int, int)), taking
precedence over everything else, including getPhysicalCoreCount().
num - number of threads to usegetNumThreads()public int getNumThreads()
myNominalNumThreads -- the thread pool's own natural
default (typically OMP_NUM_THREADS), overridden by getDefaultNumThreads() if positive, and capped by getPhysicalCoreCount().setNumThreads(int)public int getPhysicalCoreCount()
getPhysicalCoreCountNative()) since Java has no portable way to tell
the two apart, and hyperthreads provide little to no benefit for
compute-bound work like sparse factorization (see maxThreadsNnz(int, int)). Falls back to Runtime.availableProcessors()
(logical count, with a printed warning) if native detection runs but
fails, or returns -1 if this solver's native library predates
getPhysicalCoreCountNative() entirely -- callers should treat
that as "undetermined" and skip whatever they would otherwise have
capped by it, rather than treating -1 as a literal core count.
On Arm-based Macs with both performance and efficiency cores, the native code shared by the MUMPS and Accelerate solvers counts only the performance cores. This is tuned for MUMPS, whose use of Accelerate's BLAS (which runs on the chip's shared matrix units) gains little from extra threads and is slowed down by the efficiency cores. It is not true of solvers in general: Pardiso, under Rosetta, is fastest with all cores.
Queried once and cached for the life of the process: this is not meticulously synchronized against concurrent first calls from different solver instances, but the query is cheap, side-effect-free and deterministic, so a benign race only risks redoing it once, never an inconsistent result.
-1 if
undeterminedpublic void setIterativeMethod(DirectSolver.IterativeMethod method)
DirectSolver.iterativeSolve(double[], double[], double[]). The default is DirectSolver.IterativeMethod.GMRES. Has no effect if DirectSolver.hasIterativeSolves()
returns false.setIterativeMethod in interface DirectSolvermethod - iterative methodpublic DirectSolver.IterativeMethod getIterativeMethod()
DirectSolver.iterativeSolve(double[], double[], double[]).getIterativeMethod in interface DirectSolverpublic void setIterativeMaxSolves(int max)
DirectSolver.iterativeSolve(double[], double[], double[]), beyond which it fails. The default is DirectSolver.DEFAULT_ITERATIVE_MAX_SOLVES. Has no effect if DirectSolver.hasIterativeSolves() returns false.setIterativeMaxSolves in interface DirectSolvermax - maximum number of preconditioner solvespublic int getIterativeMaxSolves()
DirectSolver.iterativeSolve(double[], double[], double[]).getIterativeMaxSolves in interface DirectSolverpublic void setIterativeTolerance(double tol)
DirectSolver.iterativeSolve(double[], double[], double[]): the iteration succeeds
when the relative residual ||b - M x||/||b|| is at most
tol. The default is DirectSolver.DEFAULT_ITERATIVE_TOLERANCE.
Has no effect if DirectSolver.hasIterativeSolves() returns false.setIterativeTolerance in interface DirectSolvertol - relative residual tolerancepublic double getIterativeTolerance()
DirectSolver.iterativeSolve(double[], double[], double[]).getIterativeTolerance in interface DirectSolverpublic void setGmresRestart(int restart)
DEFAULT_GMRES_RESTART.restart - GMRES restart lengthpublic int getGmresRestart()
public int getLastIterativeSolves()
DirectSolver.iterativeSolve(double[], double[], double[]), or -1 if this is not available.getLastIterativeSolves in interface DirectSolverpublic double getLastIterativeResidual()
||b - M x||/||b|| obtained by the
most recent call to DirectSolver.iterativeSolve(double[], double[], double[]), or -1 if this is not
available.getLastIterativeResidual in interface DirectSolverpublic static void setUseCriticalArrayAccess(boolean enable)
GetPrimitiveArrayCritical) to transfer array data for the
iterative (GMRES or CGS) solves performed by their native wrappers.
The value, right-hand side and solution arrays are then copied directly
between Java and native storage, avoiding extra copies and allocation
of the value array. Critical access is held only while copying, never
during the solve, since on JDK 21 and earlier it defers garbage
collection for all threads. The default is true. Currently
used by PardisoSolver and MumpsSolver.enable - if true, use critical array accesspublic static boolean getUseCriticalArrayAccess()
setUseCriticalArrayAccess(boolean).true if critical array access is usedpublic void analyze(Matrix M, int size, int type)
factor(). If
size is less than the actual matrix size, then the analysis
is done on the principal submatrix of M defined by the first
size rows and columns.analyze in interface DirectSolverM - matrix to analyzesize - size of the matrix to factor.type - or-ed flags giving information about the matrix type. Typical flags are
SYMMETRIC or
POSITIVE_DEFINITEpublic void analyze(double[] vals,
int[] colIdxs,
int[] rowOffs,
int size,
int type)
Matrix.setCRSValues. The number of
non-zero values is given by rowOffs[size]-1. If the matrix type
is symmetric, only the upper triangular portion should be supplied.
Because no matrix object is supplied, factor()
cannot be used after calling this method; use factor(vals) instead. The values supplied here may be used to assist
the analysis but are not used for any numeric factorization.
analyze in interface DirectSolvervals - values of the non-zero matrix elementscolIdxs - 1-based column indices of the non-zero matrix elementsrowOffs - 1-based row start offsets into vals and
colIdxssize - size of the matrix to be analyzedtype - or-ed flags giving information about the matrix type, as
described for analyze(M,size,type)public void factor()
factor in interface DirectSolverpublic void factor(double[] vals)
vals. These must be ordered in the same way as those
supplied to the most recent call to analyze().factor in interface DirectSolvervals - non-zero matrix element valuespublic void analyzeAndFactor(Matrix M)
analyze (M, M.rowSize(), 0) factor()
analyzeAndFactor in interface DirectSolverM - matrix to factorpublic void solve(VectorNd x, VectorNd b)
solve in interface DirectSolverx - vector in which result is returnedb - right hand vector of matrix equationpublic void solve(double[] x,
double[] b)
M x = bwhere the solution and right hand side are supplied using
double[] objects.solve in interface DirectSolverx - vector in which result is returnedb - right hand vector of matrix equationpublic void solve(double[] X,
double[] B,
int nrhs)
M X = Bfor a set of right hand sides B, where the number of right hand sides is given by
nrhs. Both X and B should
be stored in column major order. This method is only available if DirectSolver.hasMultipleRhsSolves() returns true.solve in interface DirectSolverX - returns the solutions, in column major orderB - supplies the right hand sides, in column major ordernrhs - number of right hand sidespublic double residual(int[] rowOffs,
int[] colIdxs,
double[] vals,
int size,
double[] x,
double[] b,
boolean symmetric)
M x - b, where the values of
M are given in compressed row storage (CRS) format. This is
a convenience wrapper for DirectSolver.residual(int[], int[], double[], int, double[], double[], boolean).rowOffs - matrix row offsets (CRS format)colIdxs - non-zero element column indices (CRS format)vals - non-zero element values (CRS format)size - size of the matrixx - supplies the solution valueb - supplies the right-hand sidesymmetric - if true, assumes that the arguments define
only the upper triangular portion of a symmetric matrixpublic void dispose()
dispose in interface DirectSolverpublic void finalize()
finalize in class java.lang.Object