Skip to content

Commit d3891b9

Browse files
authored
Merge pull request #77 from FastNFT/nsev_improvements
Nsev improvements
2 parents bceaab5 + d2ae6b3 commit d3891b9

File tree

10 files changed

+509
-255
lines changed

10 files changed

+509
-255
lines changed

CHANGELOG.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@
44

55
### Added
66

7-
- A NFT routine fnft_manakovv for the Manakov equation with vanishing boundaries was added (continuous spectrum only).
8-
- The periodic NFT routine fnft_nsep now also supports pure Newton refinement.
97
- The routine fnft_kdvv now can now also compute the discrete spectrum. To locate the bound states, either Newton's method or a grid search with additional Newton refinements are available.
8+
- A NFT routine fnft_manakovv for the Manakov equation with vanishing boundaries was added (continuous spectrum only).
109
- The slow scattering methods for AKNS-type systems now include a normalization procedure to deal with numerical overflow (enabled by default).
10+
- The periodic NFT routine fnft_nsep now also supports pure Newton refinement.
11+
- The vanishing NFT routine fnft_nsev now also supports manual filtering.
1112
- The routine fnft__kdv_finvscatter has been added. The plan is to later use it for a fast inverse KdV NFT.
1213

1314
### Changed
1415

15-
- New criteria for stopping Newton iteration in fnft_nsep.
16-
- Simplified some tests to reduce run times.
16+
- New criteria for stopping Newton iterations in fnft_nsep and fnft_nsev.
17+
- The tolerance for the Newton refinements in fnft_nsev can now be set by the user.
18+
- The default number of iterations for the Newton refinements in fnft_nsev is now 100, and the user is warned if the number was too small.
19+
- Reduced some tests to reduce run times.
1720
- The code for AKNS scattering has been overhauled.
1821

1922
### Fixed

Doxyfile

