In #2336 I've added an alternative to #2333:
|
LaplaceFactory::ReturnType LaplaceFactory::create(Options* options, CELL_LOC loc, |
|
Mesh* mesh) { |
|
options = optionsOrDefaultSection(options); |
|
|
|
// Use a lambda to replace `Factory::getDefaultType` as we need to |
|
// pass the constructor arguments through to |
|
// `checkPreconditions`. Note that we immediately call the lambda |
|
const auto type = (*options)["type"].withDefault([&]() { |
|
auto result = Factory::checkPreconditions(LAPLACE_PCR)(options, loc, mesh); |
|
if (result) { |
|
return LAPLACE_PCR; |
|
} |
|
output.write("Default Laplacian '{}' preconditions not met because {}\n" |
|
"Falling back to '{}'\n", |
|
LAPLACE_PCR, result.reason, LAPLACE_CYCLIC); |
|
// Change the default type so we pick it up as a used option |
|
return LAPLACE_CYCLIC; |
|
}()); |
|
|
|
return Factory::create(type, options, loc, mesh); |
|
} |
Basically check that we can use PCR as the default Laplacian, otherwise fall back to cyclic. This essentially makes PCR the new default in most cases.
Unfortunately (or possibly fortunately?) this throws up a few issues with PCR in the following tests:
- test-gyro, which is a regression test, comparing the inversion to a benchmark result:
Running Gyro-average inversion test
1 processors (nxpe = 1)....
Checking variable pade1 ... Fail, maximum difference = 0.021458830684423447
Checking variable pade2 ... Fail, maximum difference = 0.0043205489637330174
2 processors (nxpe = 1)....
Checking variable pade1 ... Fail, maximum difference = 0.021458830684423447
Checking variable pade2 ... Fail, maximum difference = 0.0043205489637330174
4 processors (nxpe = 2)....
Checking variable pade1 ... Fail, maximum difference = 0.021458830684423447
Checking variable pade2 ... Fail, maximum difference = 0.0043205489637330174
- test-petsc-laplace-MAST-grid, which applies the forward operator and inverts the result, checking round-trip accuracy, tests 4 and 8 use the default solver (i.e. PCR), all others use PETSc (errors are the same across processor count and grid):
Checking max_error1 ... Pass
Checking max_error2 ... Pass
Checking max_error3 ... Pass
Checking max_error4 ... Fail, maximum error is = 0.9939465685503767
Checking max_error5 ... Pass
Checking max_error6 ... Pass
Checking max_error7 ... Pass
Checking max_error8 ... Fail, maximum error is = 1.0057517623023355
- test-petsc-laplace, which is similar to the previous test, but the PETSc solvers use the default Laplacian as a preconditioner:
KSPConvergedReason is -5
BoutException occured in invert->solve(b1): petsc_laplace: inversion failed to converge.
Test 1: PETSc 2nd order
Magnitude of maximum absolute error is -1
KSPConvergedReason is -5
BoutException occured in invert->solve(b1): petsc_laplace: inversion failed to converge.
Test 2: PETSc 4th order
Magnitude of maximum absolute error is -1
KSPConvergedReason is -5
BoutException occured in invert->solve(b3): petsc_laplace: inversion failed to converge.
Test 3: with coefficients constant in z, PETSc 2nd order
Magnitude of maximum absolute error is -1
Test 4: with coefficients constant in z, default solver
Magnitude of maximum absolute error is 0.999817
KSPConvergedReason is -5
BoutException occured in invert->solve(b5): petsc_laplace: inversion failed to converge.
Test 5: different profiles, PETSc 2nd order
Magnitude of maximum absolute error is -1
KSPConvergedReason is -5
BoutException occured in invert->solve(b6): Laplacian inversion failed to converge (probably)
Test 6: different profiles, PETSc 4th order
Magnitude of maximum absolute error is -1
KSPConvergedReason is -5
BoutException occured in invert->solve(b7): petsc_laplace: inversion failed to converge.
Test 7: different profiles, with coefficients constant in z, PETSc 2nd order
Magnitude of maximum absolute error is -1
Test 8: different profiles, with coefficients constant in z, default solver
Magnitude of maximum absolute error is 1.00577
Given that test-laplace is checked with both cyclic and pcr there must be something else going on. The common factor seems to be the outer boundary flags:
- test-laplace checks only
INVERT_SET in the outer boundary
- test-gyro uses
INVERT_BNDRY_ONE + INVERT_RHS
- test-petsc_laplace uses
INVERT_AC_GRAD and INVERT_AC_GRAD | INVERT_DC_GRAD
- test-petsc_laplace_MAST-grid uses
INVERT_AC_GRAD
My suspicions are that LaplacePCR ::eliminate_boundary_rows only accounts for one boundary, when there could be up to MXG boundary rows that need eliminating, depending on the inversion flags.
In #2336 I've added an alternative to #2333:
BOUT-dev/src/invert/laplace/invert_laplace.cxx
Lines 106 to 126 in 93454ec
Basically check that we can use PCR as the default Laplacian, otherwise fall back to cyclic. This essentially makes PCR the new default in most cases.
Unfortunately (or possibly fortunately?) this throws up a few issues with PCR in the following tests:
Given that
test-laplaceis checked with bothcyclicandpcrthere must be something else going on. The common factor seems to be the outer boundary flags:INVERT_SETin the outer boundaryINVERT_BNDRY_ONE + INVERT_RHSINVERT_AC_GRADandINVERT_AC_GRAD | INVERT_DC_GRADINVERT_AC_GRADMy suspicions are that
LaplacePCR ::eliminate_boundary_rowsonly accounts for one boundary, when there could be up toMXGboundary rows that need eliminating, depending on the inversion flags.