diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..7871ff36 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,28 @@ +* text=auto + +*.fig binary +*.mat binary +*.mdl binary diff merge=mlAutoMerge +*.mdlp binary +*.mex* binary +*.mlapp binary +*.mldatx binary +*.mlproj binary +*.mlx binary +*.p binary +*.sfx binary +*.sldd binary +*.slreqx binary merge=mlAutoMerge +*.slmx binary merge=mlAutoMerge +*.sltx binary +*.slxc binary +*.slx binary merge=mlAutoMerge +*.slxp binary + +## Other common binary file types +*.docx binary +*.exe binary +*.jpg binary +*.pdf binary +*.png binary +*.xlsx binary diff --git a/Examples/LiveExamples/CanonicalSensitivities.mlx b/Examples/LiveExamples/CanonicalSensitivities.mlx index f830107a..9bfd0872 100644 Binary files a/Examples/LiveExamples/CanonicalSensitivities.mlx and b/Examples/LiveExamples/CanonicalSensitivities.mlx differ diff --git a/Examples/LiveExamples/StateJumpExample.mlx b/Examples/LiveExamples/StateJumpExample.mlx index 2dd6a2ce..60ed6a2d 100644 Binary files a/Examples/LiveExamples/StateJumpExample.mlx and b/Examples/LiveExamples/StateJumpExample.mlx differ diff --git a/Examples/LiveExamples/WhiteCabbageLive.mlx b/Examples/LiveExamples/WhiteCabbageLive.mlx index 3ed67893..7b5ba968 100644 Binary files a/Examples/LiveExamples/WhiteCabbageLive.mlx and b/Examples/LiveExamples/WhiteCabbageLive.mlx differ diff --git a/Examples/LiveExamples/canonicalExRHS_test_live.mlx b/Examples/LiveExamples/canonicalExRHS_test_live.mlx index cf2eb3e9..243f18e2 100644 Binary files a/Examples/LiveExamples/canonicalExRHS_test_live.mlx and b/Examples/LiveExamples/canonicalExRHS_test_live.mlx differ diff --git a/Examples/ParameterEstimation_WhiteCabbage/plot_sensitivities_cabbage.m b/Examples/ParameterEstimation_WhiteCabbage/plot_sensitivities_cabbage.m index c161d1ac..50a48e1c 100644 --- a/Examples/ParameterEstimation_WhiteCabbage/plot_sensitivities_cabbage.m +++ b/Examples/ParameterEstimation_WhiteCabbage/plot_sensitivities_cabbage.m @@ -1,5 +1,5 @@ %% Solution ifdiff -initPaths(); + integrator = @ode45; odeoptionsrhs_test = odeset( 'AbsTol', 1e-14,'RelTol', 1e-12); datahandle = prepareDatahandleForIntegration('whiteCabbageRHS', 'integrator', func2str(integrator), 'options', odeoptionsrhs_test); diff --git a/Examples/ParameterEstimation_WhiteCabbage/test_Cabbage.m b/Examples/ParameterEstimation_WhiteCabbage/test_Cabbage.m index 82ac08a0..584948a8 100644 --- a/Examples/ParameterEstimation_WhiteCabbage/test_Cabbage.m +++ b/Examples/ParameterEstimation_WhiteCabbage/test_Cabbage.m @@ -1,5 +1,5 @@ %% Solution ifdiff -initPaths(); + integrator = @ode45; odeoptionsrhs_test = odeset( 'AbsTol', 1e-14,'RelTol', 1e-12); datahandle = prepareDatahandleForIntegration('whiteCabbageRHS', 'integrator', func2str(integrator), 'options', odeoptionsrhs_test); diff --git a/Examples/canonicalExample/AnalyticalSensitivities/Gmatrices_VDE_df_exact.m b/Examples/canonicalExample/AnalyticalSensitivities/Gmatrices_VDE_df_exact.m index f52113ff..951a5134 100644 --- a/Examples/canonicalExample/AnalyticalSensitivities/Gmatrices_VDE_df_exact.m +++ b/Examples/canonicalExample/AnalyticalSensitivities/Gmatrices_VDE_df_exact.m @@ -1,5 +1,5 @@ %% Solution with ifdiff -initPaths(); + integrator = @ode45; odeoptionsrhs_test = odeset( 'AbsTol', 1e-14,'RelTol', 1e-12); datahandle = prepareDatahandleForIntegration('canonicalExampleRHS', 'integrator', func2str(integrator), 'options', odeoptionsrhs_test); diff --git a/Examples/canonicalExample/AnalyticalSensitivities/analyticalSensitivities_test.m b/Examples/canonicalExample/AnalyticalSensitivities/analyticalSensitivities_test.m index fcaa31ca..5b280bc2 100644 --- a/Examples/canonicalExample/AnalyticalSensitivities/analyticalSensitivities_test.m +++ b/Examples/canonicalExample/AnalyticalSensitivities/analyticalSensitivities_test.m @@ -1,5 +1,5 @@ %% Solution ifdiff -%initPaths(); + integrator = @ode45; odeoptionsrhs_test = odeset( 'AbsTol', 1e-14,'RelTol', 1e-12); datahandle = prepareDatahandleForIntegration('canonicalExampleRHS', 'integrator', func2str(integrator), 'options', odeoptionsrhs_test); diff --git a/Examples/canonicalExample/analyticalSolution.m b/Examples/canonicalExample/analyticalSolution.m index 3af06c20..bbe10e57 100644 --- a/Examples/canonicalExample/analyticalSolution.m +++ b/Examples/canonicalExample/analyticalSolution.m @@ -27,8 +27,8 @@ ylabel('\sigma_2(t)') set(gca, 'FontSize', 24); set(gca, 'Box', 'off'); + %% Solution ifdiff -initPaths(); integrator = @ode45; odeoptionsrhs_test = odeset( 'AbsTol', 1e-14,'RelTol', 1e-12); datahandle = prepareDatahandleForIntegration('canonicalExampleRHS', 'integrator', func2str(integrator), 'options', odeoptionsrhs_test); diff --git a/Examples/canonicalExample/canonicalExampleRHS_extended_test.m b/Examples/canonicalExample/canonicalExampleRHS_extended_test.m index 22b299f1..5eae7939 100644 --- a/Examples/canonicalExample/canonicalExampleRHS_extended_test.m +++ b/Examples/canonicalExample/canonicalExampleRHS_extended_test.m @@ -3,7 +3,6 @@ initstates = [1 0]; %p = 5.437; p = 0.5; -%initPaths() %% options = odeset('AbsTol', 1e-14, 'RelTol', 1e-12); diff --git a/Examples/canonicalExample/sensitivities_CanonicalExample.m b/Examples/canonicalExample/sensitivities_CanonicalExample.m index 16d4200d..c9b99bfd 100644 --- a/Examples/canonicalExample/sensitivities_CanonicalExample.m +++ b/Examples/canonicalExample/sensitivities_CanonicalExample.m @@ -1,5 +1,5 @@ %% Solution with ifdiff -initPaths(); + integrator = @ode45; odeoptionsrhs_test = odeset( 'AbsTol', 1e-14,'RelTol', 1e-12); datahandle = prepareDatahandleForIntegration('canonicalExampleRHS', 'integrator', func2str(integrator), 'options', odeoptionsrhs_test); diff --git a/Examples/predatorprey_filippov/testpprhs.m b/Examples/predatorprey_filippov/testpprhs.m index bdbdf30c..3fe7fa26 100644 --- a/Examples/predatorprey_filippov/testpprhs.m +++ b/Examples/predatorprey_filippov/testpprhs.m @@ -54,13 +54,15 @@ %% EULER Integration -euler_fname = fullfile('.', 'Examples', 'predatorprey_filippov', sprintf('sol_euler_%.0e.mat', eulerStep)); +[owndir, ~] = fileparts(mfilename('fullpath')); +euler_fname = fullfile(owndir, sprintf('sol_euler_%.0e.mat', eulerStep)); if doEuler - fprintf('Integrating with integrator %s...\n', func2str(intEuler)) + fprintf('Integrating with integrator %s (might take a while) ...\n', func2str(intEuler)) figure(fignum); th = tic(); sol_euler = intEuler(@(t,x) pprhs(t,x,p), tspan, x0_1, eulerStep); time_euler = toc(th); fprintf('Euler took %g s\n', time_euler); + fprintf('Saving result to %s for later reuse.\n', euler_fname); save(euler_fname, "sol_euler"); elseif isfile(euler_fname) fprintf('Loading sol_euler from file %s\n', euler_fname); @@ -150,8 +152,8 @@ function errorPlot(fignum, x1, y1, y2, intname1, intname2) if (i == nextout) X(:,k) = Xi; k = k + 1; nextout = nextout + ceil(1 / sfac); - if ~mod(i/stepcount, 0.1), fprintf('.'); end end + if ~mod(floor(100*i/stepcount), 10), fprintf('.'); end end fprintf('\n') T = linspace(tspan(1), tspan(end), ceil(stepcount*sfac)+1); diff --git a/Examples/statejump/bounceball.m b/Examples/statejump/bounceball.m index 0f03708b..b2993485 100644 --- a/Examples/statejump/bounceball.m +++ b/Examples/statejump/bounceball.m @@ -1,6 +1,4 @@ % Solve the bouncing ball problem and plot the solutions and sensitivities -initPaths(); - solver = @ode15s; options = odeset('AbsTol', 1e-8, 'RelTol', 1e-6); diff --git a/Examples/statejump/bounceballError.m b/Examples/statejump/bounceballError.m index 635950f8..47a1bb97 100644 --- a/Examples/statejump/bounceballError.m +++ b/Examples/statejump/bounceballError.m @@ -6,8 +6,6 @@ % This is because having to set h_+ to a value slightly above zero is a burden imposed by IFDIFF, so it % should also factor into the error -initPaths(); - % INITIAL DATA g = 9.807; gamma = 0.9; diff --git a/Examples/statejump/bounceballZeno.m b/Examples/statejump/bounceballZeno.m index 08412f07..18936298 100644 --- a/Examples/statejump/bounceballZeno.m +++ b/Examples/statejump/bounceballZeno.m @@ -1,6 +1,4 @@ % Solve the bouncing ball problem with Zeno's phenomenon treatment and plot the solutions and sensitivities -initPaths(); - solver = @ode15s; options = odeset('AbsTol', 1e-8, 'RelTol', 1e-6); diff --git a/Examples/statejump/jumpSensitivities.m b/Examples/statejump/jumpSensitivities.m index 49c3743b..9a890f13 100644 --- a/Examples/statejump/jumpSensitivities.m +++ b/Examples/statejump/jumpSensitivities.m @@ -3,7 +3,6 @@ % 2. IFDIFF with standard tolerances and FD step, plus relative error % 3. IFDIFF with strict tolerances and shorter FD step, plus relative error -initPaths(); [t0, tEnd, p, x0] = jumpSensitivityInitdata(); % CONFIGURATION diff --git a/Examples/statejump/sinCosMain.m b/Examples/statejump/sinCosMain.m index f6e95139..1fd53d1c 100644 --- a/Examples/statejump/sinCosMain.m +++ b/Examples/statejump/sinCosMain.m @@ -1,5 +1,3 @@ -initPaths(); - solver = @ode45; options = odeset('AbsTol', 1e-8, 'RelTol', 1e-6); diff --git a/README.md b/README.md index c27ae705..2440dab9 100644 --- a/README.md +++ b/README.md @@ -19,12 +19,13 @@ The file [Readme_Example.m](./Readme_Example.m) contains a self-explaining Matla # First Run Prerequisites + Before using IFDIFF, it is mandatory to run the `make_mtreeplus` script once. After starting Matlab, change to the IFDIFF directory and type `make_mtreeplus`. This scripts generates a modified copy of Matlab's own parser class `mtree`, on which IFDIFF heavily relies. -It is also advisable to initialize the paths needed for IFDIFF by invoking -`initPaths();` once on every new matlab session. +It is advisable to initialize the paths needed for IFDIFF by invoking +`initIFDIFF();` once on every new matlab session.
@@ -43,7 +44,7 @@ Preprocessing generates the `datahandle`, the central structure for switching de We set ODE solver and its options as usual. If not set, default values are used. ```matlab - initPaths(); % Initialise the paths for ifdiff + initIFDIFF(); % Initialise the paths for ifdiff -- needed only once per Matlab session integrator = @ode45; odeoptions = odeset('AbsTol', 1e-14, 'RelTol', 1e-12); datahandle = prepareDatahandleForIntegration('canonicalExampleRHS', 'integrator', func2str(integrator), 'options', odeoptions); diff --git a/Readme_Example.m b/Readme_Example.m index da42f367..20d9271f 100644 --- a/Readme_Example.m +++ b/Readme_Example.m @@ -8,7 +8,7 @@ % The ODE solver and the ODE options can be set by the user with name-value pairs. % If unspecified, defaults are used. -initPaths(); % Initialise the paths for ifdiff +initIFDIFF(); % Initialise the paths for ifdiff integrator = @ode45; % Choose integrator and options odeoptions = odeset('AbsTol', 1e-8, 'RelTol', 1e-6); diff --git a/clearPaths.m b/clearPaths.m index 36794418..dfa3af20 100644 --- a/clearPaths.m +++ b/clearPaths.m @@ -7,16 +7,14 @@ function clearPaths() % OUTPUT % [none] % -% See also INITPATHS whose changes are undone by CLEARPATHS. +% See also initIFDIFF whose paths additions are undone by CLEARPATHS. -% Get absolute path to directory in which this file resides. -[filePath, ~, ~] = fileparts(mfilename('fullpath')); +% receive the required paths +ifdiffpaths = generateIFDIFFpaths(); + +% remove them from the search path +rmpath(ifdiffpaths); + -rmpath(filePath); -rmpath(genpath(fullfile(filePath, 'Tools'))); -rmpath(genpath(fullfile(filePath, 'Examples'))); -rmpath(genpath(fullfile(filePath, 'PreprocessedFunctions'))); -rmpath(fullfile(filePath, 'ComputeSensitivities')); -rmpath(genpath(fullfile(filePath, 'GenerateFixedBranchingFunctions'))); end diff --git a/docs/index.md b/docs/index.md index 65035053..8fc81963 100644 --- a/docs/index.md +++ b/docs/index.md @@ -122,7 +122,7 @@ Without any warning or error, the __naive approach with tight tolerances leads t With the switching point detection in IFDIFF, after a single call to a preparation routine, integration is just as simple as before: ```matlab - initPaths(); % initialise the paths for ifdiff (only once) + initIFDIFF(); % initialise IFDIFF (only once) tspan = [0 20]; x0 = [1;0]; p = 5.437; % set time horizon, initial value, parameter integrator = @ode45; % choose integrator odeoptions = odeset('AbsTol', 1e-5, 'RelTol', 1e-3); % set integrator options, here: low accuracy diff --git a/generateIFDIFFpaths.m b/generateIFDIFFpaths.m new file mode 100644 index 00000000..af3dd4a2 --- /dev/null +++ b/generateIFDIFFpaths.m @@ -0,0 +1,35 @@ +function [pathStr, pathList] = generateIFDIFFpaths() +% [pathStr, pathList] = generateIFDIFFpaths() +% +% Generates a character array with all paths for IFDIFF. +% The character array can be passed to addpath or rmpath +% +% INPUT: none +% +% OUTPUT: pathStr --> character array with paths needed/used by IFDIFF +% pathList --> cell array of sub-paths +% +% +% Andreas Sommer, Jul2025 +% code@andreas-sommer.eu +% + + +% get directory this file resides in +[selfdir, ~] = fileparts(mfilename('fullpath')); + +% list all IFDIFF pars +pathList = { selfdir ... % main directory of IFDIFF + , genpath(fullfile(selfdir, 'Tools')) ... + , genpath(fullfile(selfdir, 'Examples')) ... + , genpath(fullfile(selfdir, 'PreprocessedFunctions')) ... + , fullfile(selfdir, 'ComputeSensitivities') ... % no subdirs + , genpath(fullfile(selfdir, 'GenerateFixedBranchingFunctions')) ... + }; + +% combine them into a single path specification +pathStr = strjoin(pathList, pathsep()); + +% finito +end + diff --git a/initIFDIFF.m b/initIFDIFF.m new file mode 100644 index 00000000..bdd0f656 --- /dev/null +++ b/initIFDIFF.m @@ -0,0 +1,23 @@ +function initIFDIFF() +% initIFDIFF() +% +% Initializes IFDIFF, setting up paths. +% +% INPUT: none +% +% OUTPUT: none +% +% +% Andreas Sommer, Jul2025 +% code@andreas-sommer.eu +% + + +% receive the required paths +ifdiffpaths = generateIFDIFFpaths(); + +% add them to the search path at the beginning (search them first) +addpath(ifdiffpaths, '-begin'); + + +end % of function diff --git a/initPaths.m b/initPaths.m deleted file mode 100644 index ee806109..00000000 --- a/initPaths.m +++ /dev/null @@ -1,23 +0,0 @@ -function initPaths() -%INITPATHS Add directories required by IFDIFF to the MATLAB search path. -% You should always run this function before using IFDIFF (once per MATLAB session)! -% -% INPUT -% [none] -% -% OUTPUT -% [none] -% -% See also CLEARPATHS to undo the changes made by INITPATHS. - - -% Get absolute path to directory in which this file resides. -[filePath, ~, ~] = fileparts(mfilename('fullpath')); - -addpath(filePath); -addpath(genpath(fullfile(filePath, 'Tools'))); -addpath(genpath(fullfile(filePath, 'Examples'))); -addpath(genpath(fullfile(filePath, 'PreprocessedFunctions'))); -addpath(fullfile(filePath, 'ComputeSensitivities')); -addpath(genpath(fullfile(filePath, 'GenerateFixedBranchingFunctions'))); -end diff --git a/speedtracker/commands/RunBenchmarksCommand.m b/speedtracker/commands/RunBenchmarksCommand.m index 673d2c66..986ede7c 100644 --- a/speedtracker/commands/RunBenchmarksCommand.m +++ b/speedtracker/commands/RunBenchmarksCommand.m @@ -136,7 +136,7 @@ end % Main: run the benchmarks and return the results - initPaths(); + initIFDIFF(); try speedtrackerRunner = speedtrackerRunner.run(snapshots, benchmarks); catch error diff --git a/test/TestHelperFunctions.m b/test/TestHelperFunctions.m index de0b31e3..bf3134ba 100644 --- a/test/TestHelperFunctions.m +++ b/test/TestHelperFunctions.m @@ -5,11 +5,11 @@ function setPath(testCase) originalPath = path; testCase.addTeardown(@path, originalPath); - if ~exist('initPaths', 'file') + if ~exist('initIFDIFF', 'file') % We are probably in the test directory, so check parent directory cd('..'); end - initPaths(); + initIFDIFF(); % Get absolute path to directory in which this file resides. [filePath, ~, ~] = fileparts(mfilename('fullpath')); diff --git a/test/TestIgnore.m b/test/TestIgnore.m index bf1e0428..4890bff3 100644 --- a/test/TestIgnore.m +++ b/test/TestIgnore.m @@ -5,11 +5,11 @@ function setPath(testCase) originalPath = path; testCase.addTeardown(@path, originalPath); - if ~exist('initPaths', 'file') + if ~exist('initIFDIFF', 'file') % We are probably in the test directory, so check parent directory cd('..'); end - initPaths(); + initIFDIFF(); % Get absolute path to directory in which this file resides. [filePath, ~, ~] = fileparts(mfilename('fullpath')); diff --git a/test/TestPreprocessing.m b/test/TestPreprocessing.m index 3ee31da1..1adb6162 100644 --- a/test/TestPreprocessing.m +++ b/test/TestPreprocessing.m @@ -5,11 +5,11 @@ function setPath(testCase) originalPath = path; testCase.addTeardown(@path, originalPath); - if ~exist('initPaths', 'file') + if ~exist('initIFDIFF', 'file') % We are probably in the test directory, so check parent directory cd('..'); end - initPaths(); + initIFDIFF(); % Get absolute path to directory in which this file resides. [filePath, ~, ~] = fileparts(mfilename('fullpath')); diff --git a/test/TestSensitivities.m b/test/TestSensitivities.m index 04cbf195..82deec47 100644 --- a/test/TestSensitivities.m +++ b/test/TestSensitivities.m @@ -3,7 +3,7 @@ methods(TestClassSetup) function setup(~) cd(".."); - initPaths(); + initIFDIFF(); end end diff --git a/test/TestSolverCompatibility.m b/test/TestSolverCompatibility.m index 318d067d..ea3c5196 100644 --- a/test/TestSolverCompatibility.m +++ b/test/TestSolverCompatibility.m @@ -15,7 +15,7 @@ subway_tspan = [0 65]; subway_x0 = [0; 0; 0]; - % subway_p initialized later because we need to initPaths() before + % subway_p initialized later because we need to initIFDIFF() before subway_rhsFunction = 'newYorkCitySubwayModelRhs'; subway_odeoptions = odeset( 'AbsTol', 1e-20, 'RelTol', 1e-10); subway_xEnd = [2112.07361577; 0.00124794; 4124.77885608]; @@ -41,15 +41,15 @@ function setPath(testCase) originalPath = path; testCase.addTeardown(@path, originalPath); - if ~exist('initPaths', 'file') + if ~exist('initIFDIFF', 'file') % We are probably in the test directory, so check parent directory cd('..'); end - initPaths(); + initIFDIFF(); - % Get absolute path to directory in which initPaths resides. + % Get absolute path to directory in which initIFDIFF resides. % This should be the IFDIFF project root directory. - [filePath, ~, ~] = fileparts(which('initPaths')); + [filePath, ~, ~] = fileparts(which('initIFDIFF')); addpath(fullfile(filePath, 'Examples', 'subway')); end function setParameters(testCase) diff --git a/test/TestStateJumps.m b/test/TestStateJumps.m index 57d738fb..99762faf 100644 --- a/test/TestStateJumps.m +++ b/test/TestStateJumps.m @@ -10,15 +10,15 @@ function setup(testCase) originalPath = path; testCase.addTeardown(@path, originalPath); - if ~exist('initPaths', 'file') + if ~exist('initIFDIFF', 'file') % We are probably in the test directory, so check parent directory cd('..'); end - initPaths(); + initIFDIFF(); - % Get absolute path to directory in which initPaths resides. + % Get absolute path to directory in which initIFDIFF resides. % This should be the IFDIFF project root directory. - [filePath, ~, ~] = fileparts(which('initPaths')); + [filePath, ~, ~] = fileparts(which('initIFDIFF')); addpath(fullfile(filePath, 'test', 'TestStateJumps')); end end