Lines changed: 364 additions & 212 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ Please use the [issue tracker](https://github.com/FastNFT/FNFT/issues) to report
7777

7878
## Contributors
7979

80-
* Sander Wahls, TU Delft
80+
* Sander Wahls, KIT (since July 2023) and TU Delft (before)
8181
* Shrinivas Chimmalgi, TU Delft
8282
* Peter J. Prins, TU Delft
8383
* Marius Brehler, TU Dortmund

include/fnft_kdvv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
* initial guesses for the bound states are available. The complexity is
5454
* \f$ O(niter (*K\_ptr) D) \f$. \n \n
5555
* fnft_kdvv_bsloc_GRIDSEARCH_AND_REFINE: The algorithm evaluates \f$ a(\xi) \f$ on the grid
56-
* \f$ \xi = \{j nexttoward(0,1), jh,2jh,3jh,\ldots,(M-3)jh\,(M-2)jh,j nexttoward((M-1)h,0)\\}\f$,
56+
* \f$ \xi = \{j nexttoward(0,1), jh,2jh,3jh,\ldots,(M-3)jh\,(M-2)jh,j nexttoward((M-1)h,0)\}\f$,
5757
* where \f$ h:= \sqrt{c \max_t q(t)} / (M-1)\f$, where \f$ c=1\f$ for all second order discretizations,
5858
* `fnft_kdv_discretization_4SPLIT4A'/'B'('_VANILLA'), and `fnft_kdv_discretization_CF4_2`(`_VANILLA`);
5959
* \f$ c \f$ is approximately 2 for other discretizations. The constant \f$ M \f$ is chosen

include/fnft_nsev.h

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* Sander Wahls (TU Delft) 2017-2018.
1818
* Shrinivas Chimmalgi (TU Delft) 2019-2020.
1919
* Peter J Prins (TU Delft) 2020-2021.
20+
* Sander Wahls (KIT) 2023.
2021
*/
2122

2223
/**
@@ -47,12 +48,15 @@
4748
* to each other are merged. \n \n
4849
* fnft_nsev_bsfilt_FULL: Bound states in physically implausible regions and
4950
* outside the region based on the step-size of the supplied samples are
50-
* rejected.
51+
* rejected. \n \n
52+
* fnft_nsev_opts_filt_MANUAL: Only points within the specified
53+
* \link fnft_nsev_opts_t::bounding_box \endlink are kept. \n\n
5154
*/
5255
typedef enum {
5356
fnft_nsev_bsfilt_NONE,
5457
fnft_nsev_bsfilt_BASIC,
55-
fnft_nsev_bsfilt_FULL
58+
fnft_nsev_bsfilt_FULL,
59+
fnft_nsev_bsfilt_MANUAL
5660
} fnft_nsev_bsfilt_t;
5761

5862
/**
@@ -63,8 +67,7 @@ typedef enum {
6367
* https://arxiv.org/abs/1611.02435 and https://github.com/eiscor/eiscor)
6468
* with \f$ O(D^2) \f$ complexity is used to detect the roots of
6569
* \f$ a(\lambda) \f$. (Note: FNFT incorporates a development version of this
66-
* routine as no release was available yet.) This method is relatively slow,
67-
* but very reliable. \n \n
70+
* routine as no release was available yet.) This method is relatively slow. \n \n
6871
* fnft_nsev_bsloc_NEWTON: Newton's method is used to refine a given set of initial guesses.
6972
* The discretization used for the the refinement is one of the base methods \link fnft_nse_discretization_t.h \endlink.
7073
* The number of iterations is specified through the field \link fnft_nsev_opts_t::niter
@@ -76,7 +79,7 @@ typedef enum {
7679
* initial guesses for the bound states are available. The complexity is
7780
* \f$ O(niter (*K\_ptr) D) \f$. \n \n
7881
* fnft_nsev_bsloc_SUBSAMPLE_AND_REFINE: This method offers a good compromise
79-
* between the other two. The method automatically finds initial guesses for
82+
* between the previous two. The method automatically finds initial guesses for
8083
* the NEWTON method by first applying the FAST_EIGENVALUE method to a
8184
* subsampled version of the signal. Second these initial guesses are refined
8285
* using the NEWTON method. The number of samples of the subsampled signal can
@@ -158,9 +161,13 @@ typedef enum {
158161
* \link fnft_nsev_bsloc_t \endlink for details.
159162
*
160163
* @var fnft_nsev_opts_t::niter
161-
* Number of Newton iterations to be carried out when either the
162-
* fnft_nsev_bsloc_NEWTON or the fnft_nsev_bsloc_SUBSAMPLE_AND_REFINE method
163-
* is used.
164+
* For fnft_nsev_bsloc_NEWTON and fnft_nsev_bsloc_SUBSAMPLE_AND_REFINE: Maximum
165+
* number of Newton iterations to be carried out.
166+
*
167+
* @var fnft_nsev_opts_t::tol
168+
* Some bound state localization methods such as Newton have tolerance
169+
* parameters. If this value is negative, these parameters will be chosen
170+
* automatically. Set to a non-negative value to chose the tolerance manually.
164171
*
165172
* @var fnft_nsev_opts_t::discspec_type
166173
* Controls how \link fnft_nsev \endlink fills the array
@@ -194,18 +201,26 @@ typedef enum {
194201
* such as discontinuous signals, applying Richardson extrapolation may result in
195202
* worse accuracy compared to the first approximation.
196203
* By default, Richardson extrapolation is disabled (i.e., the
197-
* flag is zero). To enable, set the flag to one.
204+
* flag is zero). To enable, set the flag to one.\n\n
205+
*
206+
* @var fnft_nsev_opts_t::bounding_box
207+
* Array of four reals. Defines a box in the complex plane that is used for
208+
* manual filtering: \n
209+
* bounding_box[0] <= real(lambda) <= bounding_box[1] \n
210+
* bounding_box[2] <= imag(lambda) <= bounding_box[3] \n
198211
*/
199212
typedef struct {
200213
fnft_nsev_bsfilt_t bound_state_filtering;
201214
fnft_nsev_bsloc_t bound_state_localization;
202215
FNFT_UINT niter;
216+
FNFT_REAL tol;
203217
FNFT_UINT Dsub;
204218
fnft_nsev_dstype_t discspec_type;
205219
fnft_nsev_cstype_t contspec_type;
206220
FNFT_INT normalization_flag;
207221
fnft_nse_discretization_t discretization;
208222
FNFT_UINT richardson_extrapolation_flag;
223+
FNFT_REAL bounding_box[4];
209224
} fnft_nsev_opts_t;
210225

211226
/**
@@ -215,14 +230,16 @@ typedef struct {
215230
* @returns A \link fnft_nsev_opts_t \endlink object with the following options.\n
216231
* bound_state_filtering = fnft_nsev_bsfilt_FULL\n
217232
* bound_state_localization = fnft_nsev_bsloc_SUBSAMPLE_AND_REFINE\n
218-
* niter = 10\n
233+
* niter = 100\n
234+
* tol = -1.0\n
219235
* discspec_type = fnft_nsev_dstype_NORMING_CONSTANTS\n
220236
* contspec_type = fnft_nsev_cstype_REFLECTION_COEFFICIENT\n
221237
* normalization_flag = 1\n
222238
* discretization = fnft_nse_discretization_2SPLIT4B\n
223239
* richardson_extrapolation_flag = 0\n
240+
* bounding_box = {NAN, NAN, NAN, NAN}\n
224241
*
225-
* @ingroup fnft
242+
* @ingroup fnft
226243
*/
227244
fnft_nsev_opts_t fnft_nsev_default_opts();
228245

@@ -377,6 +394,7 @@ FNFT_INT fnft_nsev(const FNFT_UINT D, FNFT_COMPLEX const * const q,
377394
#define nsev_bsfilt_NONE fnft_nsev_bsfilt_NONE
378395
#define nsev_bsfilt_BASIC fnft_nsev_bsfilt_BASIC
379396
#define nsev_bsfilt_FULL fnft_nsev_bsfilt_FULL
397+
#define nsev_bsfilt_MANUAL fnft_nsev_bsfilt_MANUAL
380398
#define nsev_bsloc_FAST_EIGENVALUE fnft_nsev_bsloc_FAST_EIGENVALUE
381399
#define nsev_bsloc_NEWTON fnft_nsev_bsloc_NEWTON
382400
#define nsev_bsloc_SUBSAMPLE_AND_REFINE fnft_nsev_bsloc_SUBSAMPLE_AND_REFINE

include/private/fnft__akns_scatter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ FNFT_INT fnft__akns_scatter_matrix(FNFT_UINT const D,
117117
* @param[out] a_vals Array of length K, contains the values of \f$a(\lambda)\f$.
118118
* @param[out] aprime_vals Array of length K, contains the values of
119119
* \f$ a'(\lambda) = \frac{\partial a(\lambda)}{\partial \lambda}\f$.
120-
* @param[out] b Array of length K, contains the values of \f$b(\lambda)\f$.
120+
* @param[out] b_vals Array of length K, contains the values of \f$b(\lambda)\f$.
121121
* The \f$b(\lambda)\f$ are calculated using the criterion from
122122
* Prins and Wahls, <a href="https://doi.org/10.1109/ACCESS.2019.2932256">&quot;
123123
* Soliton Phase Shift Calculation for the Korteweg–De Vries Equation,&quot;</a>.
@@ -149,7 +149,7 @@ FNFT_INT akns_scatter_bound_states(FNFT_UINT const D,
149149
FNFT_COMPLEX const * const bound_states,
150150
FNFT_COMPLEX * const a_vals,
151151
FNFT_COMPLEX * const aprime_vals,
152-
FNFT_COMPLEX * const b,
152+
FNFT_COMPLEX * const b_vals,
153153
FNFT_INT * Ws,
154154
fnft__akns_discretization_t const discretization,
155155
fnft__akns_pde_t const PDE,

matlab/mex_fnft_nsev.c

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1515
*
1616
* Contributors:
17-
* Sander Wahls (TU Delft) 2017-2018.
17+
* Sander Wahls (TU Delft) 2017-2018, 2022.
1818
* Shrinivas Chimmalgi (TU Delft) 2019-2020.
1919
* Peter J. Prins (2021).
20+
* Sander Wahls (KIT) 2023.
2021
*/
2122

2223
#include <string.h>
@@ -164,7 +165,21 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
164165

165166
/* Increase k to account for vector of initial guesses */
166167
k++;
167-
168+
169+
} else if ( strcmp(str, "bsloc_tol") == 0 ) {
170+
171+
/* Extract desired number of iterations */
172+
if ( k+1 == nrhs || !mxIsDouble(prhs[k+1])
173+
|| mxGetNumberOfElements(prhs[k+1]) != 1
174+
|| mxGetScalar(prhs[k+1]) < 0.0 ) {
175+
snprintf(msg, sizeof msg, "'bsloc_tol' should be followed by a non-negative real scalar.");
176+
goto on_error;
177+
}
178+
opts.tol = (FNFT_REAL)mxGetScalar(prhs[k+1]);
179+
180+
/* Increase k to account for vector of initial guesses */
181+
k++;
182+
168183
} else if ( strcmp(str, "bsloc_subsamp_refine") == 0 ) {
169184

170185
opts.bound_state_localization = fnft_nsev_bsloc_SUBSAMPLE_AND_REFINE;
@@ -195,6 +210,26 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
195210
} else if ( strcmp(str, "bsfilt_full") == 0 ) {
196211

197212
opts.bound_state_filtering = fnft_nsev_bsfilt_FULL;
213+
214+
} else if ( strcmp(str, "bsfilt_manual") == 0 ) {
215+
216+
opts.bound_state_filtering = fnft_nsev_bsfilt_MANUAL;
217+
218+
/* Extract bounding box for manual filltering */
219+
if ( k+1 == nrhs || !mxIsDouble(prhs[k+1])
220+
|| mxGetM(prhs[k+1]) != 1 || mxGetN(prhs[k+1]) != 4) {
221+
snprintf(msg, sizeof msg, "'filt_manual' should be followed by a real row vector of length four. See the help.");
222+
goto on_error;
223+
}
224+
double const * const tmp = mxGetPr(prhs[k+1]);
225+
opts.bounding_box[0] = (FNFT_REAL)tmp[0];
226+
opts.bounding_box[1] = (FNFT_REAL)tmp[1];
227+
opts.bounding_box[2] = (FNFT_REAL)tmp[2];
228+
opts.bounding_box[3] = (FNFT_REAL)tmp[3];
229+
230+
/* Increase k to account for bounding box vector */
231+
k++;
232+
198233
} else if ( strcmp(str, "RE") == 0 ) {
199234

200235
opts.richardson_extrapolation_flag = 1;
@@ -314,7 +349,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
314349

315350
opts.discretization = fnft_nse_discretization_4SPLIT4B;
316351

317-
318352
// Slow discretizations
319353
} else if ( strcmp(str, "discr_BO") == 0 ) {
320354

@@ -374,8 +408,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
374408
if (bound_states == NULL) {
375409
K = fnft_nsev_max_K(D, &opts);
376410
if (K == 0) {
377-
snprintf(msg, sizeof msg, "Discretization does not support the chosen bound state localization method.");
378-
goto on_error;
411+
//snprintf(msg, sizeof msg, "Discretization does not support the chosen bound state localization method.");
412+
//goto on_error;
413+
K = D;
379414
}
380415
bound_states = mxMalloc(K * sizeof(FNFT_COMPLEX));
381416
}

matlab/mex_fnft_nsev.m

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@
3636
% below) is set by the algorithm. Not followed by a
3737
% value.
3838
% 'bsloc_niter' Number of iterations to be carried by Newton's method.
39-
% Followed by a positive integer.
39+
% Followed by a non-negative integer.
40+
% 'bsloc_tol' Tolerance used for stopping Newton's method. Followed
41+
% by a non-negative real number.
4042
% 'bsloc_Dsub' The desired number of samples for the subsampled signal
4143
% in the 'subsamp_refine' method. Less samples in the
4244
% subsampled stage result in faster execution time, but
@@ -48,6 +50,10 @@
4850
% bound states in the lower half plane.
4951
% 'bsfilt_full' Full bound state filtering. Additionally removes
5052
% physically implausible bound states.
53+
% 'bsfilt_manual' Manual filtering. Remove bound states outside of a box
54+
% provided by the user. Must be followed by a real vector
55+
% of the form [min_real, max_real, min_imag, max_imag]
56+
% that specifies the box.
5157
% 'RE' Use Richardson extrpolation to improve accuracy. The
5258
% approximations of the nonlinear Fourier spectrum are
5359
% calcuated using all given samples and again with half of
@@ -133,6 +139,7 @@
133139
% along with this program. If not, see <http://www.gnu.org/licenses/>.
134140
%
135141
% Contributors:
136-
% Sander Wahls (TU Delft) 2017-2018.
142+
% Sander Wahls (TU Delft) 2017-2018, 2022.
137143
% Shrinivas Chimmalgi (TU Delft) 2019-2020.
138144
% Peter J. Prins (TU Delft) 2021.
145+
% Sander Wahls (KIT) 2023.

0 commit comments

Comments
 (0)